Handoff row
Each hop between stations is one row naming the units that move; it resolves with a receipt or a typed error code.
The situation
Units move from one machine to the next in groups. The sender releases them, the receiver scans them in, and sometimes only some arrive. The workflow needs to know exactly which, and decide what happens next.
The recipe
Park a handoff row on the receiver’s role. Its metadata says what moves:
import { conditionalAccumulator, Machines } from '@hotmeshio/long-tail';
const result = await conditionalAccumulator(`handoff-${routeKey}-s2-a1`, { role: 'bond-cell', type: Machines.ROW_TYPE.HANDOFF, description: 'U1, U2: cut-01 to bond-01', metadata: { siteId: 'site-1', lineId: 'line-1', units: [{ unitId: 'U1', carrierId: 'C-7' }, { unitId: 'U2', carrierId: 'C-7' }], jobId: `${routeKey}-bond`, senderJobId: `${routeKey}-cut`, fromMachine: 'cut-01', toMachine: 'bond-01', recipeId: 'RCP-BOND-A', recipeVersion: '2', process: 'bond', attempt: 1, }, accumulate: {}, timeout: '30m',});The gateway records each release and each arrival as items, and resolves the row once every unit is in: { received: true, receiver: 'bond-01', units: ['U1', 'U2'] }. Otherwise it resolves { received: false, errorCode, detail } with codes such as dispatch-refused, no-reply, sender-rejected or jam. Machines.handoffProgress(units, items) reads { released, arrived, missing }, and Machines.handoffDecisions(errorCode) offers the default retry, manual and scrap choices that fit.
The guarantee
When a sender finishes a unit, the release and the trace and lots facets land in the same statement, so the rows that used a lot are one containment query. A handoff that ends without every unit withdraws only the jobs none of whose units arrived. See Machines.
Related patterns
The physical world
A machine is a resolver
A workflow parks a row and waits; a machine resolves it over MQTT exactly as a person would from the dashboard.
The physical world
Command a machine with a row
Start, stop, pause or change over a machine by parking a row on its role; the machine's reply resolves the row as data.
The queue as a market
Lot traceability by containment
Stamp the lots each unit consumed onto its row as an array facet. Every row that used a lot is then one containment query.
The escalation boundary
Open container
One row is a container that fills over time. Items join one at a time and the workflow wakes once with the ordered collection.
