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.