TaskContext<S> is the single interface your handlers interact with. Every handler — onEvent, onAlarm, onError, and onClientGetState — receives a TaskContext<S> as its first argument, where S is the task’s state type.
Interface
State methods
Reads the current persisted state from Durable Object storage. Returns
null if no state has been saved yet (i.e., save() has never been called for this instance).recall() always returns the raw stored state regardless of any onClientGetState hook — the hook only runs for external getState() calls.Writes a new state value to Durable Object storage, replacing any previous value. The state is encoded using the task’s
state schema before being stored.Atomic read-modify-write. Reads the current state, applies
fn to it, then saves the result. If no state exists yet, fn receives the current state as null — handle this case in your transform function.Scheduling methods
Schedules an alarm relative to now. When the alarm fires,
Calling
onAlarm is called.Duration.Input accepts Effect Duration values and plain strings in natural language format:| Input | Meaning |
|---|---|
"5 seconds" | 5 seconds from now |
"1 minute" | 1 minute from now |
"2 hours" | 2 hours from now |
Duration.seconds(30) | 30 seconds from now |
{ millis: 500 } | 500 milliseconds from now |
scheduleIn() while an alarm is already pending replaces the existing alarm.Schedules an alarm at an absolute point in time. Accepts a
Date object or a Unix timestamp in milliseconds.Cancels the pending alarm, if any. If no alarm is scheduled this is a no-op.
Returns the scheduled alarm time as a Unix timestamp in milliseconds, or
null if no alarm is pending.Lifecycle methods
Deletes all persisted state and cancels any scheduled alarm, then terminates the current handler by failing with a
PurgeSignal. The task instance is effectively reset — the next send() call will start fresh.The return type Effect<never, PurgeSignal> means this effect never produces a value: it always terminates the handler. You do not need to return after yield* ctx.purge().PurgeSignal is an internal control-flow type. Do not catch it in your handlers — let it propagate naturally.Identity properties
The instance ID that was passed to
send() or getState(). Use this to correlate logs, emit events keyed to the instance, or build derived storage keys.The task name — the key used in the definitions record passed to
createTasks().onClientGetState and recall()
The onClientGetState hook and ctx.recall() serve different purposes:
ctx.recall() | onClientGetState | |
|---|---|---|
| Who calls it | Your handler code | External client via getState() |
| What it returns | Raw persisted state | Transformed state (what the client sees) |
| When it runs | During onEvent, onAlarm, onError | Only during external getState() requests |
onClientGetState to redact sensitive fields or compute derived values without affecting internal handler logic:
TaskError type
All TaskContext methods (except purge) can fail with TaskError:
TaskError represents failures in the underlying storage or alarm infrastructure (e.g., a Durable Object storage write failure). In normal operation you will not encounter it — use Effect.orDie or handle it explicitly if needed.