///|
/// Serializes shard Identify calls per Discord's `max_concurrency` buckets.
/// One queue instance must be shared by every shard of a bot; cross-process
/// deployments can substitute their own implementation.
pub(open) trait IdentifyQueue {
/// Block (asynchronously) until this shard may send Identify.
async fn wait_for_identify(Self, shard_id : Int) -> Unit
}
///|
priv struct IdentifyBucket {
gate : @async.Semaphore
mut last_identify_ms : Int64
}
///|
/// In-process identify queue: `shard_id % max_concurrency` buckets, at most
/// one Identify per bucket per `spacing_ms` (default 5 seconds plus margin).
pub struct InMemoryQueue {
priv buckets : Array[IdentifyBucket]
priv spacing_ms : Int
}
///|
/// Create a queue with `max_concurrency` identify buckets (the value Discord
/// reports in `GET /gateway/bot`), spacing identifies within each bucket by
/// `spacing_ms`.
pub fn InMemoryQueue::InMemoryQueue(
max_concurrency? : Int = 1,
spacing_ms? : Int = 5250,
) -> InMemoryQueue {
let buckets = []
for _ in 0.. 0 {
@async.sleep(wait.to_int())
}
bucket.last_identify_ms = @clock.now_ms()
}