A machine is a resolver
Machines.loadLinestart({ machines })MachineGatewayconditionalAccumulatorA workflow parks a row and waits; a machine resolves it over MQTT exactly as a person would from the dashboard.
The situation
A route moves units through a cutting cell, a bonding cell and a person at the end of the line. The workflow should not care which stations are machines and which are people. Each hop is a wait, and each wait ends with a typed answer.
The recipe
Declare the line and let Long Tail run its gateway:
import { start, Machines } from '@hotmeshio/long-tail';
await start({ database: { connectionString: process.env.DATABASE_URL }, workers: [{ taskQueue: 'line', workflow: unitRoute }], machines: { lines: [Machines.loadLine('/etc/line.json')] },});{ "siteId": "site-1", "lineId": "line-1", "roles": { "exit": "inspector", "operator": "line-operator", "receivers": ["packer"] }, "machines": [ { "machineId": "cut-01", "process": "cut", "role": "cut-cell", "queueDepth": 4, "allowedSoftware": ["1.4.0"] } ]}Transports come from the environment (MACHINE_TRANSPORT=mqtt, MACHINE_MQTT_URL). A handoff row on cut-cell is dispatched to cut-01, claimed as the machine when it accepts, and resolved as the receiver once every unit arrives. A row on inspector resolves from the dashboard. The workflow can mix both in one route and never tell them apart.
The guarantee
The row, the wait and the result are the same for every resolver. Each machine is a bot account on its station role, so claimed_by and resolved_by name the machine. Rows are the authority: an event only tells the gateway which row to look at, and it reads the row back and acts on the stored role, status and metadata. See Machines.
Related patterns
The physical world
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 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.
Resolving from anywhere
One row, many resolvers
A person, a service, an operator, an agent or a machine can resolve the same row. The workflow receives the same typed answer either way.
The physical world
One leader per line
Every replica runs the same config; one holds a Postgres advisory lock per line and runs its gateway, and the rest take over on loss.
