uncancellable<T> method

  1. @override
Future<T> uncancellable<T>(
  1. FutureOr<T> action()
)
override

Runs action with the cancellation held back, and waits for it.

For a step that cannot be taken back: a payment on its way to the server, a write already on the wire. While action runs the job accepts no cancellation it may refuse, so neither an onCancel callback nor a child hears one, and the core waits for the body. Throws Cancelled up front if the job is already cancelled. Held, not refused: the job accepts the cancellation as the section closes and still ends cancelled, so what has to happen after the step anyway belongs inside the section.

final receipt = await ctx.uncancellable(() => api.pay(order));

Sections nest, and only the outermost lets a held cancellation through, even if action throws. A cancellation the job cannot refuse, such as a rule an engine adds, is not held: the job ends with its reason, and the held one never lands. Always await this call: the section belongs to the job, not to the future.

See Holding the cancellation back on the cancellation page, and Unregistering inside the action on the cleanup rules page for a hand-over and its disown in one section.

Implementation

@override
Future<T> uncancellable<T>(FutureOr<T> Function() action) async {
  // Before `throwIfFinished`: for work that outlived its job both
  // complaints are true, but the call from the fork is the one to fix.
  throwIfUnattended('run an uncancellable action');
  throwIfFinished('run an uncancellable action');
  check();
  enterUncancellable();
  try {
    return await action();
  } finally {
    leaveUncancellable();
  }
}