Gateway constructor
- NyxxGateway client,
- GatewayBot gatewayBot,
- List<
Shard> shards, - int totalShards,
- List<
int> shardIds
Create a new Gateway.
Implementation
Gateway(this.client, this.gatewayBot, this.shards, this.totalShards, this.shardIds) : super.create() {
final logger = Logger('${client.options.loggerName}.Gateway');
// https://discord.com/developers/docs/topics/gateway#rate-limiting
const identifyDelay = Duration(seconds: 5);
final maxConcurrency = gatewayBot.sessionStartLimit.maxConcurrency;
var remainingIdentifyRequests = gatewayBot.sessionStartLimit.remaining;
// A mapping of rateLimitId (shard.id % maxConcurrency) to Futures that complete when the identify lock for that rate_limit_key is no longer used.
final identifyLocks = <int, Future<void>>{};
// Handle messages from the shards and start them according to their rate limit key.
for (final shard in shards) {
final rateLimitKey = shard.id % maxConcurrency;
// Delay the shard starting until it is (approximately) also ready to identify.
_startTimers.add(Timer(identifyDelay * (shard.id ~/ maxConcurrency), () {
logger.fine('Starting shard ${shard.id}');
shard.add(StartShard());
}));
shard.listen(
(event) {
_messagesController.add(event);
if (event is RequestingIdentify) {
final currentLock = identifyLocks[rateLimitKey] ?? Future.value();
identifyLocks[rateLimitKey] = currentLock.then((_) async {
if (_closing) return;
if (remainingIdentifyRequests < client.options.minimumSessionStarts * 5) {
logger.warning('$remainingIdentifyRequests session starts remaining');
}
if (remainingIdentifyRequests < client.options.minimumSessionStarts) {
await client.close();
throw OutOfRemainingSessionsError(gatewayBot);
}
remainingIdentifyRequests--;
shard.add(Identify());
return await Future.delayed(identifyDelay);
});
}
},
onError: _messagesController.addError,
onDone: () async {
if (_closing) {
return;
}
await client.close();
throw ShardDisconnectedError(shard);
},
cancelOnError: false,
);
}
}