isolate<Id, Value, T> static method

Future<_Communicator<Id, Value>> isolate<Id, Value, T>(
  1. ValueSetter<BackendArgument<T>> create,
  2. String isolateId, {
  3. required IsolatorData<T> isolatorData,
  4. ErrorHandler? errorHandler,
  5. bool isMessageBus = false,
})

Implementation

static Future<_Communicator<Id, Value>> isolate<Id, Value, T>(
  ValueSetter<BackendArgument<T>> create,
  String isolateId, {
  required IsolatorData<T> isolatorData,
  ErrorHandler? errorHandler,
  bool isMessageBus = false,
}) async {
  /// In flow, when the first Backend was not created and we try to create
  /// the second or N-th Backend in [Future.wait]
  if (_needToWaitMessageBusCreation(isolateId)) {
    await _waiter(isolateId);
  }

  /// create message bus on first isolator init
  if (!_isMessageBusCreated) {
    _isMessageBusCreated = true;
    await _createMessageBus();
  }
  final Completer<_Communicator<Id, Value>> completer = Completer();
  final ReceivePort receivePort = ReceivePort();
  final SendPort sendPort = receivePort.sendPort;
  final Stream<dynamic> receiveBroadcast = receivePort.asBroadcastStream();
  final StreamSubscription<dynamic> subscription = receiveBroadcast.listen((dynamic message) {
    if (message is Packet2<SendPort, SendPort?>) {
      if (message.value2 != null) {
        _messageBusFrontend!.addIsolateSendPort(Packet2(isolateId, message.value2!));
      }
      completer.complete(
        _Communicator<Id, Value>(
          Stream.castFrom<dynamic, _Message<Id, Value>>(receiveBroadcast),
          _Sender<Id, Value>(message.value),
        ),
      );
    }
  });
  _isolates[isolateId]?.kill();
  _isolates[isolateId] = await Isolate.spawn(
    create,
    BackendArgument<T>(
      sendPort,
      data: isolatorData.data,
      config: isolatorData.config.toJson(),
      messageBusSendPort: isMessageBus ? null : _messageBusBackendSendPort,
    ),
    debugName: isolateId,
    errorsAreFatal: false,
  );

  final Isolate isolate = _isolates[isolateId]!;
  final ReceivePort errorReceivePort = ReceivePort();

  /// messageAndStackTrace is a List<String> -> [message, stackStrace]
  errorReceivePort.listen((dynamic messageAndStackTrace) async {
    if (IsolatorConfig._instance.logEvents) {
      print('[ERROR] - [$isolateId] !!! The error was thrown in backend and got in Frontend');
    }
    if (errorHandler != null) {
      /// Use only error
      await errorHandler(messageAndStackTrace[0]);
    }
    throw messageAndStackTrace as Object;
  });
  isolate.addErrorListener(errorReceivePort.sendPort);
  final _Communicator<Id, Value> communicator = await completer.future;
  await subscription.cancel();
  return communicator;
}