unregisterAll method

Resolvable<Unit> unregisterAll({
  1. Option<TOnUnregisterCallback<Dependency<Object>>> onBeforeUnregister = const None(),
  2. Option<TOnUnregisterCallback<Dependency<Object>>> onAfterUnregister = const None(),
  3. Option<bool Function(Dependency<Object>)> condition = const None(),
})
inherited

Unregisters all dependencies, optionally with callbacks and conditions.

Implementation

Resolvable<Unit> unregisterAll({
  Option<TOnUnregisterCallback<Dependency>> onBeforeUnregister = const None(),
  Option<TOnUnregisterCallback<Dependency>> onAfterUnregister = const None(),
  Option<bool Function(Dependency)> condition = const None(),
}) {
  // NOTE: Built via Resolvable composition rather than `TaskSequencer`
  // because the sequencer's `seq.completion` only reflects tasks that were
  // chained synchronously — re-entrantly-queued tasks (which happen as
  // soon as ONE async step lands in the chain) update `_current` later,
  // and the caller's `await seq.completion.value` returns before they
  // drain. A direct Resolvable chain has none of that lag.
  final results = List.of(registry.reversedDependencies);
  Resolvable<Option> chain = Sync<Option>.okValue(const None());
  for (final dependency in results) {
    if (onBeforeUnregister case Some(value: final cb)) {
      chain = _nonEagerStep(
        chain,
        () => Resolvable<Option>(
          () => consec(
            awaitCallbackResult(
              cb(Ok(dependency)),
              logAndSwallowSyncErr: true,
              logContext: 'unregisterAll.onBeforeUnregister for '
                  '${dependency.runtimeType}',
            ),
            (_) => const None(),
          ),
        ),
      );
    }

    chain = _nonEagerStep(chain, () {
      if (condition case Some(value: final test)) {
        if (!test(dependency)) return syncNone();
      }
      // `dependency.typeEntity` is the raw registry key (e.g. `Sync<Foo>`),
      // not the inner T. `removeDependencyK` wraps its argument again, so
      // we must use `removeDependencyExact` here.
      registry
          .removeDependencyExact(
            dependency.typeEntity,
            groupEntity: dependency.metadata
                .map((e) => e.groupEntity)
                .unwrapOr(const DefaultEntity()),
          )
          .end();
      return switch (dependency.metadata) {
        Some(value: final metadata) => switch (metadata.onUnregister) {
            Some(value: final onUnregister) => dependency.value.then((e) {
                return Resolvable<Resolvable<Option>>(
                  () => consec(
                    awaitCallbackResult(
                      onUnregister(Ok(e)),
                      logAndSwallowSyncErr: true,
                      logContext: 'unregisterAll dep onUnregister for '
                          '${dependency.runtimeType}',
                    ),
                    (_) => syncNone(),
                  ),
                ).flatten();
              }).flatten(),
            None() => syncNone(),
          },
        None() => syncNone(),
      };
    });

    if (onAfterUnregister case Some(value: final cb)) {
      chain = _nonEagerStep(
        chain,
        () => Resolvable<Option>(
          () => consec(
            awaitCallbackResult(
              cb(Ok(dependency)),
              logAndSwallowSyncErr: true,
              logContext: 'unregisterAll.onAfterUnregister for '
                  '${dependency.runtimeType}',
            ),
            (_) => const None(),
          ),
        ),
      );
    }
  }
  return chain.toUnit();
}