Continuations¶
Chain jobs together: a child job waits for its parent to complete successfully before executing.
Basic Usage¶
// 1. Enqueue the parent job
var parentJobId = await scheduler.EnqueueAsync<ProcessPaymentJob, PaymentInput>(
new PaymentInput(orderId, amount),
cancellationToken: ct);
// 2. Create the continuation — child waits for parent
await scheduler.ContinueWithAsync<SendConfirmationJob, ConfirmationInput>(
parentJobId: parentJobId,
input: new ConfirmationInput(orderId),
cancellationToken: ct);
The child job is stored as AwaitingContinuation. When the parent completes with Succeeded, the child transitions to Enqueued automatically.
Multiple Continuations¶
One parent can have multiple children. They all execute in parallel after the parent succeeds.
var parentJobId = await scheduler.EnqueueAsync<ImportDataJob, ImportInput>(input, cancellationToken: ct);
// These all run after the import succeeds
await scheduler.ContinueWithAsync<NotifyUsersJob>(parentJobId, cancellationToken: ct);
await scheduler.ContinueWithAsync<UpdateMetricsJob>(parentJobId, cancellationToken: ct);
await scheduler.ContinueWithAsync<CleanupTempFilesJob>(parentJobId, cancellationToken: ct);
Chaining¶
Chain multiple jobs in sequence:
var step1 = await scheduler.EnqueueAsync<FetchDataJob>(cancellationToken: ct);
var step2 = await scheduler.ContinueWithAsync<ProcessDataJob, DataInput>(step1, new DataInput(), cancellationToken: ct);
var step3 = await scheduler.ContinueWithAsync<PublishResultJob>(step2, cancellationToken: ct);
Execution order: FetchDataJob → ProcessDataJob → PublishResultJob
What Happens on Parent Failure?¶
If the parent job fails (exhausts retries → Failed), the child job remains in AwaitingContinuation indefinitely. It will never execute.
To handle this, either:
- Ensure the parent has sufficient retries — see Retry & Dead Letter
- Handle in dead-letter — manually enqueue the child in the parent's dead-letter handler if needed
Batch Acknowledgment¶
EnableBatchAcknowledgment = true releases continuations exactly like the default path: when a parent is acknowledged in a batch, every child waiting on it becomes runnable in the same operation. (Before v5.6 the batch path skipped this and children stayed in AwaitingContinuation.)
Trace Context¶
A continuation records the W3C traceparent that is current when you call ContinueWithAsync (the ambient Activity), not the parent job's execution span. When you enqueue the parent and create its continuations in the same request, both carry the same trace, so:
- OpenTelemetry traces show the chain under the trace of the request that created it
- You can follow the complete execution path in your APM tool
See OpenTelemetry for details.
When to Use Continuations¶
Use continuations when: - Job B depends on Job A completing successfully - You need a guaranteed execution order - You want trace correlation across the chain
Don't use continuations when: - Jobs are independent — enqueue them separately - You need Job B to run even if Job A fails — enqueue both independently - You need conditional branching — use a single job with internal branching logic
Next Steps¶
- Job Types — Define parent and child jobs
- Retry & Dead Letter — Ensure parent jobs don't fail
- Dashboard — Monitor job chains