Carry a claim across continueAsNew
A looping dispatcher keeps the orders it claimed but could not place yet, and carries them into its next run instead of releasing them.
The situation
A dispatcher runs in ticks. This tick it claimed five orders but found only three free cells. Releasing the other two would put them back behind newer work; holding them should give them first place next tick.
The recipe
import { Durable } from '@hotmeshio/hotmesh';import * as activities from '../activities/dispatch';
const { placeOrders, claimFreshOrders } = Durable.workflow.proxyActivities<typeof activities>({ activities });
export async function dispatcher(envelope: { data: { carried?: OrderGroup[] } }) { const carried = envelope.data.carried ?? [];
// 1. Place the carried backlog first: already claimed and aging. const first = carried.length ? await placeOrders(carried) : { unplaced: [] };
// 2. Claim fresh demand only once the backlog is placed. const unplaced = [...first.unplaced]; if (unplaced.length === 0) { const fresh = await claimFreshOrders(); unplaced.push(...(await placeOrders(fresh)).unplaced); }
await Durable.workflow.sleep('30 seconds'); await Durable.workflow.continueAsNew({ data: { carried: unplaced } });}The unplaced groups ride the next run’s input. Claim them with a durationMinutes that outlasts a tick, so the lock is still live when the next run places them.
The guarantee
The claim lives on the rows, not in the dispatcher’s memory, so it survives the restart that continueAsNew performs. If the dispatcher stops for good, the windows lapse and the rows return to the pool. The durable workflow is the coordinator; there is no distributed transaction. See Faceted routing.
Related patterns
The queue as a market
Two-sided dispatcher
Demand and supply are both rows. A dispatcher counts free supply, claims that much demand, locks the supply all-or-none, and pairs them.
Resolving from anywhere
A claim is a work lock
A claim names a holder and a window. While the window is live nobody else can resolve the row, and when it lapses the row is back in the pool.
The queue as a market
Availability is a query
A row is held only while its claim window is live. Availability is computed at read time, so no job has to flip a flag back.
