Shard constructor

Shard(
  1. int id,
  2. Isolate isolate,
  3. Stream receiveStream,
  4. SendPort sendPort,
  5. NyxxGateway client
)

Create a new Shard.

Implementation

Shard(this.id, this.isolate, this.receiveStream, this.sendPort, this.client) {
  client.initialized.then((_) {
    final sendStream = client.options.plugins.fold(
      _sendController.stream,
      (previousValue, plugin) => plugin.interceptGatewayMessages(this, previousValue),
    );
    sendStream.listen(sendPort.send, cancelOnError: false, onDone: close);

    final transformedReceiveStream = client.options.plugins.fold(
      _rawReceiveController.stream,
      (previousValue, plugin) => plugin.interceptShardMessages(this, previousValue),
    );
    transformedReceiveStream.pipe(_transformedReceiveController);
  });

  receiveStream.cast<ShardMessage>().pipe(_rawReceiveController);

  final subscription = listen((message) {
    if (message is Sent) {
      logger
        ..fine('Sent payload: ${message.payload.opcode.name}')
        ..finer('Opcode: ${message.payload.opcode.value}, Data: ${message.payload.data}');
    } else if (message is ErrorReceived) {
      logger.warning('Error: ${message.error}', message.error, message.stackTrace);
    } else if (message is Disconnecting) {
      logger.info('Disconnecting: ${message.reason}');
    } else if (message is EventReceived) {
      final event = message.event;

      if (event is! RawDispatchEvent) {
        logger.finer('Receive: ${event.opcode.name}');

        switch (event) {
          case InvalidSessionEvent(:final isResumable):
            logger.finest('Resumable: $isResumable');
            if (isResumable) {
              logger.info('Reconnecting: invalid session');
            } else {
              logger.warning('Reconnecting: unresumable invalid session');
            }
          case HelloEvent(:final heartbeatInterval):
            logger.finest('Heartbeat Interval: $heartbeatInterval');
          case ReconnectEvent():
            logger.info('Reconnecting: reconnect requested');
          case HeartbeatAckEvent(:final latency):
            _latency = latency;
          default:
            break;
        }
      } else {
        logger
          ..fine('Receive event: ${event.name}')
          ..finer('Seq: ${event.seq}, Data: ${event.payload}');

        if (event.name == 'READY') {
          logger.info('Connected to Gateway');
        } else if (event.name == 'RESUMED') {
          logger.info('Reconnected to Gateway');
        }
      }
    } else if (message is RequestingIdentify) {
      logger.fine('Ready to identify');
    }
  });

  subscription.asFuture().then((value) {
    // Can happen if the shard closes unexpectedly.
    // Prevents further calls to close() from attempting to add events.
    if (!_doneCompleter.isCompleted) {
      _doneCompleter.complete(value);
    }
  });
}