Skip to content

A machine is a resolver

The physical worldMQTTSDKDashboardMachines.loadLinestart({ machines })MachineGatewayconditionalAccumulator

A 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:

start.ts
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')] },
});
/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.