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.
The situation
Orders wait in one queue and work cells advertise themselves as ready in another. Matching them by hand does not scale, and matching them with a separate scheduler means a second source of truth.
The recipe
// 1. Anticipate supply.const free = await lt.escalations.searchByFacets({ role: 'cells', status: 'pending', available: true, facets: { state: 'ready' },});const capacity = free.data?.escalations.length ?? 0;
// 2. Claim that much demand, complete orders only, by priority.const orders = await lt.escalations.claimGroups({ query: { role: 'orders', available: true }, limit: capacity, sizeFacet: 'orderSize',});const groups = orders.data?.groups ?? [];
// 3. Lock the supply for the claimed demand, all or none.const cells = await lt.escalations.claimByFacets({ query: { role: 'cells', facets: { state: 'ready' } }, limit: groups.length, allOrNone: true,});
// 4. Pair, hand off, and resolve both sides.Each cell’s ready row is its advertisement; resolving it with a job hands the work over and wakes the cell’s own workflow.
The guarantee
Every step is a single statement over the shared escalation table: claims use FOR UPDATE SKIP LOCKED and group claims re-check completeness inside the lock. Several dispatchers can run side by side without double-claiming a row. Use resolveAllOrNone to deliver each cell its own job in one statement. See Faceted routing.
Related patterns
The queue as a market
Claim complete groups
A consumer claims whole orders, every unit at once, and only orders whose units have all arrived. No order is ever split across consumers.
The queue as a market
All-or-none claim
Claim exactly N rows or none. A dispatcher that needs four free stations either locks four or locks nothing and tries again.
The queue as a market
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 queue as a market
Pace by queue depth
An upstream step releases new work only while the downstream queue is below a set depth, reading the depth with one counted query.
