Tasks
A task is a call carried the way an event is: over the same topology, with the same guarantees. Nobody waits for it. The caller hands it over and continues; the operation runs later, in whichever process of the target component is free to take it.
await context.remote.orders.archive({
query: { id: orderId },
task: true
}) The operation being called is an ordinary operation. Being run as a task is a property of the call, not of the operation, and the same operation can be called both ways.
§Why not just an event
Events and tasks are both handled without a waiting caller, and they fail and retry by the same rules. They differ in who decides that work should happen.
An event states a fact, and the publisher does not know who reacts. A task is an instruction: the caller knows exactly which operation it wants run, and with what request. Archiving an order because the customer asked is a task. Updating a report because an order was archived is a reaction to an event.
§What an accepted task can count on
It is kept before the call returns. The call that hands over a task answers only once the task is durably stored. A caller that stops the instant after has nothing left to do.
It outlives its circumstances. The task waits if the target component is down, being deployed, or not yet started. It does not expire, and it does not depend on the caller continuing to exist.
A failure does not lose it. An exception has the task tried again after a growing pause; one that keeps failing is kept for an operator, as described in Delivery.
In short: a task that was accepted will run.
§What it asks
The operation may run more than once. The guarantee is that the task runs, not that it runs once. The operation has to tolerate repetition, by the means described in Delivery and Transactional Inbox.
A refusal is final and silent. A returned error ends the task. There is no caller to receive it, so if a refusal matters, the operation records it in state.
There is no deadline. Nothing ends a task early. Work that may stop being worth doing has to be able to tell from the state it reads.
The caller learns nothing directly. The call that creates a task answers nothing about its result. If the caller needs the outcome, it gets it as it would get any other fact about another component: by observing state or by receiving an event.
§What cannot be a task
A task is taken by whichever process is free, at some later time. Two kinds of call cannot be made on those terms:
- a call addressed to one particular process, because the process that takes the task is not chosen by the caller;
- a call that carries a stream, because the stream exists only while its caller is writing it.
§Tasks and component boundaries
All tasks for a component are served in turn by its processes, whichever operation each is for. A backlog of slow tasks therefore delays the component’s other tasks.
Where that matters, it is a signal about boundaries. Work with a different rhythm and a different cost belongs in a component of its own, which is the same boundary that determines what is deployed and scaled together.