cancel method

Future<MissionOutcome> cancel(
  1. String missionId
)

Cancels a mission by id and returns the salvaged result (FR-003, FR-004, FR-005, FR-006).

Cancelling the leading mission completes the whole coalescing group with a cancelled_partial outcome; all subscribers (original + coalesced) receive that salvaged outcome. Per-subscriber policies (continue / escalate / serve-partials) are not yet wired up — see issue #388.

Implementation

Future<MissionOutcome> cancel(String missionId) async {
  final canonical = _missionIdToKey[missionId];
  if (canonical == null) {
    throw StateError('Mission not found: $missionId');
  }
  final group = _groups[canonical];
  if (group == null) {
    throw StateError('Mission not active: $missionId');
  }

  final token =
      group.cancelToken ??
      CancelToken(gracePeriod: _config.cancellationGracePeriod);

  // Salvage + complete the group synchronously BEFORE triggering
  // disposal. This ensures [submit] sees the salvaged outcome when
  // it resumes after the executor returns (the executor unblocks the
  // moment the disposal race starts, before this method runs its
  // post-disposal salvage).
  if (!group.isCompleted) {
    final salvagedOutcome = _salvager.salvage(group.mission);
    group.complete(salvagedOutcome);
  }

  // Trigger the grace-period disposal race. The executor's
  // `await cancelToken.onSettled` resolves when this completes.
  await runCancellation(token, group.handles);

  _cache.store(group.mission.key, group.mission.outcome!);
  return group.mission.outcome!;
}