Results
What it is
Section titled “What it is”A result backend records each task’s TaskState
and return value under its id. AsyncResult is the
producer’s handle to read it. The backend is optional.
When to use it
Section titled “When to use it”- A request needs the answer of a short task (
await r.get(timeout: ...)). - A client polls for a long job: return the id, then read
app.resultFor(id).state. - You use
send(dedupeKey:),chord(), or revocation that must reach workers started later; all three keep state in the backend. - Rose’s “fire” should create a visible
pendingstate.
When not to use it
Section titled “When not to use it”- Pure side-effect tasks nobody reads back (emails, cache warms): omit
backend:and save a Redis write per state change.AsyncResultmembers then throwStateError. - Large outputs (files, big reports): store them in object storage or your database and return a key. Results are JSON strings in Redis.
- Business records: results expire (24 h by default on Redis). Persist anything you need to keep in your own database from inside the task.
How it works
Section titled “How it works”State changes over a task’s life:
send ──▶ pending (or scheduled with an ETA)worker ──▶ started ──▶ success | failure | retry ──▶ started ... | revokedEach change overwrites the stored snapshot. On Redis every write resets the key’s TTL to
resultTtl, so a result lives 24 hours after its last change. InMemoryResultBackend
keeps results until evicted by maxEntries or hidden by ttl.
AsyncResult.get() polls the backend every pollInterval (100 ms) until a terminal state
or timeout (30 s). It returns the value on success and throws TaskFailureException
on failure or revoked, ResultTimeoutException on timeout. A missing key reads as
pending, so a result that expired looks like a task that never ran: get then times out.
Values are stored as JSON. With Redis, a handler that returns a List<int> comes back as
List<dynamic>; type the TaskRef with JSON shapes (Map<String, dynamic>,
List<dynamic>) and convert on read.
Results are per id. For a workflow, the chain’s AsyncResult is its last step, a group
gives a GroupResult of members, and a chord gives the callback’s result.
Example
Section titled “Example”import 'package:gisila_queue/gisila_queue.dart';
// Start a long export and hand the id to the client.final r = await exportCsv.delay([reportId]);final jobId = r.id;
// Later, in another request (or another process):final job = app.resultFor<String>(jobId);switch (await job.state) { case TaskState.success: print('download: ${await job.get()}'); case TaskState.failure: case TaskState.revoked: print('failed'); default: print('still working');}