start static method

Future<Runtime> start(
  1. Module module, {
  2. ResolverBackend? backend,
  3. CleanupFailureObserver? cleanupFailureObserver,
  4. Iterable<RuntimeObserver> observers = const <RuntimeObserver>[],
  5. RuntimeObserverErrorHandler? observerErrorHandler,
})

Build a runtime, install constructor bindings, and acquire resources.

Implementation

static Future<Runtime> start(
  Module module, {
  ResolverBackend? backend,
  CleanupFailureObserver? cleanupFailureObserver,
  Iterable<RuntimeObserver> observers = const <RuntimeObserver>[],
  RuntimeObserverErrorHandler? observerErrorHandler,
}) async {
  final observerHub = _RuntimeObservers.create(
    observers,
    observerErrorHandler,
  );
  final resolver = backend ?? AutoInjectorBackend();
  final rootScope = Scope._();
  final rootObservation = observerHub == null
      ? null
      : _ExecutionObservation(
          observers: observerHub,
          executionId: 0,
          executionLabel: null,
          parentExecutionId: null,
          startedAt: DateTime.now(),
          initialMetadata: const <String, Object>{},
        );
  final context = _RuntimeContext(
    backend: resolver,
    scope: rootScope,
    cancellation: CancellationSignal._(),
    overrides: const <_ServiceIdentity, Object>{},
    locals: const <Object, Object>{},
    observation: rootObservation,
  );

  try {
    for (final binding in module) {
      if (!binding._isResource) {
        binding._register(resolver);
      }
    }

    resolver.commit();

    for (final binding in module) {
      if (binding._isResource) {
        await binding._startResource(context);
      }
    }

    await Future<void>.sync(resolver.activate);

    return Runtime._(context, cleanupFailureObserver, observerHub);
  } catch (error, stackTrace) {
    final outcome = ExitDefect<Object, Object>(error, stackTrace);
    Object? cleanupError;
    StackTrace? cleanupStackTrace;

    try {
      await rootScope._close(outcome);
    } catch (releaseError, releaseStack) {
      final diagnostic = CleanupFailureDiagnostic(
        outcome: outcome,
        error: _asScopeReleaseException(releaseError, releaseStack),
        executionId: 0,
      );
      _emitCleanupFailure(rootObservation, rootScope, diagnostic);
      await _notifyCleanupFailureBestEffort(
        cleanupFailureObserver,
        diagnostic,
      );
      cleanupError = releaseError;
      cleanupStackTrace = releaseStack;
    }

    try {
      await Future<void>.sync(resolver.close);
    } catch (backendError, backendStackTrace) {
      if (cleanupError == null) {
        cleanupError = backendError;
        cleanupStackTrace = backendStackTrace;
      } else {
        cleanupError = CompositeDefect(
          primary: cleanupError,
          primaryStackTrace: cleanupStackTrace!,
          secondary: backendError,
          secondaryStackTrace: backendStackTrace,
        );
        cleanupStackTrace = backendStackTrace;
      }
    }

    if (cleanupError != null) {
      Error.throwWithStackTrace(
        CompositeDefect(
          primary: error,
          primaryStackTrace: stackTrace,
          secondary: cleanupError,
          secondaryStackTrace: cleanupStackTrace!,
        ),
        stackTrace,
      );
    }

    Error.throwWithStackTrace(error, stackTrace);
  }
}