Schedule delayed tasks
You’ll schedule a reminder for later, make sure a stale reminder is skipped, and make sure double submissions only schedule one.
Prerequisites
Section titled “Prerequisites”- An app with a result backend (needed for
dedupeKey). - A worker running for the target queue.
1. Register the task
Section titled “1. Register the task”import 'package:gisila_queue/gisila_queue.dart';
final app = GisilaQueue.redis(namespace: 'shop');
final remind = app.task<void>('carts.remind', (ctx) async { final cartId = ctx.arg(0) as int; await sendCartReminder(cartId); return null;});2. Delay by a duration with countdown
Section titled “2. Delay by a duration with countdown”await remind.applyAsync(args: [cartId], countdown: const Duration(hours: 2));3. Or pin a time with eta
Section titled “3. Or pin a time with eta”final tomorrow9am = DateTime.now().add(const Duration(days: 1));await remind.applyAsync( args: [cartId], eta: DateTime(tomorrow9am.year, tomorrow9am.month, tomorrow9am.day, 9),);If both are given, countdown wins. The message is stored as scheduled until due. On
Redis a due message is promoted about once a second, so expect up to a second of extra
delay.
4. Skip it if it would run too late
Section titled “4. Skip it if it would run too late”await remind.applyAsync( args: [cartId], countdown: const Duration(hours: 2), expiresIn: const Duration(hours: 3),);If no worker picks it up before the expiry (workers were down, the queue was backed up),
the worker records it as revoked (expired at ...) and does not run it.
5. Schedule once, even if asked twice
Section titled “5. Schedule once, even if asked twice”dedupeKey is on app.send, which also
takes eta and expires as absolute times:
final r = await app.send<void>( 'carts.remind', args: [cartId], eta: DateTime.now().add(const Duration(hours: 2)), dedupeKey: 'cart-$cartId', dedupeFor: const Duration(hours: 3),);A second call with the same key inside dedupeFor enqueues nothing and returns the first
task’s AsyncResult (same id).
6. Cancel a scheduled task
Section titled “6. Cancel a scheduled task”await app.resultFor<void>(r.id).revoke();With a result backend, the revoke is stored, so the worker skips the task when it comes due even if it wasn’t running when you revoked.
Verify it works
Section titled “Verify it works”final first = await app.send<void>('carts.remind', args: [7], dedupeKey: 'cart-7');final second = await app.send<void>('carts.remind', args: [7], dedupeKey: 'cart-7');print(first.id == second.id); // trueprint(await first.state); // TaskState.pending (or scheduled with an eta)Next steps
Section titled “Next steps”- Schedule periodic tasks for recurring work.
- Producer API reference.