Skip to content

Deliver what arrived on timeout

The escalation boundarySDKconditionalbatchpartialOnTimeout

With partialOnTimeout, a batch that misses its deadline wakes with the items filled so far instead of false, so the workflow can act on them.

The situation

Twelve inspections are due by end of shift. If ten arrive, the workflow should ship those ten and reschedule two, not treat the whole order as failed.

The recipe

workflows/shift-inspections.ts
const result = await conditional<Record<string, InspectionV1> & { $trigger?: 'timeout' }>(signalId, {
role: 'inspection',
metadata: { orderId },
batch: partKeys,
timeout: '8h',
partialOnTimeout: true,
});
if (result === null) return cancelled(orderId);
if (result && result.$trigger === 'timeout') {
const done = partKeys.filter((k) => k in result);
return reschedule(orderId, partKeys.filter((k) => !done.includes(k)));
}

Without the flag, a batch timeout returns false and the partial items stay on the expired row for audit. With it, the timer resumes the wait with the filled items plus $trigger: 'timeout'.

The guarantee

The value the workflow receives is the value the expired row stores as resolver_payload. The flag is stored on the row as envelope.batch_partial_on_timeout at creation, so the behavior is fixed for the life of the wait. Existing batch waits are unchanged. See Batches and accumulators.