tadpole/gateway

Shard protocol decisions, pure logic: resume/reconnect/close-code tables, backoff, heartbeat miss tracking, sharding math. The shard actor in tadpole/gateway/shard applies these decisions on a live connection.

Internals: total functions over integers, so every decision the actor makes is testable without a socket. See also tadpole/gateway/shard for the actor, and tadpole/bot, whose disconnect logs quote close_code_name.

Types

pub type HeartbeatState {
  HeartbeatState(
    interval_ms: Int,
    last_sent_sequence: Int,
    missed_acks: Int,
  )
}

Constructors

  • HeartbeatState(
      interval_ms: Int,
      last_sent_sequence: Int,
      missed_acks: Int,
    )
pub type ShardState {
  Disconnected
  Connecting
  HelloReceived
  Identifying
  Resuming
  Connected
  ReconnectScheduled(next_attempt: Int)
}

Constructors

  • Disconnected
  • Connecting
  • HelloReceived
  • Identifying
  • Resuming
  • Connected
  • ReconnectScheduled(next_attempt: Int)

Values

pub fn ack_missed(
  state: HeartbeatState,
) -> #(HeartbeatState, Bool)

Returns whether the connection has crossed the zombie threshold.

pub fn ack_received(state: HeartbeatState) -> HeartbeatState
pub fn backoff_ms(attempts: Int) -> Int

Exponential with a cap: 1s, 2s, 4s, 8s … 60s. No jitter; Discord’s session start limit already handles identify contention.

pub fn can_resume(close_code: Int) -> Bool

Is a session resume safe after this close code? Codes that mean the session itself is bad (auth, invalid seq, disallowed intents) are not resumable; everything up to 4002 keeps the session.

pub fn close_code_name(code: Int) -> String
pub fn guild_shard_id(guild_id: Int, shard_count: Int) -> Int

The shard a guild belongs to.

pub const initial_backoff_ms: Int
pub const max_backoff_ms: Int
pub const max_missed_acks: Int
pub fn should_reconnect(close_code: Int) -> Bool

Should the shard reconnect after this close code at all? Mirrors the docs’ close code table. The stop set is every code the docs mark “Reconnect: false”: a bad token, a bad shard, a bad version, bad or disallowed intents. All config problems, and backing off forever without fixing any of them just grinds against the API. 4003 (not authenticated) reconnects: the docs mark it reconnect: true, and a fresh identify after a lost session is the documented fix.

Search Document