createActor method

Future<ActorRef> createActor(
  1. Uri path, {
  2. ActorFactory? factory,
  3. int? mailboxSize,
  4. bool sendInit = false,
})

Creates an actor at the given path.

The path for an actor must be unique. It is an error to create an actor with a path, an existing actor already is created with. If the given path ends with a slash (/), the path is extended by an UUID.

The given ActorFactory is called to create the actor for the given path. If no factory is provided, a global factory for the given path is used. If such factory does not exists, an error is thrown. This factory will also be used to recreate the actor in case of an error.

If sendInit is set to true, the const initMessage is sent to the actors mailbox before the returned future completes.

Implementation

Future<ActorRef> createActor(
  Uri path, {
  ActorFactory? factory,
  int? mailboxSize,
  bool sendInit = false,
}) async {
  path = path.validActorPath();
  _log.info('createActor < path=$path, factory=${factory != null}, mailboxSize=$mailboxSize, sendInit=$sendInit');

  if (!path.hasAbsolutePath) {
    throw ArgumentError.value(path, 'path', 'must be absolute');
  }
  if (path.pathSegments.last.isEmpty) {
    throw ArgumentError.value(path, 'path', 'must not end with a slash');
  }

  if (mailboxSize != null && mailboxSize <= 0) {
    throw ArgumentError.value(mailboxSize, 'mailboxSize', 'must be greater than zero');
  }

  /// check if the actor must be created externally
  if (!_isLocalPath(path)) {
    _log.fine('createActor | path is an external path');
    final externalCreate = _externalCreateActor.value;
    if (externalCreate != null) {
      final result = await externalCreate(
        path,
        mailboxSize ?? _defaultMailboxSize,
      );
      if (sendInit) {
        await result.send(initMsg);
      }
      _log.fine('createActor > $result');
      return result;
    }
    throw StateError('No external actor create function registered!');
  }

  _log.fine('createActor | path is a local path');
  final existing = _actorRefs[path.path];
  if (existing != null) {
    _log.fine('createActor | found existing actor');
    throw ArgumentError.value(path.path, 'path', 'path already in use');
  }

  // search for registered factory if no factory is provided
  final actorFactory = factory ?? _findFactory(path);
  if (actorFactory == null) {
    throw NoFactoryFound(path);
  }

  // create, store and return the actor ref
  final actorPath = _finalActorPath(path);
  _log.fine('createActor | final path is $actorPath');
  final actorRef = createActorRef(
    actorPath,
    mailboxSize ?? _defaultMailboxSize,
    await actorFactory(actorPath),
    actorFactory,
    ActorContext._(
      _name,
      _defaultMailboxSize,
      _missingHostHandling,
      _actorRefs,
      _factories,
      _externalCreateActor,
      _externalLookupActor,
      _externalLookupActors,
      _onActorAdded,
      _onActorRemoved,
      _metrics,
    ),
    _onMessageProcessed,
    _onActorStopped,
  );
  if (_isLocalPath(path)) {
    _actorRefs[actorPath.path] = actorRef;
    _onActorAdded.value?.call(actorRef.path);
  }

  if (sendInit) {
    await actorRef.send(initMsg);
  }

  _log.info('createActor > $actorRef');
  return actorRef;
}