pause method

  1. @override
Future<void> pause([
  1. Duration duration = Duration.zero
])
override

Waits for duration, or until the job is cancelled.

A checkpoint that takes time: it throws Cancelled up front if the job is already cancelled or its rules no longer hold, and a cancellation that arrives during the pause ends it there, with that Cancelled. Without a duration it comes back on the next turn of the event loop, as a timer of zero length does; a negative one counts as zero. Use it wherever a body would write Future.delayed, which is no checkpoint and cannot be cancelled.

while (true) {
  await ctx.join(sync);
  await ctx.pause(const Duration(minutes: 5));
}

Inside uncancellable a cancellation is held until the section ends, and the pause runs its whole length. During cleanup this throws a StateError, as abandonable does: a disposer that has to let time pass awaits a plain Future.delayed. Only a cancellation ends a pause early: one the body walked away from runs to its end, timer and all, when the job ends some other way.

See A pause of the job on the time page.

Implementation

@override
Future<void> pause([Duration duration = Duration.zero]) async {
  // Asked here, before `abandonable` asks: the message names the call made.
  throwIfFinished('pause');
  Timer? timer;
  try {
    // `abandonable` asks the checkpoint first, so on a job that is cancelled
    // already no timer is made.
    await abandonable<void>(() {
      final elapsed = Completer<void>();
      timer = Timer(duration, elapsed.complete);
      return elapsed.future;
    });
  } finally {
    // What `Future.delayed` under `abandonable` cannot do: the walk away from
    // the waiting takes the timer with it.
    timer?.cancel();
  }
}