@hotmeshio/long-tail 0.26.0 → 0.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -2
- package/build/api/settings.d.ts +4 -1
- package/build/api/settings.js +7 -1
- package/build/index.d.ts +4 -0
- package/build/index.js +35 -8
- package/build/lib/db/config-lock.d.ts +10 -0
- package/build/lib/db/config-lock.js +28 -0
- package/build/lib/db/schemas/041_machine_lines.sql +26 -0
- package/build/lib/events/browser-view.js +8 -2
- package/build/lib/events/nats.d.ts +11 -0
- package/build/lib/events/nats.js +33 -2
- package/build/lib/events/publish.d.ts +33 -0
- package/build/lib/events/publish.js +52 -1
- package/build/lib/machines/index.d.ts +1 -0
- package/build/lib/machines/index.js +1 -0
- package/build/lib/machines/line.d.ts +4 -1
- package/build/lib/machines/line.js +18 -1
- package/build/lib/machines/protocol/codec.d.ts +24 -0
- package/build/lib/machines/protocol/codec.js +10 -0
- package/build/lib/machines/protocol/constants.d.ts +1 -1
- package/build/lib/machines/protocol/constants.js +1 -1
- package/build/lib/machines/protocol/contract.js +12 -3
- package/build/lib/machines/site/edge-account.d.ts +11 -0
- package/build/lib/machines/site/edge-account.js +24 -0
- package/build/lib/machines/site/mosquitto-conf.d.ts +5 -4
- package/build/lib/machines/site/mosquitto-conf.js +31 -16
- package/build/lib/machines/site/site-conf.d.ts +16 -6
- package/build/lib/machines/site/site-conf.js +39 -13
- package/build/lib/machines/transport/callback-feed.d.ts +1 -0
- package/build/lib/machines/transport/callback-feed.js +4 -1
- package/build/lib/machines/transport/delivery.d.ts +3 -4
- package/build/lib/machines/transport/delivery.js +3 -8
- package/build/lib/machines/transport/index.d.ts +2 -0
- package/build/lib/machines/transport/index.js +2 -0
- package/build/lib/machines/transport/memory.d.ts +2 -0
- package/build/lib/machines/transport/memory.js +6 -0
- package/build/lib/machines/transport/mqtt-bus.d.ts +2 -0
- package/build/lib/machines/transport/mqtt-bus.js +4 -0
- package/build/lib/machines/transport/nats-bus.d.ts +8 -13
- package/build/lib/machines/transport/nats-bus.js +26 -43
- package/build/lib/machines/transport/nats-feed.d.ts +1 -0
- package/build/lib/machines/transport/nats-feed.js +6 -3
- package/build/lib/machines/transport/pubsub-feed.d.ts +18 -0
- package/build/lib/machines/transport/pubsub-feed.js +42 -0
- package/build/lib/machines/transport/stream-bus.d.ts +42 -0
- package/build/lib/machines/transport/stream-bus.js +61 -0
- package/build/lib/machines/transport/streams.d.ts +10 -14
- package/build/lib/machines/transport/streams.js +18 -61
- package/build/lib/messaging/config.d.ts +25 -0
- package/build/lib/messaging/config.js +55 -0
- package/build/lib/messaging/constants.d.ts +26 -0
- package/build/lib/messaging/constants.js +26 -0
- package/build/lib/messaging/index.d.ts +24 -0
- package/build/lib/messaging/index.js +65 -0
- package/build/lib/messaging/memory.d.ts +16 -0
- package/build/lib/messaging/memory.js +147 -0
- package/build/lib/messaging/nats/permissions.d.ts +13 -0
- package/build/lib/messaging/nats/permissions.js +22 -0
- package/build/lib/messaging/nats/provider.d.ts +30 -0
- package/build/lib/messaging/nats/provider.js +77 -0
- package/build/lib/messaging/nats/render-conf.d.ts +68 -0
- package/build/lib/messaging/nats/render-conf.js +58 -0
- package/build/lib/messaging/nats/streams.d.ts +26 -0
- package/build/lib/messaging/nats/streams.js +97 -0
- package/build/lib/messaging/subjects.d.ts +8 -0
- package/build/lib/messaging/subjects.js +25 -0
- package/build/modules/machines.d.ts +8 -0
- package/build/modules/machines.js +16 -0
- package/build/routes/index.js +2 -0
- package/build/routes/machines.d.ts +2 -0
- package/build/routes/machines.js +220 -0
- package/build/scripts/bambu-boat.d.ts +17 -0
- package/build/scripts/bambu-boat.js +134 -0
- package/build/scripts/bambu-print.d.ts +18 -0
- package/build/scripts/bambu-print.js +114 -0
- package/build/services/machines/commands.d.ts +5 -5
- package/build/services/machines/commands.js +3 -2
- package/build/services/machines/config.d.ts +8 -1
- package/build/services/machines/config.js +17 -7
- package/build/services/machines/contracts.d.ts +29 -2
- package/build/services/machines/contracts.js +12 -3
- package/build/services/machines/gateway/actions.d.ts +2 -1
- package/build/services/machines/gateway/admission.d.ts +15 -3
- package/build/services/machines/gateway/admission.js +29 -14
- package/build/services/machines/gateway/dispatcher.d.ts +19 -3
- package/build/services/machines/gateway/dispatcher.js +61 -13
- package/build/services/machines/gateway/executor.d.ts +18 -4
- package/build/services/machines/gateway/executor.js +99 -34
- package/build/services/machines/gateway/gateway.d.ts +22 -1
- package/build/services/machines/gateway/gateway.js +83 -28
- package/build/services/machines/gateway/index.d.ts +3 -0
- package/build/services/machines/gateway/index.js +3 -0
- package/build/services/machines/gateway/inspect.d.ts +17 -0
- package/build/services/machines/gateway/inspect.js +68 -0
- package/build/services/machines/gateway/lifecycle.d.ts +21 -0
- package/build/services/machines/gateway/lifecycle.js +89 -0
- package/build/services/machines/gateway/log.d.ts +8 -0
- package/build/services/machines/gateway/log.js +18 -0
- package/build/services/machines/gateway/pacing.d.ts +14 -0
- package/build/services/machines/gateway/pacing.js +27 -2
- package/build/services/machines/gateway/plan-escalation.js +21 -7
- package/build/services/machines/gateway/plan-machine.d.ts +5 -4
- package/build/services/machines/gateway/plan-machine.js +70 -19
- package/build/services/machines/gateway/project.d.ts +9 -0
- package/build/services/machines/gateway/project.js +55 -0
- package/build/services/machines/gateway/receipts.d.ts +3 -0
- package/build/services/machines/gateway/receipts.js +3 -1
- package/build/services/machines/gateway/reconcile.d.ts +2 -0
- package/build/services/machines/gateway/reconcile.js +16 -3
- package/build/services/machines/gateway/registration.js +1 -1
- package/build/services/machines/gateway/reply-waiter.d.ts +6 -3
- package/build/services/machines/gateway/reply-waiter.js +37 -16
- package/build/services/machines/gateway/state.d.ts +50 -4
- package/build/services/machines/gateway/state.js +77 -10
- package/build/services/machines/gateway/wire.d.ts +58 -0
- package/build/services/machines/gateway/wire.js +171 -0
- package/build/services/machines/index.d.ts +3 -0
- package/build/services/machines/index.js +2 -0
- package/build/services/machines/leadership.d.ts +17 -4
- package/build/services/machines/leadership.js +43 -18
- package/build/services/machines/line-index.d.ts +16 -0
- package/build/services/machines/line-index.js +39 -0
- package/build/services/machines/registry-sql.d.ts +31 -0
- package/build/services/machines/registry-sql.js +110 -0
- package/build/services/machines/registry-sync.d.ts +31 -0
- package/build/services/machines/registry-sync.js +81 -0
- package/build/services/machines/registry.d.ts +77 -0
- package/build/services/machines/registry.js +158 -0
- package/build/services/machines/rows.js +26 -2
- package/build/services/machines/select.d.ts +9 -2
- package/build/services/machines/select.js +20 -7
- package/build/services/machines/surface.d.ts +45 -5
- package/build/services/machines/surface.js +102 -16
- package/build/services/machines/testing/fake-long-tail.d.ts +1 -0
- package/build/services/machines/testing/fake-long-tail.js +6 -3
- package/build/start/adapters.js +11 -2
- package/build/start/apply-report.d.ts +1 -1
- package/build/start/apply-report.js +3 -25
- package/build/start/index.js +23 -5
- package/build/system/index.js +13 -0
- package/build/system/mcp-servers/admin/schemas.d.ts +22 -22
- package/build/system/mcp-servers/human-queue-schemas.d.ts +7 -7
- package/build/system/mcp-servers/machines-schemas.d.ts +35 -0
- package/build/system/mcp-servers/machines-schemas.js +35 -0
- package/build/system/mcp-servers/machines.d.ts +20 -0
- package/build/system/mcp-servers/machines.js +154 -0
- package/build/system/seed/tool-manifests-machines.d.ts +2 -0
- package/build/system/seed/tool-manifests-machines.js +88 -0
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/types/events.d.ts +6 -1
- package/build/types/index.d.ts +2 -0
- package/build/types/machines-view.d.ts +159 -0
- package/build/types/machines-view.js +7 -0
- package/build/types/machines.d.ts +6 -1
- package/build/types/messaging.d.ts +72 -0
- package/build/types/messaging.js +11 -0
- package/build/types/startup.d.ts +26 -1
- package/dashboard/dist/assets/{AdminDashboard-DlItqxFS.js → AdminDashboard-Bm7VG65H.js} +2 -2
- package/dashboard/dist/assets/{AdminDashboard-DlItqxFS.js.map → AdminDashboard-Bm7VG65H.js.map} +1 -1
- package/dashboard/dist/assets/{AgentConfigPage-BUmT4a7n.js → AgentConfigPage-aJF7Sdbc.js} +6 -6
- package/dashboard/dist/assets/{AgentConfigPage-BUmT4a7n.js.map → AgentConfigPage-aJF7Sdbc.js.map} +1 -1
- package/dashboard/dist/assets/{AgentDetailPage-Cww8rlBi.js → AgentDetailPage-GwwghhxT.js} +3 -3
- package/dashboard/dist/assets/{AgentDetailPage-Cww8rlBi.js.map → AgentDetailPage-GwwghhxT.js.map} +1 -1
- package/dashboard/dist/assets/AgentsPage-DVvCzZyg.js +2 -0
- package/dashboard/dist/assets/{AgentsPage-C9UuUKhr.js.map → AgentsPage-DVvCzZyg.js.map} +1 -1
- package/dashboard/dist/assets/AvailableEscalationsPage-Cxmcji_K.js +2 -0
- package/dashboard/dist/assets/{AvailableEscalationsPage-DrvfXz70.js.map → AvailableEscalationsPage-Cxmcji_K.js.map} +1 -1
- package/dashboard/dist/assets/{BotPicker-CDq9XRMp.js → BotPicker-CofRxk4L.js} +2 -2
- package/dashboard/dist/assets/{BotPicker-CDq9XRMp.js.map → BotPicker-CofRxk4L.js.map} +1 -1
- package/dashboard/dist/assets/{BulkAssignModal-jsvqtrEA.js → BulkAssignModal-BARWuz4L.js} +2 -2
- package/dashboard/dist/assets/{BulkAssignModal-jsvqtrEA.js.map → BulkAssignModal-BARWuz4L.js.map} +1 -1
- package/dashboard/dist/assets/{CapabilitiesPage-CSCrI6B1.js → CapabilitiesPage-BJAWVNEx.js} +2 -2
- package/dashboard/dist/assets/{CapabilitiesPage-CSCrI6B1.js.map → CapabilitiesPage-BJAWVNEx.js.map} +1 -1
- package/dashboard/dist/assets/{CollapsibleSection-uD9mn-CQ.js → CollapsibleSection-CtgoaG75.js} +2 -2
- package/dashboard/dist/assets/{CollapsibleSection-uD9mn-CQ.js.map → CollapsibleSection-CtgoaG75.js.map} +1 -1
- package/dashboard/dist/assets/{ConfirmDeleteModal-BRmx2hA4.js → ConfirmDeleteModal-BYXXBWs6.js} +2 -2
- package/dashboard/dist/assets/{ConfirmDeleteModal-BRmx2hA4.js.map → ConfirmDeleteModal-BYXXBWs6.js.map} +1 -1
- package/dashboard/dist/assets/{ConnectedAppsPage-DlMzE5a-.js → ConnectedAppsPage-D0JkzWa7.js} +2 -2
- package/dashboard/dist/assets/{ConnectedAppsPage-DlMzE5a-.js.map → ConnectedAppsPage-D0JkzWa7.js.map} +1 -1
- package/dashboard/dist/assets/{CountdownTimer-sRuM4eM5.js → CountdownTimer-BcFxdZYN.js} +2 -2
- package/dashboard/dist/assets/{CountdownTimer-sRuM4eM5.js.map → CountdownTimer-BcFxdZYN.js.map} +1 -1
- package/dashboard/dist/assets/{CredentialsPage-bLYydwqa.js → CredentialsPage-DPSY20rV.js} +2 -2
- package/dashboard/dist/assets/{CredentialsPage-bLYydwqa.js.map → CredentialsPage-DPSY20rV.js.map} +1 -1
- package/dashboard/dist/assets/{CronLabel-D_ATDL2N.js → CronLabel-Dg_Oew_Y.js} +2 -2
- package/dashboard/dist/assets/{CronLabel-D_ATDL2N.js.map → CronLabel-Dg_Oew_Y.js.map} +1 -1
- package/dashboard/dist/assets/{DropZone-u1JGfR9G.js → DropZone-Cl_Flb16.js} +2 -2
- package/dashboard/dist/assets/{DropZone-u1JGfR9G.js.map → DropZone-Cl_Flb16.js.map} +1 -1
- package/dashboard/dist/assets/{ElapsedCell-groSMfqB.js → ElapsedCell-Dm3G5fK2.js} +2 -2
- package/dashboard/dist/assets/{ElapsedCell-groSMfqB.js.map → ElapsedCell-Dm3G5fK2.js.map} +1 -1
- package/dashboard/dist/assets/{EntityTimelinePanel-D-F3_A9m.js → EntityTimelinePanel-CrEEP04e.js} +2 -2
- package/dashboard/dist/assets/{EntityTimelinePanel-D-F3_A9m.js.map → EntityTimelinePanel-CrEEP04e.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationListSchemaPage-Bad6Jrmr.js → EscalationListSchemaPage-wOInXcjs.js} +3 -3
- package/dashboard/dist/assets/{EscalationListSchemaPage-Bad6Jrmr.js.map → EscalationListSchemaPage-wOInXcjs.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationSchemaPage-BKi_npI9.js → EscalationSchemaPage-CrIj_g9d.js} +3 -3
- package/dashboard/dist/assets/{EscalationSchemaPage-BKi_npI9.js.map → EscalationSchemaPage-CrIj_g9d.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationTimeline-DQUUm3b1.js → EscalationTimeline-CeAsl5IT.js} +2 -2
- package/dashboard/dist/assets/{EscalationTimeline-DQUUm3b1.js.map → EscalationTimeline-CeAsl5IT.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationTitleSelect-3mhXh77a.js → EscalationTitleSelect-D8qpCYiy.js} +2 -2
- package/dashboard/dist/assets/{EscalationTitleSelect-3mhXh77a.js.map → EscalationTitleSelect-D8qpCYiy.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationsOverview-Qaov-uML.js → EscalationsOverview-CvaqVPsr.js} +2 -2
- package/dashboard/dist/assets/{EscalationsOverview-Qaov-uML.js.map → EscalationsOverview-CvaqVPsr.js.map} +1 -1
- package/dashboard/dist/assets/{EventTable-V4RF_n58.js → EventTable-Be0JuEl6.js} +2 -2
- package/dashboard/dist/assets/{EventTable-V4RF_n58.js.map → EventTable-Be0JuEl6.js.map} +1 -1
- package/dashboard/dist/assets/FilterBar-BVyAjIgv.js +2 -0
- package/dashboard/dist/assets/FilterBar-BVyAjIgv.js.map +1 -0
- package/dashboard/dist/assets/{GraphInvokePage-Djslhf96.js → GraphInvokePage-D_QigJeD.js} +2 -2
- package/dashboard/dist/assets/{GraphInvokePage-Djslhf96.js.map → GraphInvokePage-D_QigJeD.js.map} +1 -1
- package/dashboard/dist/assets/{HomePage-EjcNxlKx.js → HomePage-C1haeuNy.js} +2 -2
- package/dashboard/dist/assets/{HomePage-EjcNxlKx.js.map → HomePage-C1haeuNy.js.map} +1 -1
- package/dashboard/dist/assets/LinePage-CWD5pv1g.js +5 -0
- package/dashboard/dist/assets/LinePage-CWD5pv1g.js.map +1 -0
- package/dashboard/dist/assets/LinesPage-NqChsKcO.js +3 -0
- package/dashboard/dist/assets/LinesPage-NqChsKcO.js.map +1 -0
- package/dashboard/dist/assets/{ListToolbar-RrEAePOX.js → ListToolbar-BZCNrTh6.js} +2 -2
- package/dashboard/dist/assets/{ListToolbar-RrEAePOX.js.map → ListToolbar-BZCNrTh6.js.map} +1 -1
- package/dashboard/dist/assets/{McpOverview-8gqiL3Vj.js → McpOverview-yJTYnh1z.js} +2 -2
- package/dashboard/dist/assets/{McpOverview-8gqiL3Vj.js.map → McpOverview-yJTYnh1z.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryDetailPage-COyn6Ak5.js → McpQueryDetailPage-ChuLpJ4u.js} +3 -3
- package/dashboard/dist/assets/{McpQueryDetailPage-COyn6Ak5.js.map → McpQueryDetailPage-ChuLpJ4u.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryPage-Dj6Qj72w.js → McpQueryPage-9S-v9soF.js} +2 -2
- package/dashboard/dist/assets/{McpQueryPage-Dj6Qj72w.js.map → McpQueryPage-9S-v9soF.js.map} +1 -1
- package/dashboard/dist/assets/McpRunDetailPage-BhrcfxD5.js +2 -0
- package/dashboard/dist/assets/{McpRunDetailPage-80fQn9iX.js.map → McpRunDetailPage-BhrcfxD5.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunsPage-DaSsI-EM.js → McpRunsPage-C5_i8_Zx.js} +2 -2
- package/dashboard/dist/assets/{McpRunsPage-DaSsI-EM.js.map → McpRunsPage-C5_i8_Zx.js.map} +1 -1
- package/dashboard/dist/assets/{NamespacePill-C5epAgq6.js → NamespacePill-OTZD2hzt.js} +2 -2
- package/dashboard/dist/assets/{NamespacePill-C5epAgq6.js.map → NamespacePill-OTZD2hzt.js.map} +1 -1
- package/dashboard/dist/assets/{OperationsPage-BSu1o2gB.js → OperationsPage-C03CeU5P.js} +2 -2
- package/dashboard/dist/assets/{OperationsPage-BSu1o2gB.js.map → OperationsPage-C03CeU5P.js.map} +1 -1
- package/dashboard/dist/assets/{OperatorDashboard-HFI4WGIV.js → OperatorDashboard-BzC134Jt.js} +2 -2
- package/dashboard/dist/assets/{OperatorDashboard-HFI4WGIV.js.map → OperatorDashboard-BzC134Jt.js.map} +1 -1
- package/dashboard/dist/assets/{PageHeader-BSWIspNB.js → PageHeader-Hx8APPwE.js} +2 -2
- package/dashboard/dist/assets/{PageHeader-BSWIspNB.js.map → PageHeader-Hx8APPwE.js.map} +1 -1
- package/dashboard/dist/assets/{PageHeaderWithStats-DDjopQ-k.js → PageHeaderWithStats-BEQYYBJv.js} +2 -2
- package/dashboard/dist/assets/{PageHeaderWithStats-DDjopQ-k.js.map → PageHeaderWithStats-BEQYYBJv.js.map} +1 -1
- package/dashboard/dist/assets/{PersonaDetailPage-D0qlBuGi.js → PersonaDetailPage-D0mY9L6j.js} +2 -2
- package/dashboard/dist/assets/{PersonaDetailPage-D0qlBuGi.js.map → PersonaDetailPage-D0mY9L6j.js.map} +1 -1
- package/dashboard/dist/assets/{PersonasPage-BJClu-5H.js → PersonasPage-FFlm5Eug.js} +2 -2
- package/dashboard/dist/assets/{PersonasPage-BJClu-5H.js.map → PersonasPage-FFlm5Eug.js.map} +1 -1
- package/dashboard/dist/assets/{PortalPage-CucNZn_w.js → PortalPage-Cpc25uO-.js} +2 -2
- package/dashboard/dist/assets/{PortalPage-CucNZn_w.js.map → PortalPage-Cpc25uO-.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessDetailPage-B9wMw0RV.js → ProcessDetailPage-Di2J7KwY.js} +2 -2
- package/dashboard/dist/assets/{ProcessDetailPage-B9wMw0RV.js.map → ProcessDetailPage-Di2J7KwY.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessesListPage-B6k4RpmR.js → ProcessesListPage-BEXwU3Z0.js} +2 -2
- package/dashboard/dist/assets/{ProcessesListPage-B6k4RpmR.js.map → ProcessesListPage-BEXwU3Z0.js.map} +1 -1
- package/dashboard/dist/assets/{ResolverForm-ZVufJ4G-.js → ResolverForm-2ks-3jXC.js} +6 -6
- package/dashboard/dist/assets/{ResolverForm-ZVufJ4G-.js.map → ResolverForm-2ks-3jXC.js.map} +1 -1
- package/dashboard/dist/assets/{RoleDetailPage-CTbq0mz4.js → RoleDetailPage-DqoOk0xc.js} +3 -3
- package/dashboard/dist/assets/{RoleDetailPage-CTbq0mz4.js.map → RoleDetailPage-DqoOk0xc.js.map} +1 -1
- package/dashboard/dist/assets/{RolePill-CoETDpjF.js → RolePill-R5_ctGFy.js} +2 -2
- package/dashboard/dist/assets/{RolePill-CoETDpjF.js.map → RolePill-R5_ctGFy.js.map} +1 -1
- package/dashboard/dist/assets/{RolesPage-DBKxeam4.js → RolesPage-CPmo8Srr.js} +2 -2
- package/dashboard/dist/assets/{RolesPage-DBKxeam4.js.map → RolesPage-CPmo8Srr.js.map} +1 -1
- package/dashboard/dist/assets/{RosterWidget-BkLAwEYB.js → RosterWidget-D2yovCKw.js} +2 -2
- package/dashboard/dist/assets/{RosterWidget-BkLAwEYB.js.map → RosterWidget-D2yovCKw.js.map} +1 -1
- package/dashboard/dist/assets/{RunAsSelector-D2DC4iDf.js → RunAsSelector-CMv96On6.js} +2 -2
- package/dashboard/dist/assets/{RunAsSelector-D2DC4iDf.js.map → RunAsSelector-CMv96On6.js.map} +1 -1
- package/dashboard/dist/assets/{ScanCodesPage-BlKleaT0.js → ScanCodesPage-CA6cTT-M.js} +2 -2
- package/dashboard/dist/assets/{ScanCodesPage-BlKleaT0.js.map → ScanCodesPage-CA6cTT-M.js.map} +1 -1
- package/dashboard/dist/assets/{ScanSchemeDetailPage-CTW6gofi.js → ScanSchemeDetailPage-DnctN5-H.js} +2 -2
- package/dashboard/dist/assets/{ScanSchemeDetailPage-CTW6gofi.js.map → ScanSchemeDetailPage-DnctN5-H.js.map} +1 -1
- package/dashboard/dist/assets/{ScanStationPage-DPRjSPyT.js → ScanStationPage-Bk8RwkKL.js} +2 -2
- package/dashboard/dist/assets/{ScanStationPage-DPRjSPyT.js.map → ScanStationPage-Bk8RwkKL.js.map} +1 -1
- package/dashboard/dist/assets/{ScopeBadge-CGsTtqFr.js → ScopeBadge-BXZ084nD.js} +2 -2
- package/dashboard/dist/assets/{ScopeBadge-CGsTtqFr.js.map → ScopeBadge-BXZ084nD.js.map} +1 -1
- package/dashboard/dist/assets/{StickyPagination-CkmX3-Gu.js → StickyPagination-B0FSuUgs.js} +2 -2
- package/dashboard/dist/assets/{StickyPagination-CkmX3-Gu.js.map → StickyPagination-B0FSuUgs.js.map} +1 -1
- package/dashboard/dist/assets/{StreamMessageDetail-Xm_n510s.js → StreamMessageDetail-BwZEvMpP.js} +2 -2
- package/dashboard/dist/assets/{StreamMessageDetail-Xm_n510s.js.map → StreamMessageDetail-BwZEvMpP.js.map} +1 -1
- package/dashboard/dist/assets/{SwimlaneTimeline-De48aJan.js → SwimlaneTimeline-BDVQEaMw.js} +2 -2
- package/dashboard/dist/assets/{SwimlaneTimeline-De48aJan.js.map → SwimlaneTimeline-BDVQEaMw.js.map} +1 -1
- package/dashboard/dist/assets/{TagInput-S7UuVT_M.js → TagInput-DjPUDp2M.js} +2 -2
- package/dashboard/dist/assets/{TagInput-S7UuVT_M.js.map → TagInput-DjPUDp2M.js.map} +1 -1
- package/dashboard/dist/assets/{TaskDetailPage-HycMx3O9.js → TaskDetailPage-BOlv3iGB.js} +2 -2
- package/dashboard/dist/assets/{TaskDetailPage-HycMx3O9.js.map → TaskDetailPage-BOlv3iGB.js.map} +1 -1
- package/dashboard/dist/assets/{TaskQueuePill-BlHNpYiZ.js → TaskQueuePill-D-4Ynf3K.js} +2 -2
- package/dashboard/dist/assets/{TaskQueuePill-BlHNpYiZ.js.map → TaskQueuePill-D-4Ynf3K.js.map} +1 -1
- package/dashboard/dist/assets/{TasksListPage-OIcFFp1C.js → TasksListPage-e2teY0bD.js} +2 -2
- package/dashboard/dist/assets/{TasksListPage-OIcFFp1C.js.map → TasksListPage-e2teY0bD.js.map} +1 -1
- package/dashboard/dist/assets/{TimeAgo-OTC_55oZ.js → TimeAgo-Cvkpf_b3.js} +2 -2
- package/dashboard/dist/assets/{TimeAgo-OTC_55oZ.js.map → TimeAgo-Cvkpf_b3.js.map} +1 -1
- package/dashboard/dist/assets/{TimestampCell-CAwIj_AI.js → TimestampCell-B3btAV0N.js} +2 -2
- package/dashboard/dist/assets/{TimestampCell-CAwIj_AI.js.map → TimestampCell-B3btAV0N.js.map} +1 -1
- package/dashboard/dist/assets/{ToolPill-D40uLM_v.js → ToolPill-GsKQ80CO.js} +2 -2
- package/dashboard/dist/assets/{ToolPill-D40uLM_v.js.map → ToolPill-GsKQ80CO.js.map} +1 -1
- package/dashboard/dist/assets/{ToolTestPanel-8Vf6pfw4.js → ToolTestPanel-B03nebR7.js} +2 -2
- package/dashboard/dist/assets/{ToolTestPanel-8Vf6pfw4.js.map → ToolTestPanel-B03nebR7.js.map} +1 -1
- package/dashboard/dist/assets/{TopicDetailPage-iZW8rK9L.js → TopicDetailPage-DBRWne3O.js} +3 -3
- package/dashboard/dist/assets/{TopicDetailPage-iZW8rK9L.js.map → TopicDetailPage-DBRWne3O.js.map} +1 -1
- package/dashboard/dist/assets/{TopicsPage-CqiEcj-W.js → TopicsPage-CVe2M9HD.js} +2 -2
- package/dashboard/dist/assets/{TopicsPage-CqiEcj-W.js.map → TopicsPage-CVe2M9HD.js.map} +1 -1
- package/dashboard/dist/assets/{UserName-DQFjuoib.js → UserName-B_q_qp6V.js} +2 -2
- package/dashboard/dist/assets/{UserName-DQFjuoib.js.map → UserName-B_q_qp6V.js.map} +1 -1
- package/dashboard/dist/assets/WorkflowExecutionPage-Bh_dr9tM.js +2 -0
- package/dashboard/dist/assets/{WorkflowExecutionPage-Di08wCbs.js.map → WorkflowExecutionPage-Bh_dr9tM.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowPill-DJLcK_CM.js → WorkflowPill-D7244fKp.js} +2 -2
- package/dashboard/dist/assets/{WorkflowPill-DJLcK_CM.js.map → WorkflowPill-D7244fKp.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsDashboard-Bb8HlrTJ.js → WorkflowsDashboard-DA6Mj7qH.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsDashboard-Bb8HlrTJ.js.map → WorkflowsDashboard-DA6Mj7qH.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsOverview-Dta1kurk.js → WorkflowsOverview-B1kBLj-a.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsOverview-Dta1kurk.js.map → WorkflowsOverview-B1kBLj-a.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-CfAajg68.js → YamlWorkflowDetailPage-6GJM8QIX.js} +8 -8
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-CfAajg68.js.map → YamlWorkflowDetailPage-6GJM8QIX.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowsPage-CQFUzT4t.js → YamlWorkflowsPage-Bu811C7f.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowsPage-CQFUzT4t.js.map → YamlWorkflowsPage-Bu811C7f.js.map} +1 -1
- package/dashboard/dist/assets/{agents-PuftRTB2.js → agents-MPk_GnYz.js} +2 -2
- package/dashboard/dist/assets/{agents-PuftRTB2.js.map → agents-MPk_GnYz.js.map} +1 -1
- package/dashboard/dist/assets/{bots-BmEiPAWY.js → bots-2RihE2Tc.js} +2 -2
- package/dashboard/dist/assets/{bots-BmEiPAWY.js.map → bots-2RihE2Tc.js.map} +1 -1
- package/dashboard/dist/assets/{capabilities-CRii4Soa.js → capabilities-CC4iwJ1P.js} +2 -2
- package/dashboard/dist/assets/{capabilities-CRii4Soa.js.map → capabilities-CC4iwJ1P.js.map} +1 -1
- package/dashboard/dist/assets/{controlplane-DO_czaYo.js → controlplane-Bmkic8BH.js} +2 -2
- package/dashboard/dist/assets/{controlplane-DO_czaYo.js.map → controlplane-Bmkic8BH.js.map} +1 -1
- package/dashboard/dist/assets/{escalation-columns-CzCquCPh.js → escalation-columns-B0lhUUrQ.js} +2 -2
- package/dashboard/dist/assets/{escalation-columns-CzCquCPh.js.map → escalation-columns-B0lhUUrQ.js.map} +1 -1
- package/dashboard/dist/assets/{escalation-items-Cy0ZgJqV.js → escalation-items-7WFpPo46.js} +2 -2
- package/dashboard/dist/assets/{escalation-items-Cy0ZgJqV.js.map → escalation-items-7WFpPo46.js.map} +1 -1
- package/dashboard/dist/assets/index-B9uv-euR.css +1 -0
- package/dashboard/dist/assets/{index-DhSCCpqM.js → index-B_XV1rwu.js} +2 -2
- package/dashboard/dist/assets/{index-DhSCCpqM.js.map → index-B_XV1rwu.js.map} +1 -1
- package/dashboard/dist/assets/{index-Cx8xb-oU.js → index-C2CLfGwL.js} +2 -2
- package/dashboard/dist/assets/{index-Cx8xb-oU.js.map → index-C2CLfGwL.js.map} +1 -1
- package/dashboard/dist/assets/{index-Cga5IW3D.js → index-C3AeFihz.js} +2 -2
- package/dashboard/dist/assets/{index-Cga5IW3D.js.map → index-C3AeFihz.js.map} +1 -1
- package/dashboard/dist/assets/{index-DiaRlFYI.js → index-CBri8fYM.js} +2 -2
- package/dashboard/dist/assets/{index-DiaRlFYI.js.map → index-CBri8fYM.js.map} +1 -1
- package/dashboard/dist/assets/{index-CL_1VpGb.js → index-CRWsB7ZC.js} +2 -2
- package/dashboard/dist/assets/{index-CL_1VpGb.js.map → index-CRWsB7ZC.js.map} +1 -1
- package/dashboard/dist/assets/{index-XntldBd0.js → index-CTOv3G7a.js} +2 -2
- package/dashboard/dist/assets/{index-XntldBd0.js.map → index-CTOv3G7a.js.map} +1 -1
- package/dashboard/dist/assets/{index-CfP2nKRc.js → index-CcArGkzI.js} +3 -3
- package/dashboard/dist/assets/{index-CfP2nKRc.js.map → index-CcArGkzI.js.map} +1 -1
- package/dashboard/dist/assets/{index-Dz6R8-Dw.js → index-CkMHS-hG.js} +25 -25
- package/dashboard/dist/assets/index-CkMHS-hG.js.map +1 -0
- package/dashboard/dist/assets/index-CmsmwCyv.js +2 -0
- package/dashboard/dist/assets/{index-4YaDUcKd.js.map → index-CmsmwCyv.js.map} +1 -1
- package/dashboard/dist/assets/{index-2SM2_onB.js → index-CvJsvqIc.js} +2 -2
- package/dashboard/dist/assets/{index-2SM2_onB.js.map → index-CvJsvqIc.js.map} +1 -1
- package/dashboard/dist/assets/{index-Rwqrflm-.js → index-D-ilRyfy.js} +2 -2
- package/dashboard/dist/assets/{index-Rwqrflm-.js.map → index-D-ilRyfy.js.map} +1 -1
- package/dashboard/dist/assets/{index-CZ7A3AcD.js → index-DSUtfDXx.js} +2 -2
- package/dashboard/dist/assets/{index-CZ7A3AcD.js.map → index-DSUtfDXx.js.map} +1 -1
- package/dashboard/dist/assets/{index-jL2K6us4.js → index-Da6ycKyf.js} +2 -2
- package/dashboard/dist/assets/{index-jL2K6us4.js.map → index-Da6ycKyf.js.map} +1 -1
- package/dashboard/dist/assets/{knowledge-CeUqGPuo.js → knowledge-Bpbg20DC.js} +2 -2
- package/dashboard/dist/assets/{knowledge-CeUqGPuo.js.map → knowledge-Bpbg20DC.js.map} +1 -1
- package/dashboard/dist/assets/machines-BqOZZU-3.js +2 -0
- package/dashboard/dist/assets/machines-BqOZZU-3.js.map +1 -0
- package/dashboard/dist/assets/{mcp-Cx96NTeD.js → mcp-CmcUXYce.js} +2 -2
- package/dashboard/dist/assets/{mcp-Cx96NTeD.js.map → mcp-CmcUXYce.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-query-XAzWl0gm.js → mcp-query-C8buQxN9.js} +2 -2
- package/dashboard/dist/assets/{mcp-query-XAzWl0gm.js.map → mcp-query-C8buQxN9.js.map} +1 -1
- package/dashboard/dist/assets/{personas--4kjwyOw.js → personas-C2n5oDmY.js} +2 -2
- package/dashboard/dist/assets/{personas--4kjwyOw.js.map → personas-C2n5oDmY.js.map} +1 -1
- package/dashboard/dist/assets/{pipelines-PgkwvG7f.js → pipelines-RKpSkFz7.js} +2 -2
- package/dashboard/dist/assets/{pipelines-PgkwvG7f.js.map → pipelines-RKpSkFz7.js.map} +1 -1
- package/dashboard/dist/assets/{tasks-CcYxdBa3.js → tasks-Dab4hExW.js} +2 -2
- package/dashboard/dist/assets/{tasks-CcYxdBa3.js.map → tasks-Dab4hExW.js.map} +1 -1
- package/dashboard/dist/assets/{topics-_lik7cNY.js → topics-FTMNP7r3.js} +2 -2
- package/dashboard/dist/assets/{topics-_lik7cNY.js.map → topics-FTMNP7r3.js.map} +1 -1
- package/dashboard/dist/assets/{useDebouncedValue-Bm_AoxVx.js → useDebouncedValue-B_1u1YIk.js} +2 -2
- package/dashboard/dist/assets/{useDebouncedValue-Bm_AoxVx.js.map → useDebouncedValue-B_1u1YIk.js.map} +1 -1
- package/dashboard/dist/assets/{useNamespace-DgXXKdx5.js → useNamespace-HUeAI7Qb.js} +2 -2
- package/dashboard/dist/assets/{useNamespace-DgXXKdx5.js.map → useNamespace-HUeAI7Qb.js.map} +1 -1
- package/dashboard/dist/assets/{useYamlActivityEvents-Dj2qtGSd.js → useYamlActivityEvents-Cax54qHH.js} +2 -2
- package/dashboard/dist/assets/{useYamlActivityEvents-Dj2qtGSd.js.map → useYamlActivityEvents-Cax54qHH.js.map} +1 -1
- package/dashboard/dist/assets/{validate-FlXCBBT6.js → validate-DxOaV7QS.js} +2 -2
- package/dashboard/dist/assets/{validate-FlXCBBT6.js.map → validate-DxOaV7QS.js.map} +1 -1
- package/dashboard/dist/assets/{vendor-icons-DUYcKTjP.js → vendor-icons-fxBvvHBi.js} +187 -182
- package/dashboard/dist/assets/vendor-icons-fxBvvHBi.js.map +1 -0
- package/dashboard/dist/assets/{yaml-workflows-B0_JxRYQ.js → yaml-workflows-BgY1XHJx.js} +2 -2
- package/dashboard/dist/assets/{yaml-workflows-B0_JxRYQ.js.map → yaml-workflows-BgY1XHJx.js.map} +1 -1
- package/dashboard/dist/index.html +3 -3
- package/docs/architecture.md +1 -0
- package/docs/code-owned-configuration.md +6 -0
- package/docs/dashboard.md +1 -0
- package/docs/events.md +83 -4
- package/docs/machines.md +129 -23
- package/docs/mcp.md +19 -0
- package/package.json +3 -1
- package/build/lib/machines/transport/nats-durable.d.ts +0 -11
- package/build/lib/machines/transport/nats-durable.js +0 -28
- package/dashboard/dist/assets/AgentsPage-C9UuUKhr.js +0 -2
- package/dashboard/dist/assets/AvailableEscalationsPage-DrvfXz70.js +0 -2
- package/dashboard/dist/assets/FilterBar-BygWrnB1.js +0 -2
- package/dashboard/dist/assets/FilterBar-BygWrnB1.js.map +0 -1
- package/dashboard/dist/assets/McpRunDetailPage-80fQn9iX.js +0 -2
- package/dashboard/dist/assets/WorkflowExecutionPage-Di08wCbs.js +0 -2
- package/dashboard/dist/assets/index-4YaDUcKd.js +0 -2
- package/dashboard/dist/assets/index-CnU7Jjz3.css +0 -1
- package/dashboard/dist/assets/index-Dz6R8-Dw.js.map +0 -1
- package/dashboard/dist/assets/vendor-icons-DUYcKTjP.js.map +0 -1
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* Runs the planner's actions: escalation verbs through LineEscalations,
|
|
4
4
|
* dispatches and commands through the Dispatcher, alarm and machine rows,
|
|
5
5
|
* and the offline debounce. A verb that fails for real throws, so the message that
|
|
6
|
-
* caused it is delivered again.
|
|
6
|
+
* caused it is delivered again. What ran comes back as wire actions, for the
|
|
7
|
+
* record of the message that caused it.
|
|
7
8
|
*/
|
|
8
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
10
|
exports.Executor = void 0;
|
|
@@ -15,18 +16,29 @@ const escalations_1 = require("./escalations");
|
|
|
15
16
|
const log_1 = require("./log");
|
|
16
17
|
const dispatcher_1 = require("./dispatcher");
|
|
17
18
|
const plan_shared_1 = require("./plan-shared");
|
|
19
|
+
const state_1 = require("./state");
|
|
20
|
+
const wire_1 = require("./wire");
|
|
18
21
|
const NOT_FOUND = 404;
|
|
19
22
|
const CONFLICT = 409;
|
|
23
|
+
/** A verb's outcome as the wire records it: done, already done, or refused by Long Tail. */
|
|
24
|
+
function outcomeOf(verb, rowId, result) {
|
|
25
|
+
const refused = result.outcome === escalations_1.VERB_OUTCOME.INVALID || result.status === NOT_FOUND || result.status === CONFLICT;
|
|
26
|
+
if (refused)
|
|
27
|
+
return { verb: 'refuse', rowId, detail: `${verb}: ${result.detail ?? result.outcome}` };
|
|
28
|
+
return { verb, rowId, ...(result.outcome === escalations_1.VERB_OUTCOME.ALREADY ? { detail: result.detail ?? 'already ended' } : {}) };
|
|
29
|
+
}
|
|
20
30
|
class Executor {
|
|
21
31
|
constructor(d) {
|
|
22
32
|
this.d = d;
|
|
23
33
|
this.inflight = new Set();
|
|
24
34
|
this.quietPending = new Set();
|
|
25
35
|
this.timers = new Set();
|
|
36
|
+
this.stopped = false;
|
|
26
37
|
this.dispatcher = new dispatcher_1.Dispatcher(d);
|
|
27
38
|
}
|
|
28
39
|
/** Dispatches and commands run detached so one slow reply never holds up the feed. */
|
|
29
40
|
async apply(actions) {
|
|
41
|
+
const done = [];
|
|
30
42
|
for (const action of actions) {
|
|
31
43
|
if (action.kind === 'dispatch')
|
|
32
44
|
this.track(this.dispatcher.dispatch(action));
|
|
@@ -34,75 +46,110 @@ class Executor {
|
|
|
34
46
|
this.track(this.dispatcher.command(action));
|
|
35
47
|
else if (action.kind === 'control')
|
|
36
48
|
this.track(this.dispatcher.control(action));
|
|
37
|
-
else
|
|
38
|
-
await this.run(action);
|
|
49
|
+
else {
|
|
50
|
+
done.push(...await this.run(action));
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
done.push((0, wire_1.plannedAction)(action));
|
|
39
54
|
}
|
|
55
|
+
return done;
|
|
40
56
|
}
|
|
41
57
|
/** Resolves when every detached dispatch has finished. */
|
|
42
58
|
async idle() {
|
|
43
59
|
while (this.inflight.size)
|
|
44
60
|
await Promise.all([...this.inflight]);
|
|
45
61
|
}
|
|
62
|
+
/** Work still running sends nothing more and raises no row; the next leader takes it up from the message or the row. */
|
|
46
63
|
stop() {
|
|
64
|
+
this.stopped = true;
|
|
47
65
|
for (const t of this.timers)
|
|
48
66
|
clearTimeout(t);
|
|
49
67
|
this.timers.clear();
|
|
68
|
+
this.dispatcher.stop();
|
|
50
69
|
this.d.replies.cancelAll();
|
|
51
70
|
}
|
|
71
|
+
/** A row raised after stop() would be raised again by the next leader, so the message is nak'd instead. */
|
|
72
|
+
live() {
|
|
73
|
+
if (this.stopped)
|
|
74
|
+
throw new dispatcher_1.GatewayStopped();
|
|
75
|
+
}
|
|
52
76
|
track(work) {
|
|
53
|
-
const tracked = work.catch((err) =>
|
|
77
|
+
const tracked = work.catch((err) => {
|
|
78
|
+
if (!(err instanceof dispatcher_1.GatewayStopped))
|
|
79
|
+
this.d.log.error(log_1.GATEWAY_LOG.VERB_FAILED, { error: String(err?.message ?? err) });
|
|
80
|
+
})
|
|
54
81
|
.finally(() => this.inflight.delete(tracked));
|
|
55
82
|
this.inflight.add(tracked);
|
|
56
83
|
}
|
|
57
84
|
async run(a) {
|
|
58
85
|
const { lt, state, replies } = this.d;
|
|
59
86
|
switch (a.kind) {
|
|
60
|
-
case 'claim':
|
|
61
|
-
|
|
87
|
+
case 'claim': {
|
|
88
|
+
const result = await lt.claim(a.as, a.rowId);
|
|
89
|
+
this.check(a, result);
|
|
90
|
+
return [outcomeOf('claim', a.rowId, result)];
|
|
91
|
+
}
|
|
62
92
|
case 'accumulate':
|
|
63
93
|
return this.accumulate(a);
|
|
64
|
-
case 'resolve':
|
|
65
|
-
|
|
94
|
+
case 'resolve': {
|
|
95
|
+
const result = await lt.resolve(a.as, a.rowId, a.payload);
|
|
96
|
+
this.check(a, result);
|
|
66
97
|
state.close(a.rowId);
|
|
67
|
-
return;
|
|
98
|
+
return [outcomeOf('resolve', a.rowId, result)];
|
|
99
|
+
}
|
|
68
100
|
case 'createAlarmRow':
|
|
69
|
-
return this.createAlarmRow(a);
|
|
101
|
+
return [{ verb: 'create-row', rowId: await this.createAlarmRow(a), detail: `${a.row.type} ${a.alarmId} at ${a.machineId}` }];
|
|
70
102
|
case 'createRow': {
|
|
103
|
+
this.live();
|
|
71
104
|
const { id } = await lt.create(actions_1.CONTROLLER, a.row);
|
|
72
105
|
this.d.log.info(log_1.GATEWAY_LOG.VIOLATION_ROW, { row: id, type: a.row.type });
|
|
73
|
-
return;
|
|
106
|
+
return [{ verb: 'create-row', rowId: id, detail: a.row.type }];
|
|
74
107
|
}
|
|
75
108
|
case 'watchOffline':
|
|
76
|
-
|
|
109
|
+
this.watchOffline(a.machineId);
|
|
110
|
+
return [(0, wire_1.plannedAction)(a)];
|
|
77
111
|
case 'settleReply':
|
|
78
|
-
if (
|
|
79
|
-
|
|
80
|
-
return;
|
|
112
|
+
if (replies.settle({ cmdId: a.cmdId, status: a.status, reason: a.reason, ...(a.code ? { code: a.code } : {}) }))
|
|
113
|
+
return [(0, wire_1.plannedAction)(a)];
|
|
114
|
+
return [{ verb: 'ack', detail: `late ${a.status} ${a.cmdId}` }, ...await this.lateReply(a)];
|
|
81
115
|
case 'settleSnapshot':
|
|
82
116
|
replies.settleSnapshot(a.machineId, new Set(a.jobIds));
|
|
83
|
-
return;
|
|
117
|
+
return [(0, wire_1.plannedAction)(a)];
|
|
84
118
|
case 'bindAddress':
|
|
85
119
|
await this.d.addresses.bind(a.machineId, a.address);
|
|
86
120
|
state.bindAddress(a.machineId, a.address);
|
|
87
121
|
this.d.log.info(log_1.GATEWAY_LOG.ADDRESS_BOUND, { machine: a.machineId, address: a.address, ...(a.by ? { approvedBy: a.by } : {}) });
|
|
88
|
-
return;
|
|
122
|
+
return [{ verb: 'ack', detail: `bound ${a.machineId} to ${a.address}` }];
|
|
89
123
|
case 'refuseBinding':
|
|
90
124
|
this.d.log.warn(log_1.GATEWAY_LOG.ADDRESS_REFUSED, { machine: a.machineId, address: a.address, reason: a.reason });
|
|
125
|
+
return [(0, wire_1.plannedAction)(a)];
|
|
91
126
|
}
|
|
92
127
|
}
|
|
93
|
-
/**
|
|
128
|
+
/**
|
|
129
|
+
* A dispatch's second reply: ready, or a failure to prepare that ends the
|
|
130
|
+
* handoff. When the handoff into the machine has already ended, as one
|
|
131
|
+
* dispatched on arrival does at acceptance, the failure ends the handoff
|
|
132
|
+
* carrying the units out of it.
|
|
133
|
+
*/
|
|
94
134
|
async lateReply(a) {
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
135
|
+
const { state, log } = this.d;
|
|
136
|
+
const into = state.rowForDispatch(a.cmdId);
|
|
137
|
+
const m = into?.toMachine;
|
|
138
|
+
if (!into || !m)
|
|
139
|
+
return [];
|
|
140
|
+
const context = { row: into.id, machine: m, cmdId: a.cmdId, reason: a.reason };
|
|
141
|
+
if (a.status === protocol_1.REPLY_STATUS.COMPLETED) {
|
|
142
|
+
log.info(log_1.GATEWAY_LOG.DISPATCH_READY, context);
|
|
143
|
+
return [];
|
|
144
|
+
}
|
|
101
145
|
if (a.status !== protocol_1.REPLY_STATUS.FAILED)
|
|
102
|
-
return;
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
146
|
+
return [];
|
|
147
|
+
const row = into.ended ? onwardRow(state, into, m) : into;
|
|
148
|
+
log.warn(log_1.GATEWAY_LOG.DISPATCH_FAILED, { ...context, ...(into.ended ? { onward: row?.id ?? null } : {}) });
|
|
149
|
+
if (!row)
|
|
150
|
+
return [];
|
|
151
|
+
return this.apply((0, plan_shared_1.failHandoff)(state, row, m, {
|
|
152
|
+
received: false, errorCode: contracts_1.HANDOFF_ERROR.DISPATCH_FAILED, detail: `${m} could not prepare the job: ${a.reason}`, ...(a.code ? { code: a.code } : {}),
|
|
106
153
|
}));
|
|
107
154
|
}
|
|
108
155
|
/** Add the item; when the row then holds every key the action waits for, resolve it. */
|
|
@@ -110,15 +157,18 @@ class Executor {
|
|
|
110
157
|
const { lt, state } = this.d;
|
|
111
158
|
const result = await lt.accumulate(a.as, a.rowId, a.itemKey, a.payload, a.metadata);
|
|
112
159
|
this.check(a, result);
|
|
160
|
+
const added = { ...outcomeOf('accumulate', a.rowId, result), itemKey: a.itemKey };
|
|
113
161
|
if (!a.complete || result.outcome === escalations_1.VERB_OUTCOME.INVALID)
|
|
114
|
-
return;
|
|
162
|
+
return [added];
|
|
115
163
|
const held = new Set(result.itemKeys ?? await lt.itemKeys(a.rowId));
|
|
116
164
|
if (!a.complete.keys.every((k) => held.has(k)))
|
|
117
|
-
return;
|
|
165
|
+
return [added];
|
|
118
166
|
if (a.complete.then)
|
|
119
|
-
return this.apply(a.complete.then);
|
|
120
|
-
|
|
167
|
+
return [added, ...await this.apply(a.complete.then)];
|
|
168
|
+
const resolved = await lt.resolve(a.as, a.rowId, a.complete.payload ?? {});
|
|
169
|
+
this.check(a, resolved);
|
|
121
170
|
state.close(a.rowId);
|
|
171
|
+
return [added, outcomeOf('resolve', a.rowId, resolved)];
|
|
122
172
|
}
|
|
123
173
|
check(a, result) {
|
|
124
174
|
const rowId = a.rowId;
|
|
@@ -133,17 +183,19 @@ class Executor {
|
|
|
133
183
|
}
|
|
134
184
|
}
|
|
135
185
|
async createAlarmRow(a) {
|
|
186
|
+
this.live();
|
|
136
187
|
const { id } = await this.d.lt.create(actions_1.CONTROLLER, { ...a.row, role: (0, line_1.operatorRole)(this.d.line) });
|
|
137
188
|
this.d.log.info(log_1.GATEWAY_LOG.ALARM_ROW, { row: id, machine: a.machineId, alarm: a.alarmId });
|
|
138
189
|
const track = this.d.state.alarms.get(this.d.state.alarmKey(a.machineId, a.alarmId));
|
|
139
190
|
const raisedAt = a.row.metadata?.raisedAt;
|
|
140
191
|
if (track && (!track.raisedAt || !raisedAt || track.raisedAt === raisedAt)) {
|
|
141
192
|
track.rowId = id;
|
|
142
|
-
return;
|
|
193
|
+
return id;
|
|
143
194
|
}
|
|
144
195
|
// Cleared at the machine, or raised again, while the row was being created.
|
|
145
196
|
const note = track ? `${a.machineId} raised ${a.alarmId} again; this one ended` : `cleared at ${a.machineId}`;
|
|
146
197
|
await this.d.lt.resolve(actions_1.CONTROLLER, id, { decision: contracts_1.DECISION.CLEARED, note });
|
|
198
|
+
return id;
|
|
147
199
|
}
|
|
148
200
|
/** Raise a quiet row for each connected machine silent longer than `quietMs`. */
|
|
149
201
|
checkQuiet(machineIds, quietMs) {
|
|
@@ -157,6 +209,7 @@ class Executor {
|
|
|
157
209
|
}
|
|
158
210
|
}
|
|
159
211
|
async raiseQuiet(machineId, silentMs) {
|
|
212
|
+
this.live();
|
|
160
213
|
const { id } = await this.d.lt.create(actions_1.CONTROLLER, {
|
|
161
214
|
type: contracts_1.ROW_TYPE.MACHINE_QUIET, role: (0, line_1.operatorRole)(this.d.line), priority: 2,
|
|
162
215
|
description: `${machineId} is connected but has sent nothing for ${Math.round(silentMs / 1000)} s`,
|
|
@@ -179,11 +232,12 @@ class Executor {
|
|
|
179
232
|
link.watching = false;
|
|
180
233
|
if (link.online || link.rowId)
|
|
181
234
|
return;
|
|
235
|
+
this.live();
|
|
182
236
|
const since = new Date(link.since).toISOString();
|
|
183
237
|
const { id } = await this.d.lt.create(actions_1.CONTROLLER, {
|
|
184
238
|
type: contracts_1.ROW_TYPE.MACHINE_OFFLINE, role: (0, line_1.operatorRole)(this.d.line), priority: 2,
|
|
185
239
|
description: `${machineId} has been offline since ${since}`,
|
|
186
|
-
metadata: { siteId: this.d.line.siteId, lineId: this.d.line.lineId, machineId, offlineSince: since },
|
|
240
|
+
metadata: { siteId: this.d.line.siteId, lineId: this.d.line.lineId, machineId, offlineSince: since, ...(link.reason ? { reason: link.reason } : {}) },
|
|
187
241
|
});
|
|
188
242
|
this.d.log.info(log_1.GATEWAY_LOG.OFFLINE_ROW, { row: id, machine: machineId });
|
|
189
243
|
if (!link.online)
|
|
@@ -193,3 +247,14 @@ class Executor {
|
|
|
193
247
|
}
|
|
194
248
|
}
|
|
195
249
|
exports.Executor = Executor;
|
|
250
|
+
/** The open handoff out of `m` for units a closed handoff brought into it. */
|
|
251
|
+
function onwardRow(state, into, m) {
|
|
252
|
+
if (into.ended !== state_1.ROW_END.RESOLVED || into.dispatch !== state_1.DISPATCH_STATE.ACCEPTED)
|
|
253
|
+
return undefined;
|
|
254
|
+
for (const u of into.units) {
|
|
255
|
+
const row = state.openFor(u.unitId, (r) => r.fromMachine === m);
|
|
256
|
+
if (row)
|
|
257
|
+
return row;
|
|
258
|
+
}
|
|
259
|
+
return undefined;
|
|
260
|
+
}
|
|
@@ -3,15 +3,18 @@
|
|
|
3
3
|
* reads escalation events (a new handoff row means "dispatch"), reads every
|
|
4
4
|
* machine message on the line (a receipt means "resolve"), and performs the
|
|
5
5
|
* verbs a person would, as the machine. Neither side knows about the other.
|
|
6
|
+
* Every message read or sent is recorded on the wire (wire.ts).
|
|
6
7
|
*/
|
|
7
8
|
import { type HandoffRowAdapter } from '../rows';
|
|
8
9
|
import { type AddressBook } from './address-book';
|
|
9
10
|
import type { LineDef } from '../../../lib/machines/line';
|
|
10
11
|
import { type LineCodec } from '../../../lib/machines/protocol';
|
|
11
|
-
import { type EscalationFeed, type MachineBus } from '../../../lib/machines/transport';
|
|
12
|
+
import { type EscalationFeed, type InboundMessage, type MachineBus } from '../../../lib/machines/transport';
|
|
13
|
+
import type { InspectResult } from '../../../types/machines-view';
|
|
12
14
|
import type { LineEscalations } from './escalations';
|
|
13
15
|
import { type GatewayLog } from './log';
|
|
14
16
|
import { GatewayState } from './state';
|
|
17
|
+
import { type WireSink } from './wire';
|
|
15
18
|
export interface GatewaySettings {
|
|
16
19
|
topicRoot: string;
|
|
17
20
|
replyTimeoutMs: number;
|
|
@@ -23,6 +26,12 @@ export interface GatewaySettings {
|
|
|
23
26
|
quietMs: number;
|
|
24
27
|
/** How long confirmed message ids gather before a receipt goes out (codecs with receipts). */
|
|
25
28
|
receiptDelayMs?: number;
|
|
29
|
+
/** Note each job's start, progress steps and pauses on the row that holds it; off unless set. */
|
|
30
|
+
lifecycle?: boolean;
|
|
31
|
+
/** With lifecycle notes, progress is noted each time it crosses this many percent; 0 notes none. */
|
|
32
|
+
progressStep?: number;
|
|
33
|
+
/** Record telemetry messages on the wire too; off unless set. */
|
|
34
|
+
wireTelemetry?: boolean;
|
|
26
35
|
}
|
|
27
36
|
export interface GatewayDeps {
|
|
28
37
|
bus: MachineBus;
|
|
@@ -37,6 +46,8 @@ export interface GatewayDeps {
|
|
|
37
46
|
codec?: LineCodec;
|
|
38
47
|
/** Where a line that learns addresses keeps them; in memory by default. */
|
|
39
48
|
addresses?: AddressBook;
|
|
49
|
+
/** Where wire records go; Long Tail's events by default. */
|
|
50
|
+
wire?: WireSink;
|
|
40
51
|
}
|
|
41
52
|
export declare class MachineGateway {
|
|
42
53
|
private readonly deps;
|
|
@@ -48,12 +59,22 @@ export declare class MachineGateway {
|
|
|
48
59
|
private readonly log;
|
|
49
60
|
private readonly addresses;
|
|
50
61
|
private readonly admission;
|
|
62
|
+
private readonly wire;
|
|
51
63
|
private quietTimer?;
|
|
52
64
|
constructor(deps: GatewayDeps);
|
|
53
65
|
start(): Promise<void>;
|
|
66
|
+
/**
|
|
67
|
+
* Hand the line over cleanly: nothing new is raised or sent, a message
|
|
68
|
+
* still being handled is nak'd for the next leader if it would make a row,
|
|
69
|
+
* receipts for what was applied go out, then the sessions close.
|
|
70
|
+
*/
|
|
54
71
|
stop(): Promise<void>;
|
|
72
|
+
/** Machines that report only changes are asked for their full state once the gateway listens. */
|
|
73
|
+
private askEveryMachine;
|
|
55
74
|
/** Resolves when no dispatch is in flight (tests). */
|
|
56
75
|
idle(): Promise<void>;
|
|
76
|
+
/** A dry run of one message on a copy of the state: nothing is applied (inspect.ts). */
|
|
77
|
+
inspect(msg: Pick<InboundMessage, 'topic' | 'payload' | 'retained'>): InspectResult;
|
|
57
78
|
/**
|
|
58
79
|
* On taking the line: open handoff and command rows (a dispatch or command
|
|
59
80
|
* interrupted by a restart is sent again with the same cmdId), the gateway's
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* reads escalation events (a new handoff row means "dispatch"), reads every
|
|
5
5
|
* machine message on the line (a receipt means "resolve"), and performs the
|
|
6
6
|
* verbs a person would, as the machine. Neither side knows about the other.
|
|
7
|
+
* Every message read or sent is recorded on the wire (wire.ts).
|
|
7
8
|
*/
|
|
8
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
10
|
exports.MachineGateway = void 0;
|
|
@@ -15,14 +16,18 @@ const address_book_1 = require("./address-book");
|
|
|
15
16
|
const admission_1 = require("./admission");
|
|
16
17
|
const protocol_1 = require("../../../lib/machines/protocol");
|
|
17
18
|
const transport_1 = require("../../../lib/machines/transport");
|
|
19
|
+
const publish_1 = require("../../../lib/events/publish");
|
|
18
20
|
const reply_waiter_1 = require("./reply-waiter");
|
|
19
21
|
const executor_1 = require("./executor");
|
|
22
|
+
const dispatcher_1 = require("./dispatcher");
|
|
23
|
+
const inspect_1 = require("./inspect");
|
|
20
24
|
const log_1 = require("./log");
|
|
21
25
|
const plan_escalation_1 = require("./plan-escalation");
|
|
22
26
|
const pacing_1 = require("./pacing");
|
|
23
27
|
const plan_machine_1 = require("./plan-machine");
|
|
24
28
|
const state_1 = require("./state");
|
|
25
29
|
const receipts_1 = require("./receipts");
|
|
30
|
+
const wire_1 = require("./wire");
|
|
26
31
|
class MachineGateway {
|
|
27
32
|
constructor(deps) {
|
|
28
33
|
this.deps = deps;
|
|
@@ -32,22 +37,30 @@ class MachineGateway {
|
|
|
32
37
|
this.codec = deps.codec ?? (0, protocol_1.genericCodec)({ root: deps.settings.topicRoot, line: deps.line });
|
|
33
38
|
this.state.unitsPerDispatch = this.codec.unitsPerDispatch;
|
|
34
39
|
this.state.dispatchOnArrival = this.codec.dispatchOn === protocol_1.DISPATCH_ON.ARRIVAL;
|
|
40
|
+
this.state.rowOps = (0, protocol_1.declaredRowOps)(this.codec);
|
|
41
|
+
this.state.lifecycle = deps.settings.lifecycle === true;
|
|
42
|
+
this.state.retainedAlarms = this.codec.retainedAlarms === true;
|
|
43
|
+
this.state.progressStep = deps.settings.progressStep ?? this.state.progressStep;
|
|
35
44
|
this.addresses = deps.addresses ?? new address_book_1.MemoryAddressBook();
|
|
45
|
+
this.wire = new wire_1.WireRecorder(deps.line, deps.wire ?? publish_1.publishMachineWireEvent, { telemetry: deps.settings.wireTelemetry === true });
|
|
36
46
|
this.executor = new executor_1.Executor({
|
|
37
|
-
addresses: this.addresses,
|
|
47
|
+
addresses: this.addresses, wire: this.wire,
|
|
38
48
|
bus: deps.bus, lt: deps.lt, replies: new reply_waiter_1.ReplyWaiter(), state: this.state, line: deps.line,
|
|
39
49
|
codec: this.codec, replyTimeoutMs: deps.settings.replyTimeoutMs,
|
|
40
50
|
dispatchAttempts: deps.settings.dispatchAttempts, offlineDebounceMs: deps.settings.offlineDebounceMs, log: this.log,
|
|
41
51
|
});
|
|
42
52
|
this.admission = { state: this.state, line: deps.line, executor: this.executor, log: this.log, pace: () => this.pace() };
|
|
43
|
-
this.receipts = new receipts_1.ReceiptBatcher({ bus: deps.bus, codec: this.codec, delayMs: deps.settings.receiptDelayMs ?? DEFAULT_RECEIPT_DELAY_MS, log: this.log });
|
|
53
|
+
this.receipts = new receipts_1.ReceiptBatcher({ bus: deps.bus, codec: this.codec, delayMs: deps.settings.receiptDelayMs ?? DEFAULT_RECEIPT_DELAY_MS, log: this.log, wire: this.wire });
|
|
44
54
|
}
|
|
45
55
|
async start() {
|
|
46
56
|
await this.deps.bus.connect();
|
|
47
57
|
await this.deps.feed.connect();
|
|
58
|
+
this.state.takenAt = Date.now();
|
|
48
59
|
await this.reconcile();
|
|
49
60
|
await this.deps.feed.consume((event) => this.onEscalation(event));
|
|
50
61
|
await this.deps.bus.consume((msg) => this.onMachine(msg));
|
|
62
|
+
if (this.codec.snapshotOnStart)
|
|
63
|
+
await this.askEveryMachine();
|
|
51
64
|
const { quietMs } = this.deps.settings;
|
|
52
65
|
if (quietMs > 0) {
|
|
53
66
|
const machines = this.deps.line.machines.map((m) => m.machineId);
|
|
@@ -55,18 +68,37 @@ class MachineGateway {
|
|
|
55
68
|
}
|
|
56
69
|
this.log.info(log_1.GATEWAY_LOG.STARTED, { site: this.deps.line.siteId, line: this.deps.line.lineId });
|
|
57
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* Hand the line over cleanly: nothing new is raised or sent, a message
|
|
73
|
+
* still being handled is nak'd for the next leader if it would make a row,
|
|
74
|
+
* receipts for what was applied go out, then the sessions close.
|
|
75
|
+
*/
|
|
58
76
|
async stop() {
|
|
59
77
|
if (this.quietTimer)
|
|
60
78
|
clearInterval(this.quietTimer);
|
|
61
79
|
this.executor.stop();
|
|
80
|
+
await this.deps.feed.unsubscribe();
|
|
81
|
+
await this.deps.bus.unsubscribe();
|
|
82
|
+
await this.executor.idle();
|
|
62
83
|
await this.receipts.flush();
|
|
63
84
|
await this.deps.feed.close();
|
|
64
85
|
await this.deps.bus.close();
|
|
65
86
|
}
|
|
87
|
+
/** Machines that report only changes are asked for their full state once the gateway listens. */
|
|
88
|
+
async askEveryMachine() {
|
|
89
|
+
const at = Date.now();
|
|
90
|
+
await this.executor.apply(this.deps.line.machines.map((m) => ({
|
|
91
|
+
kind: 'command', machineId: m.machineId, op: protocol_1.OP.SNAPSHOT, cmdId: `${m.machineId}:takeover:${at}`, args: {},
|
|
92
|
+
})));
|
|
93
|
+
}
|
|
66
94
|
/** Resolves when no dispatch is in flight (tests). */
|
|
67
95
|
idle() {
|
|
68
96
|
return this.executor.idle();
|
|
69
97
|
}
|
|
98
|
+
/** A dry run of one message on a copy of the state: nothing is applied (inspect.ts). */
|
|
99
|
+
inspect(msg) {
|
|
100
|
+
return (0, inspect_1.dryRun)({ state: this.state, line: this.deps.line, codec: this.codec, dispatchTtlMs: this.deps.settings.dispatchTtlMs }, { ...msg, deliveries: 1 });
|
|
101
|
+
}
|
|
70
102
|
/**
|
|
71
103
|
* On taking the line: open handoff and command rows (a dispatch or command
|
|
72
104
|
* interrupted by a restart is sent again with the same cmdId), the gateway's
|
|
@@ -80,6 +112,7 @@ class MachineGateway {
|
|
|
80
112
|
const addresses = await (0, reconcile_1.restoreAddresses)(this.state, this.addresses, this.deps.line);
|
|
81
113
|
const handoffs = await this.reconcileHandoffs();
|
|
82
114
|
await this.executor.apply(await (0, reconcile_1.arrivalsOnRows)(this.state, this.deps.lt, this.deps.settings.dispatchTtlMs));
|
|
115
|
+
await (0, reconcile_1.notesOnRows)(this.state, this.deps.lt);
|
|
83
116
|
const commands = await this.reconcileCommands();
|
|
84
117
|
const restored = await (0, reconcile_1.restoreLineRows)(this.state, this.deps.lt, this.deps.line);
|
|
85
118
|
await this.resync();
|
|
@@ -121,18 +154,31 @@ class MachineGateway {
|
|
|
121
154
|
async resync() {
|
|
122
155
|
const { line } = this.deps;
|
|
123
156
|
const active = new Set();
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
157
|
+
this.state.readingRetained = true;
|
|
158
|
+
try {
|
|
159
|
+
for (const read of await this.deps.bus.retained((0, protocol_1.lineFilter)(this.codec.root, line.siteId, line.lineId))) {
|
|
160
|
+
const msg = { ...read, retained: true };
|
|
161
|
+
for (const raw of this.decode(msg)) {
|
|
162
|
+
if (!raw.parsed)
|
|
163
|
+
continue;
|
|
164
|
+
const admitted = await (0, admission_1.admitSender)(this.admission, msg.topic, raw);
|
|
165
|
+
if (!('seen' in admitted)) {
|
|
166
|
+
this.wire.inbound(msg, raw, admitted, 1, admitted.sender);
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
const { seen } = admitted;
|
|
170
|
+
if (seen.parsed.kind === protocol_1.MESSAGE_KIND.ALARM && seen.body?.body?.active)
|
|
171
|
+
active.add(this.state.alarmKey(seen.parsed.ident.machineId, seen.parsed.key));
|
|
172
|
+
const applied = await this.applyMachine(msg.topic, seen.parsed, seen.body);
|
|
173
|
+
this.wire.inbound(msg, seen, { ...applied, actions: [...admitted.actions, ...applied.actions] }, 1);
|
|
174
|
+
}
|
|
134
175
|
}
|
|
135
176
|
}
|
|
177
|
+
finally {
|
|
178
|
+
this.state.readingRetained = false;
|
|
179
|
+
}
|
|
180
|
+
if (!this.state.retainedAlarms)
|
|
181
|
+
return;
|
|
136
182
|
for (const gone of (0, reconcile_1.alarmsClearedMeanwhile)(this.state, active)) {
|
|
137
183
|
this.state.alarms.delete(gone.key);
|
|
138
184
|
await this.executor.apply([{ kind: 'resolve', as: actions_1.CONTROLLER, rowId: gone.rowId, payload: { decision: contracts_1.DECISION.CLEARED, note: `cleared at ${gone.machineId} while the gateway was away` } }]);
|
|
@@ -147,7 +193,8 @@ class MachineGateway {
|
|
|
147
193
|
return transport_1.DISPOSITION.ACK;
|
|
148
194
|
}
|
|
149
195
|
catch (err) {
|
|
150
|
-
|
|
196
|
+
if (!(err instanceof dispatcher_1.GatewayStopped))
|
|
197
|
+
this.log.error(log_1.GATEWAY_LOG.VERB_FAILED, { event: event.type, error: err.message });
|
|
151
198
|
return transport_1.DISPOSITION.NAK;
|
|
152
199
|
}
|
|
153
200
|
}
|
|
@@ -165,19 +212,21 @@ class MachineGateway {
|
|
|
165
212
|
return { ...event, role: row.role, data: row };
|
|
166
213
|
}
|
|
167
214
|
async onMachine(msg) {
|
|
168
|
-
const decoded = this.decode(msg
|
|
215
|
+
const decoded = this.decode(msg);
|
|
169
216
|
const acted = [];
|
|
170
217
|
let outcome = transport_1.DISPOSITION.TERM;
|
|
171
218
|
let failed = false;
|
|
172
219
|
for (const raw of decoded) {
|
|
173
220
|
if (!raw.parsed)
|
|
174
221
|
continue;
|
|
175
|
-
const
|
|
176
|
-
if (!('
|
|
177
|
-
failed ||=
|
|
178
|
-
outcome = worse(outcome,
|
|
222
|
+
const admitted = await (0, admission_1.admitSender)(this.admission, msg.topic, raw);
|
|
223
|
+
if (!('seen' in admitted)) {
|
|
224
|
+
failed ||= admitted.failed;
|
|
225
|
+
outcome = worse(outcome, admitted.disposition);
|
|
226
|
+
this.wire.inbound(msg, raw, admitted, msg.deliveries, admitted.sender);
|
|
179
227
|
continue;
|
|
180
228
|
}
|
|
229
|
+
const { seen } = admitted;
|
|
181
230
|
acted.push(seen);
|
|
182
231
|
if (seen.violations.length && msg.deliveries === 1) {
|
|
183
232
|
this.log.warn(log_1.GATEWAY_LOG.CONTRACT_VIOLATION, { topic: msg.topic, violations: seen.violations });
|
|
@@ -187,9 +236,10 @@ class MachineGateway {
|
|
|
187
236
|
: await this.applyMachine(msg.topic, seen.parsed, seen.body);
|
|
188
237
|
failed ||= applied.failed;
|
|
189
238
|
outcome = worse(outcome, applied.disposition);
|
|
239
|
+
this.wire.inbound(msg, seen, { ...applied, actions: [...admitted.actions, ...applied.actions] }, msg.deliveries);
|
|
190
240
|
}
|
|
191
241
|
// No row has claimed it after this many tries, so it is not racing its row: stop. A failed verb always retries.
|
|
192
|
-
if (outcome === transport_1.DISPOSITION.NAK && !failed && msg.deliveries >= MAX_DELIVERIES) {
|
|
242
|
+
if (outcome === transport_1.DISPOSITION.NAK && !failed && msg.deliveries >= wire_1.MAX_DELIVERIES) {
|
|
193
243
|
this.log.warn(log_1.GATEWAY_LOG.UNMATCHED, { topic: msg.topic, deliveries: msg.deliveries });
|
|
194
244
|
outcome = transport_1.DISPOSITION.TERM;
|
|
195
245
|
}
|
|
@@ -198,14 +248,19 @@ class MachineGateway {
|
|
|
198
248
|
return outcome;
|
|
199
249
|
}
|
|
200
250
|
/** A message the codec cannot read is not retried: it is logged and has no effect. */
|
|
201
|
-
decode(
|
|
251
|
+
decode(msg) {
|
|
252
|
+
let decoded;
|
|
202
253
|
try {
|
|
203
|
-
|
|
254
|
+
decoded = this.codec.decode(msg.topic, msg.payload, msg.retained);
|
|
204
255
|
}
|
|
205
256
|
catch (err) {
|
|
206
|
-
this.log.warn(log_1.GATEWAY_LOG.UNREADABLE, { topic, error: err.message });
|
|
257
|
+
this.log.warn(log_1.GATEWAY_LOG.UNREADABLE, { topic: msg.topic, error: err.message });
|
|
258
|
+
this.wire.unreadable(msg, err.message);
|
|
207
259
|
return [];
|
|
208
260
|
}
|
|
261
|
+
if (!decoded.length)
|
|
262
|
+
this.wire.unreadable(msg, 'not a machine message', 'none');
|
|
263
|
+
return decoded;
|
|
209
264
|
}
|
|
210
265
|
/** Done with the message: confirm each id its codec asked to confirm. */
|
|
211
266
|
confirm(decoded) {
|
|
@@ -224,21 +279,21 @@ class MachineGateway {
|
|
|
224
279
|
}
|
|
225
280
|
catch (err) {
|
|
226
281
|
this.log.warn(log_1.GATEWAY_LOG.UNREADABLE, { topic, error: err.message });
|
|
227
|
-
return { disposition: transport_1.DISPOSITION.TERM, failed: false };
|
|
282
|
+
return { disposition: transport_1.DISPOSITION.TERM, failed: false, actions: [{ verb: 'unreadable', detail: err.message }] };
|
|
228
283
|
}
|
|
229
284
|
try {
|
|
230
|
-
await this.executor.apply(plan.actions);
|
|
285
|
+
const actions = await this.executor.apply(plan.actions);
|
|
231
286
|
await this.pace();
|
|
232
|
-
return { disposition: plan.disposition, failed: false };
|
|
287
|
+
return { disposition: plan.disposition, failed: false, actions };
|
|
233
288
|
}
|
|
234
289
|
catch (err) {
|
|
235
|
-
|
|
236
|
-
|
|
290
|
+
if (!(err instanceof dispatcher_1.GatewayStopped))
|
|
291
|
+
this.log.error(log_1.GATEWAY_LOG.VERB_FAILED, { topic, error: err.message });
|
|
292
|
+
return { disposition: transport_1.DISPOSITION.NAK, failed: true, actions: [] };
|
|
237
293
|
}
|
|
238
294
|
}
|
|
239
295
|
}
|
|
240
296
|
exports.MachineGateway = MachineGateway;
|
|
241
|
-
const MAX_DELIVERIES = 30;
|
|
242
297
|
const DEFAULT_RECEIPT_DELAY_MS = 250;
|
|
243
298
|
const RANK = { [transport_1.DISPOSITION.TERM]: 0, [transport_1.DISPOSITION.ACK]: 1, [transport_1.DISPOSITION.NAK]: 2 };
|
|
244
299
|
/** One wire message may decode to several; any that must be retried retries the message. */
|
|
@@ -24,3 +24,6 @@ __exportStar(require("./provision"), exports);
|
|
|
24
24
|
__exportStar(require("./state"), exports);
|
|
25
25
|
__exportStar(require("./address-book"), exports);
|
|
26
26
|
__exportStar(require("./registration"), exports);
|
|
27
|
+
__exportStar(require("./wire"), exports);
|
|
28
|
+
__exportStar(require("./project"), exports);
|
|
29
|
+
__exportStar(require("./inspect"), exports);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A dry run of one wire message: what the codec reads and what the gateway
|
|
3
|
+
* would do, planned on a copy of the state so the line is untouched and no
|
|
4
|
+
* row is created or changed.
|
|
5
|
+
*/
|
|
6
|
+
import type { LineDef } from '../../../lib/machines/line';
|
|
7
|
+
import type { LineCodec } from '../../../lib/machines/protocol';
|
|
8
|
+
import type { InboundMessage } from '../../../lib/machines/transport';
|
|
9
|
+
import type { InspectResult } from '../../../types/machines-view';
|
|
10
|
+
import type { GatewayState } from './state';
|
|
11
|
+
export interface DryRunContext {
|
|
12
|
+
state: GatewayState;
|
|
13
|
+
line: LineDef;
|
|
14
|
+
codec: LineCodec;
|
|
15
|
+
dispatchTtlMs: number;
|
|
16
|
+
}
|
|
17
|
+
export declare function dryRun(ctx: DryRunContext, msg: InboundMessage): InspectResult;
|