pause method
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();
}
}