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 situation
An order of three parts should go to one kitting station together. Parts arrive at different times, and a station that grabs two of three is stuck holding a partial order.
The recipe
const kitted = await conditional<{ kitId: string }>(`kit-${orderId}-${partNo}`, { role: 'kitting', originId: orderId, metadata: { orderId, orderSize: 3 },});const { data } = await lt.escalations.claimGroups({ query: { role: 'kitting', available: true }, limit: 2, durationMinutes: 30, sizeFacet: 'orderSize',});// data.groups: whole orders, all units claimed by this stationltc esc claim-groups --role kitting --limit 2 --size-facet orderSizeUnits of one order share origin_id. The sizeFacet names the metadata key that holds the order’s unit count. limit is how many orders this consumer can take.
The guarantee
A group is eligible only when its member count equals its declared size. Completeness is re-checked inside the lock, and the claim is one transaction with FOR UPDATE SKIP LOCKED, so concurrent consumers never split a group or claim the same row. See Faceted routing.
Related patterns
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
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
Resolve a set, all or none
Each row in a set resolves with its own payload in one statement, waking each workflow with its own value, or nothing resolves.
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.
