@hotmeshio/long-tail 0.4.22 → 0.4.24
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/build/api/dba.d.ts +2 -1
- package/build/api/dba.js +3 -2
- package/build/api/exports.d.ts +1 -0
- package/build/api/exports.js +1 -1
- package/build/api/maintenance.d.ts +1 -0
- package/build/api/maintenance.js +3 -3
- package/build/api/overview.d.ts +4 -0
- package/build/api/overview.js +13 -0
- package/build/api/workflows/discovery.js +5 -2
- package/build/modules/maintenance.js +1 -0
- package/build/routes/controlplane.js +40 -29
- package/build/routes/dba.js +13 -2
- package/build/routes/exports.js +6 -0
- package/build/routes/index.js +2 -0
- package/build/routes/maintenance.js +1 -0
- package/build/routes/overview.d.ts +2 -0
- package/build/routes/overview.js +50 -0
- package/build/services/controlplane/index.js +7 -5
- package/build/services/dba.d.ts +3 -1
- package/build/services/dba.js +5 -4
- package/build/services/export/index.d.ts +2 -2
- package/build/services/export/index.js +16 -10
- package/build/services/maintenance/index.js +7 -4
- package/build/services/overview/index.d.ts +78 -0
- package/build/services/overview/index.js +105 -0
- package/build/services/overview/sql.d.ts +29 -0
- package/build/services/overview/sql.js +134 -0
- package/build/services/pipelines/queries.js +5 -2
- package/build/services/pipelines/sql.d.ts +0 -1
- package/build/services/pipelines/sql.js +1 -3
- package/build/system/mcp-servers/admin/controlplane.js +1 -1
- package/build/system/mcp-servers/admin/index.js +4 -2
- package/build/system/mcp-servers/admin/maintenance.js +1 -0
- package/build/system/mcp-servers/admin/overview.d.ts +13 -0
- package/build/system/mcp-servers/admin/overview.js +34 -0
- package/build/system/mcp-servers/admin/pipelines.js +4 -4
- package/build/system/mcp-servers/admin/schemas.d.ts +26 -20
- package/build/system/mcp-servers/admin/schemas.js +17 -15
- package/build/system/seed/tool-manifests-admin.d.ts +114 -0
- package/build/system/seed/tool-manifests-admin.js +2 -0
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/types/maintenance.d.ts +2 -0
- package/dashboard/dist/assets/{AdminDashboard-BwUGcCxQ.js → AdminDashboard-CgJC8ZZF.js} +2 -2
- package/dashboard/dist/assets/{AdminDashboard-BwUGcCxQ.js.map → AdminDashboard-CgJC8ZZF.js.map} +1 -1
- package/dashboard/dist/assets/{AgentConfigPage-DgrYzLwq.js → AgentConfigPage-Bjl2Lsvo.js} +2 -2
- package/dashboard/dist/assets/{AgentConfigPage-DgrYzLwq.js.map → AgentConfigPage-Bjl2Lsvo.js.map} +1 -1
- package/dashboard/dist/assets/{AgentDetailPage-XJpl7wfJ.js → AgentDetailPage-D5dHrfaM.js} +2 -2
- package/dashboard/dist/assets/{AgentDetailPage-XJpl7wfJ.js.map → AgentDetailPage-D5dHrfaM.js.map} +1 -1
- package/dashboard/dist/assets/{AgentsPage-CGpVG6r8.js → AgentsPage-Mom3N1Av.js} +2 -2
- package/dashboard/dist/assets/{AgentsPage-CGpVG6r8.js.map → AgentsPage-Mom3N1Av.js.map} +1 -1
- package/dashboard/dist/assets/{AvailableEscalationsPage-DR1e0TQZ.js → AvailableEscalationsPage-B2ZAb41C.js} +2 -2
- package/dashboard/dist/assets/{AvailableEscalationsPage-DR1e0TQZ.js.map → AvailableEscalationsPage-B2ZAb41C.js.map} +1 -1
- package/dashboard/dist/assets/{BotPicker-BKtjl6IL.js → BotPicker-dCvnjynP.js} +2 -2
- package/dashboard/dist/assets/{BotPicker-BKtjl6IL.js.map → BotPicker-dCvnjynP.js.map} +1 -1
- package/dashboard/dist/assets/{CapabilitiesPage-kCB8fyOj.js → CapabilitiesPage-CK2fJ9Sy.js} +2 -2
- package/dashboard/dist/assets/{CapabilitiesPage-kCB8fyOj.js.map → CapabilitiesPage-CK2fJ9Sy.js.map} +1 -1
- package/dashboard/dist/assets/{CollapsibleSection-C3tU61hB.js → CollapsibleSection-bW0UZN9b.js} +2 -2
- package/dashboard/dist/assets/{CollapsibleSection-C3tU61hB.js.map → CollapsibleSection-bW0UZN9b.js.map} +1 -1
- package/dashboard/dist/assets/{CredentialsPage-Dt4nJs_B.js → CredentialsPage-DVOK3aaR.js} +2 -2
- package/dashboard/dist/assets/{CredentialsPage-Dt4nJs_B.js.map → CredentialsPage-DVOK3aaR.js.map} +1 -1
- package/dashboard/dist/assets/{CronLabel-BdE6mHyA.js → CronLabel-Cv5em7OP.js} +2 -2
- package/dashboard/dist/assets/{CronLabel-BdE6mHyA.js.map → CronLabel-Cv5em7OP.js.map} +1 -1
- package/dashboard/dist/assets/{CustomDurationPicker-B_Yxfb-u.js → CustomDurationPicker-Dy4NBqhZ.js} +2 -2
- package/dashboard/dist/assets/{CustomDurationPicker-B_Yxfb-u.js.map → CustomDurationPicker-Dy4NBqhZ.js.map} +1 -1
- package/dashboard/dist/assets/{ElapsedCell-tcGx5PFI.js → ElapsedCell-TQqWaVRq.js} +2 -2
- package/dashboard/dist/assets/{ElapsedCell-tcGx5PFI.js.map → ElapsedCell-TQqWaVRq.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationsOverview-1KO5dXzk.js → EscalationsOverview-Cv5UvuHI.js} +2 -2
- package/dashboard/dist/assets/{EscalationsOverview-1KO5dXzk.js.map → EscalationsOverview-Cv5UvuHI.js.map} +1 -1
- package/dashboard/dist/assets/{EventTable-DnpsQ6Ew.js → EventTable-Doky6fCO.js} +2 -2
- package/dashboard/dist/assets/{EventTable-DnpsQ6Ew.js.map → EventTable-Doky6fCO.js.map} +1 -1
- package/dashboard/dist/assets/HomePage-CzvVyTq4.js +2 -0
- package/dashboard/dist/assets/HomePage-CzvVyTq4.js.map +1 -0
- package/dashboard/dist/assets/{ListToolbar-jrVba7QN.js → ListToolbar-Cfec9gz_.js} +2 -2
- package/dashboard/dist/assets/{ListToolbar-jrVba7QN.js.map → ListToolbar-Cfec9gz_.js.map} +1 -1
- package/dashboard/dist/assets/McpOverview-BN4GsBGI.js +2 -0
- package/dashboard/dist/assets/McpOverview-BN4GsBGI.js.map +1 -0
- package/dashboard/dist/assets/McpQueryDetailPage-lCW668WQ.js +5 -0
- package/dashboard/dist/assets/McpQueryDetailPage-lCW668WQ.js.map +1 -0
- package/dashboard/dist/assets/{McpQueryPage-WZfTY43_.js → McpQueryPage-BK5L2PqJ.js} +2 -2
- package/dashboard/dist/assets/{McpQueryPage-WZfTY43_.js.map → McpQueryPage-BK5L2PqJ.js.map} +1 -1
- package/dashboard/dist/assets/McpRunDetailPage-CQOeYqxa.js +2 -0
- package/dashboard/dist/assets/McpRunDetailPage-CQOeYqxa.js.map +1 -0
- package/dashboard/dist/assets/McpRunsPage-QsXid9Xe.js +2 -0
- package/dashboard/dist/assets/McpRunsPage-QsXid9Xe.js.map +1 -0
- package/dashboard/dist/assets/{OperatorDashboard-Cy7ySMXj.js → OperatorDashboard-CZQSINho.js} +2 -2
- package/dashboard/dist/assets/{OperatorDashboard-Cy7ySMXj.js.map → OperatorDashboard-CZQSINho.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessDetailPage-DYIfvWyc.js → ProcessDetailPage-DUCOOvOK.js} +2 -2
- package/dashboard/dist/assets/{ProcessDetailPage-DYIfvWyc.js.map → ProcessDetailPage-DUCOOvOK.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessesListPage-DR1RGaMl.js → ProcessesListPage-CXvSLTIM.js} +2 -2
- package/dashboard/dist/assets/{ProcessesListPage-DR1RGaMl.js.map → ProcessesListPage-CXvSLTIM.js.map} +1 -1
- package/dashboard/dist/assets/RolesPage-DlQR0Iz_.js +2 -0
- package/dashboard/dist/assets/RolesPage-DlQR0Iz_.js.map +1 -0
- package/dashboard/dist/assets/{RunAsSelector-B-ksMoEj.js → RunAsSelector-DP-jxsv6.js} +2 -2
- package/dashboard/dist/assets/{RunAsSelector-B-ksMoEj.js.map → RunAsSelector-DP-jxsv6.js.map} +1 -1
- package/dashboard/dist/assets/{SwimlaneTimeline-Cr_K5qpu.js → SwimlaneTimeline-BmASA0nN.js} +2 -2
- package/dashboard/dist/assets/{SwimlaneTimeline-Cr_K5qpu.js.map → SwimlaneTimeline-BmASA0nN.js.map} +1 -1
- package/dashboard/dist/assets/{TaskDetailPage-BO5p7AEe.js → TaskDetailPage-CRowpkeZ.js} +2 -2
- package/dashboard/dist/assets/{TaskDetailPage-BO5p7AEe.js.map → TaskDetailPage-CRowpkeZ.js.map} +1 -1
- package/dashboard/dist/assets/{TasksListPage-BRg-uFtF.js → TasksListPage-uJ6z37J-.js} +2 -2
- package/dashboard/dist/assets/{TasksListPage-BRg-uFtF.js.map → TasksListPage-uJ6z37J-.js.map} +1 -1
- package/dashboard/dist/assets/TimeAgo-BxwngK1D.js +2 -0
- package/dashboard/dist/assets/{TimeAgo-BSzN6rAH.js.map → TimeAgo-BxwngK1D.js.map} +1 -1
- package/dashboard/dist/assets/{TimestampCell-DL6zMNEQ.js → TimestampCell-CDmichOM.js} +2 -2
- package/dashboard/dist/assets/{TimestampCell-DL6zMNEQ.js.map → TimestampCell-CDmichOM.js.map} +1 -1
- package/dashboard/dist/assets/ToolTestPanel-xjTn8sU8.js +2 -0
- package/dashboard/dist/assets/ToolTestPanel-xjTn8sU8.js.map +1 -0
- package/dashboard/dist/assets/{TopicDetailPage-D7gCsPKB.js → TopicDetailPage-Dm0hDlS8.js} +2 -2
- package/dashboard/dist/assets/{TopicDetailPage-D7gCsPKB.js.map → TopicDetailPage-Dm0hDlS8.js.map} +1 -1
- package/dashboard/dist/assets/{TopicsPage-B3Aa8Haz.js → TopicsPage-letISGGD.js} +2 -2
- package/dashboard/dist/assets/{TopicsPage-B3Aa8Haz.js.map → TopicsPage-letISGGD.js.map} +1 -1
- package/dashboard/dist/assets/{UserName-BjHIJWgh.js → UserName-W6_Iz2Qb.js} +2 -2
- package/dashboard/dist/assets/{UserName-BjHIJWgh.js.map → UserName-W6_Iz2Qb.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowExecutionPage-BQ7AYlQA.js → WorkflowExecutionPage-Cfx-xlRT.js} +2 -2
- package/dashboard/dist/assets/{WorkflowExecutionPage-BQ7AYlQA.js.map → WorkflowExecutionPage-Cfx-xlRT.js.map} +1 -1
- package/dashboard/dist/assets/WorkflowsDashboard-DC4XHMWt.js +2 -0
- package/dashboard/dist/assets/WorkflowsDashboard-DC4XHMWt.js.map +1 -0
- package/dashboard/dist/assets/{WorkflowsOverview-B4DUcVxs.js → WorkflowsOverview-GefO_yn0.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsOverview-B4DUcVxs.js.map → WorkflowsOverview-GefO_yn0.js.map} +1 -1
- package/dashboard/dist/assets/YamlWorkflowsPage-CMsrFooO.js +2 -0
- package/dashboard/dist/assets/YamlWorkflowsPage-CMsrFooO.js.map +1 -0
- package/dashboard/dist/assets/{agents-CkvQDr9b.js → agents-BI5OeN84.js} +2 -2
- package/dashboard/dist/assets/{agents-CkvQDr9b.js.map → agents-BI5OeN84.js.map} +1 -1
- package/dashboard/dist/assets/{bots-CzuMCVgU.js → bots-1UzUCsrR.js} +2 -2
- package/dashboard/dist/assets/{bots-CzuMCVgU.js.map → bots-1UzUCsrR.js.map} +1 -1
- package/dashboard/dist/assets/capabilities-BUbl-ojp.js +2 -0
- package/dashboard/dist/assets/{capabilities-CbGmS0ty.js.map → capabilities-BUbl-ojp.js.map} +1 -1
- package/dashboard/dist/assets/{controlplane-DGvwkuYx.js → controlplane-DTFrH_vN.js} +2 -2
- package/dashboard/dist/assets/{controlplane-DGvwkuYx.js.map → controlplane-DTFrH_vN.js.map} +1 -1
- package/dashboard/dist/assets/{escalation-B7ysVToF.js → escalation-BQhCt4W0.js} +2 -2
- package/dashboard/dist/assets/{escalation-B7ysVToF.js.map → escalation-BQhCt4W0.js.map} +1 -1
- package/dashboard/dist/assets/{escalation-columns-CHQEJU1j.js → escalation-columns-J20k5CcY.js} +2 -2
- package/dashboard/dist/assets/{escalation-columns-CHQEJU1j.js.map → escalation-columns-J20k5CcY.js.map} +1 -1
- package/dashboard/dist/assets/{helpers-BFOjXa4r.js → helpers-ge6Eu90Y.js} +2 -2
- package/dashboard/dist/assets/{helpers-BFOjXa4r.js.map → helpers-ge6Eu90Y.js.map} +1 -1
- package/dashboard/dist/assets/index-C-mbURj-.js +2 -0
- package/dashboard/dist/assets/index-C-mbURj-.js.map +1 -0
- package/dashboard/dist/assets/{index-BduDiGcw.js → index-C45DvtAZ.js} +2 -2
- package/dashboard/dist/assets/{index-BduDiGcw.js.map → index-C45DvtAZ.js.map} +1 -1
- package/dashboard/dist/assets/{index-B9_1AZaG.js → index-C9ClHiiW.js} +2 -2
- package/dashboard/dist/assets/{index-B9_1AZaG.js.map → index-C9ClHiiW.js.map} +1 -1
- package/dashboard/dist/assets/index-CLUYzdwz.js +2 -0
- package/dashboard/dist/assets/{index-DQHmfTPo.js.map → index-CLUYzdwz.js.map} +1 -1
- package/dashboard/dist/assets/{index-l_8R6U4r.js → index-CVGgSoda.js} +2 -2
- package/dashboard/dist/assets/{index-l_8R6U4r.js.map → index-CVGgSoda.js.map} +1 -1
- package/dashboard/dist/assets/{index-_BRA9uFL.js → index-CWEOhAiK.js} +3 -3
- package/dashboard/dist/assets/{index-_BRA9uFL.js.map → index-CWEOhAiK.js.map} +1 -1
- package/dashboard/dist/assets/{index-BFaDxPxA.js → index-CWlP6vHG.js} +2 -2
- package/dashboard/dist/assets/{index-BFaDxPxA.js.map → index-CWlP6vHG.js.map} +1 -1
- package/dashboard/dist/assets/index-DasoTRjT.js +2 -0
- package/dashboard/dist/assets/{index-BeLphL59.js.map → index-DasoTRjT.js.map} +1 -1
- package/dashboard/dist/assets/{index-CvOGgvzP.js → index-FhasoOjO.js} +2 -2
- package/dashboard/dist/assets/{index-CvOGgvzP.js.map → index-FhasoOjO.js.map} +1 -1
- package/dashboard/dist/assets/{index-a98qWLB-.js → index-WQQJ_cp7.js} +2 -2
- package/dashboard/dist/assets/{index-a98qWLB-.js.map → index-WQQJ_cp7.js.map} +1 -1
- package/dashboard/dist/assets/{index-CbrMW-gM.js → index-hAZiac0C.js} +2 -2
- package/dashboard/dist/assets/{index-CbrMW-gM.js.map → index-hAZiac0C.js.map} +1 -1
- package/dashboard/dist/assets/{index-v0OQpgXS.js → index-si70YcIP.js} +2 -2
- package/dashboard/dist/assets/{index-v0OQpgXS.js.map → index-si70YcIP.js.map} +1 -1
- package/dashboard/dist/assets/{index-CRiBkHPb.js → index-vgxjge70.js} +2 -2
- package/dashboard/dist/assets/{index-CRiBkHPb.js.map → index-vgxjge70.js.map} +1 -1
- package/dashboard/dist/assets/{knowledge-BlF8UMrk.js → knowledge-D9Tuh-o-.js} +2 -2
- package/dashboard/dist/assets/{knowledge-BlF8UMrk.js.map → knowledge-D9Tuh-o-.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-MtXuky8q.js → mcp-BO8QnWyk.js} +2 -2
- package/dashboard/dist/assets/{mcp-MtXuky8q.js.map → mcp-BO8QnWyk.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-query-DQ-J1Q0K.js → mcp-query-WLtQtr51.js} +2 -2
- package/dashboard/dist/assets/{mcp-query-DQ-J1Q0K.js.map → mcp-query-WLtQtr51.js.map} +1 -1
- package/dashboard/dist/assets/pipelines-BAVf9xud.js +2 -0
- package/dashboard/dist/assets/pipelines-BAVf9xud.js.map +1 -0
- package/dashboard/dist/assets/{roles-D-LhJ82d.js → roles-mGO2-2hA.js} +2 -2
- package/dashboard/dist/assets/{roles-D-LhJ82d.js.map → roles-mGO2-2hA.js.map} +1 -1
- package/dashboard/dist/assets/{tasks-BrP_8uEN.js → tasks-JVRVCx0f.js} +2 -2
- package/dashboard/dist/assets/{tasks-BrP_8uEN.js.map → tasks-JVRVCx0f.js.map} +1 -1
- package/dashboard/dist/assets/{topics-DUk-zX5D.js → topics-BLVnahd7.js} +2 -2
- package/dashboard/dist/assets/{topics-DUk-zX5D.js.map → topics-BLVnahd7.js.map} +1 -1
- package/dashboard/dist/assets/{useEventHooks-XNNzwADV.js → useEventHooks-BwjAi0Qq.js} +2 -2
- package/dashboard/dist/assets/{useEventHooks-XNNzwADV.js.map → useEventHooks-BwjAi0Qq.js.map} +1 -1
- package/dashboard/dist/assets/useNamespace-DkHmXddZ.js +2 -0
- package/dashboard/dist/assets/useNamespace-DkHmXddZ.js.map +1 -0
- package/dashboard/dist/assets/{useYamlActivityEvents-DANQ5jIY.js → useYamlActivityEvents-CsaR5dWj.js} +2 -2
- package/dashboard/dist/assets/{useYamlActivityEvents-DANQ5jIY.js.map → useYamlActivityEvents-CsaR5dWj.js.map} +1 -1
- package/dashboard/dist/assets/{users-vj0JgOkA.js → users-BvizpAkV.js} +2 -2
- package/dashboard/dist/assets/{users-vj0JgOkA.js.map → users-BvizpAkV.js.map} +1 -1
- package/dashboard/dist/assets/{workflows-CmqgGPzI.js → workflows-CyEYa01a.js} +2 -2
- package/dashboard/dist/assets/{workflows-CmqgGPzI.js.map → workflows-CyEYa01a.js.map} +1 -1
- package/dashboard/dist/assets/{yaml-workflows-DNFyjBXH.js → yaml-workflows-i3GzrEme.js} +2 -2
- package/dashboard/dist/assets/{yaml-workflows-DNFyjBXH.js.map → yaml-workflows-i3GzrEme.js.map} +1 -1
- package/dashboard/dist/index.html +1 -1
- package/docs/api/http/controlplane.md +6 -4
- package/docs/api/http/dba.md +1 -0
- package/docs/api/http/exports.md +26 -0
- package/docs/api/http/maintenance.md +1 -0
- package/docs/api/http/mcp-endpoint.md +68 -0
- package/docs/api/mcp/admin.md +7 -7
- package/docs/api/sdk/controlplane.md +4 -4
- package/package.json +1 -1
- package/dashboard/dist/assets/HomePage-B2Jgo1J1.js +0 -2
- package/dashboard/dist/assets/HomePage-B2Jgo1J1.js.map +0 -1
- package/dashboard/dist/assets/McpOverview-BzyxJyc9.js +0 -2
- package/dashboard/dist/assets/McpOverview-BzyxJyc9.js.map +0 -1
- package/dashboard/dist/assets/McpQueryDetailPage-DXNseeKl.js +0 -5
- package/dashboard/dist/assets/McpQueryDetailPage-DXNseeKl.js.map +0 -1
- package/dashboard/dist/assets/McpRunDetailPage-DKZp-p7S.js +0 -2
- package/dashboard/dist/assets/McpRunDetailPage-DKZp-p7S.js.map +0 -1
- package/dashboard/dist/assets/McpRunsPage-SXyiwc0d.js +0 -2
- package/dashboard/dist/assets/McpRunsPage-SXyiwc0d.js.map +0 -1
- package/dashboard/dist/assets/RolesPage-pMERxj15.js +0 -2
- package/dashboard/dist/assets/RolesPage-pMERxj15.js.map +0 -1
- package/dashboard/dist/assets/TimeAgo-BSzN6rAH.js +0 -2
- package/dashboard/dist/assets/ToolTestPanel-fLzNp79U.js +0 -2
- package/dashboard/dist/assets/ToolTestPanel-fLzNp79U.js.map +0 -1
- package/dashboard/dist/assets/WorkflowsDashboard-D-G8Xudz.js +0 -2
- package/dashboard/dist/assets/WorkflowsDashboard-D-G8Xudz.js.map +0 -1
- package/dashboard/dist/assets/YamlWorkflowsPage-CnTNOku0.js +0 -2
- package/dashboard/dist/assets/YamlWorkflowsPage-CnTNOku0.js.map +0 -1
- package/dashboard/dist/assets/capabilities-CbGmS0ty.js +0 -2
- package/dashboard/dist/assets/index-BeLphL59.js +0 -2
- package/dashboard/dist/assets/index-DDlrQeTj.js +0 -2
- package/dashboard/dist/assets/index-DDlrQeTj.js.map +0 -1
- package/dashboard/dist/assets/index-DQHmfTPo.js +0 -2
- package/dashboard/dist/assets/namespaces-DtsT_GoV.js +0 -2
- package/dashboard/dist/assets/namespaces-DtsT_GoV.js.map +0 -1
- package/dashboard/dist/assets/pipelines-BjlCm9VH.js +0 -2
- package/dashboard/dist/assets/pipelines-BjlCm9VH.js.map +0 -1
package/build/api/dba.d.ts
CHANGED
|
@@ -19,6 +19,7 @@ import type { LTApiResult } from '../types/sdk';
|
|
|
19
19
|
* @returns `{ status: 200, data: <prune result summary> }`
|
|
20
20
|
*/
|
|
21
21
|
export declare function prune(input: {
|
|
22
|
+
appId: string;
|
|
22
23
|
expire?: string;
|
|
23
24
|
jobs?: boolean;
|
|
24
25
|
streams?: boolean;
|
|
@@ -39,4 +40,4 @@ export declare function prune(input: {
|
|
|
39
40
|
*
|
|
40
41
|
* @returns `{ status: 200, data: { ok: true } }`
|
|
41
42
|
*/
|
|
42
|
-
export declare function deploy(): Promise<LTApiResult>;
|
|
43
|
+
export declare function deploy(appId: string): Promise<LTApiResult>;
|
package/build/api/dba.js
CHANGED
|
@@ -58,6 +58,7 @@ const dbaService = __importStar(require("../services/dba"));
|
|
|
58
58
|
async function prune(input) {
|
|
59
59
|
try {
|
|
60
60
|
const result = await dbaService.prune({
|
|
61
|
+
appId: input.appId,
|
|
61
62
|
expire: input.expire,
|
|
62
63
|
jobs: input.jobs,
|
|
63
64
|
streams: input.streams,
|
|
@@ -84,9 +85,9 @@ async function prune(input) {
|
|
|
84
85
|
*
|
|
85
86
|
* @returns `{ status: 200, data: { ok: true } }`
|
|
86
87
|
*/
|
|
87
|
-
async function deploy() {
|
|
88
|
+
async function deploy(appId) {
|
|
88
89
|
try {
|
|
89
|
-
await dbaService.deploy();
|
|
90
|
+
await dbaService.deploy(appId);
|
|
90
91
|
return { status: 200, data: { ok: true } };
|
|
91
92
|
}
|
|
92
93
|
catch (err) {
|
package/build/api/exports.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ import type { ExportMode } from '@hotmeshio/hotmesh/build/types/exporter';
|
|
|
15
15
|
* @returns `{ status: 200, data: { jobs, total, ... } }` on success
|
|
16
16
|
*/
|
|
17
17
|
export declare function listJobs(input: {
|
|
18
|
+
app_id: string;
|
|
18
19
|
limit?: number;
|
|
19
20
|
offset?: number;
|
|
20
21
|
entity?: string;
|
package/build/api/exports.js
CHANGED
|
@@ -55,7 +55,7 @@ const resolve_1 = require("../services/task/resolve");
|
|
|
55
55
|
*/
|
|
56
56
|
async function listJobs(input) {
|
|
57
57
|
try {
|
|
58
|
-
const result = await exportService.listJobs(input);
|
|
58
|
+
const result = await exportService.listJobs(input.app_id, input);
|
|
59
59
|
return { status: 200, data: result };
|
|
60
60
|
}
|
|
61
61
|
catch (err) {
|
|
@@ -17,6 +17,7 @@ export declare function getMaintenanceConfig(): LTApiResult;
|
|
|
17
17
|
* @returns `{ status: 200, data: { config, restarted: true } }`
|
|
18
18
|
*/
|
|
19
19
|
export declare function updateMaintenanceConfig(input: {
|
|
20
|
+
appId: string;
|
|
20
21
|
schedule: string;
|
|
21
22
|
rules: LTMaintenanceConfig['rules'];
|
|
22
23
|
}): Promise<LTApiResult>;
|
package/build/api/maintenance.js
CHANGED
|
@@ -26,11 +26,11 @@ function getMaintenanceConfig() {
|
|
|
26
26
|
*/
|
|
27
27
|
async function updateMaintenanceConfig(input) {
|
|
28
28
|
try {
|
|
29
|
-
if (!input.schedule || !Array.isArray(input.rules)) {
|
|
30
|
-
return { status: 400, error: 'schedule (string) and rules (array) are required' };
|
|
29
|
+
if (!input.appId || !input.schedule || !Array.isArray(input.rules)) {
|
|
30
|
+
return { status: 400, error: 'appId (string), schedule (string), and rules (array) are required' };
|
|
31
31
|
}
|
|
32
32
|
await maintenance_1.maintenanceRegistry.disconnect();
|
|
33
|
-
maintenance_1.maintenanceRegistry.register({ schedule: input.schedule, rules: input.rules });
|
|
33
|
+
maintenance_1.maintenanceRegistry.register({ appId: input.appId, schedule: input.schedule, rules: input.rules });
|
|
34
34
|
await maintenance_1.maintenanceRegistry.connect();
|
|
35
35
|
return {
|
|
36
36
|
status: 200,
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.overview = overview;
|
|
4
|
+
const overview_1 = require("../services/overview");
|
|
5
|
+
async function overview(input) {
|
|
6
|
+
try {
|
|
7
|
+
const data = await (0, overview_1.getSystemOverview)(input.period);
|
|
8
|
+
return { status: 200, data };
|
|
9
|
+
}
|
|
10
|
+
catch (err) {
|
|
11
|
+
return { status: 500, error: err.message };
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -41,6 +41,7 @@ const cron_1 = require("../../services/cron");
|
|
|
41
41
|
const db_1 = require("../../lib/db");
|
|
42
42
|
const registry_1 = require("../../services/workers/registry");
|
|
43
43
|
const sql_1 = require("../../services/pipelines/sql");
|
|
44
|
+
const hotmesh_utils_1 = require("../../services/hotmesh-utils");
|
|
44
45
|
/**
|
|
45
46
|
* List active workflow workers with their registration status.
|
|
46
47
|
*
|
|
@@ -81,9 +82,11 @@ async function listDiscoveredWorkflows(input) {
|
|
|
81
82
|
try {
|
|
82
83
|
// 1. Active workers from in-memory registry
|
|
83
84
|
const activeWorkers = (0, registry_1.getRegisteredWorkers)();
|
|
84
|
-
// 2. Historical entities from
|
|
85
|
+
// 2. Historical entities from jobs table
|
|
85
86
|
const pool = (0, db_1.getPool)();
|
|
86
|
-
|
|
87
|
+
// TODO: accept app_id parameter to avoid hardcoded schema
|
|
88
|
+
const schema = (0, hotmesh_utils_1.quoteSchema)((0, hotmesh_utils_1.sanitizeAppId)('durable'));
|
|
89
|
+
const { rows: entityRows } = await pool.query((0, sql_1.DISTINCT_ENTITIES)(schema));
|
|
87
90
|
const historicalEntities = new Set(entityRows.map((r) => r.entity));
|
|
88
91
|
// 3. Registered configs
|
|
89
92
|
const configs = await configService.listWorkflowConfigs();
|
|
@@ -39,8 +39,8 @@ const api = __importStar(require("../api/controlplane"));
|
|
|
39
39
|
const router = (0, express_1.Router)();
|
|
40
40
|
/**
|
|
41
41
|
* GET /api/controlplane/apps
|
|
42
|
-
* List available HotMesh application
|
|
43
|
-
*
|
|
42
|
+
* List available HotMesh application namespaces.
|
|
43
|
+
* Builder-only.
|
|
44
44
|
*/
|
|
45
45
|
router.get('/apps', auth_1.requireBuilder, async (_req, res) => {
|
|
46
46
|
const result = await api.listApps();
|
|
@@ -49,11 +49,16 @@ router.get('/apps', auth_1.requireBuilder, async (_req, res) => {
|
|
|
49
49
|
/**
|
|
50
50
|
* GET /api/controlplane/rollcall?app_id=durable&delay=1000
|
|
51
51
|
* Execute a roll call — discovers all engines and workers.
|
|
52
|
-
*
|
|
52
|
+
* Builder-only. app_id is required.
|
|
53
53
|
*/
|
|
54
54
|
router.get('/rollcall', auth_1.requireBuilder, async (req, res) => {
|
|
55
|
+
const appId = req.query.app_id;
|
|
56
|
+
if (!appId) {
|
|
57
|
+
res.status(400).json({ error: 'app_id query parameter is required' });
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
55
60
|
const result = await api.rollCall({
|
|
56
|
-
appId
|
|
61
|
+
appId,
|
|
57
62
|
delay: req.query.delay ? parseInt(req.query.delay, 10) : undefined,
|
|
58
63
|
});
|
|
59
64
|
res.status(result.status).json(result.data ?? { error: result.error });
|
|
@@ -61,27 +66,32 @@ router.get('/rollcall', auth_1.requireBuilder, async (req, res) => {
|
|
|
61
66
|
/**
|
|
62
67
|
* POST /api/controlplane/throttle
|
|
63
68
|
* Apply a throttle command to the mesh.
|
|
64
|
-
*
|
|
69
|
+
* Builder-only. appId is required in body.
|
|
65
70
|
*
|
|
66
71
|
* Body: { appId: string, throttle: number, topic?: string, guid?: string }
|
|
67
|
-
* throttle: ms delay (-1 = pause, 0 = resume, >0 = delay per msg)
|
|
68
72
|
*/
|
|
69
73
|
router.post('/throttle', auth_1.requireBuilder, async (req, res) => {
|
|
70
|
-
const { appId
|
|
74
|
+
const { appId, throttle, topic, guid, scope } = req.body;
|
|
75
|
+
if (!appId) {
|
|
76
|
+
res.status(400).json({ error: 'appId is required' });
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
71
79
|
const result = await api.applyThrottle({ appId, throttle, topic, guid, scope });
|
|
72
80
|
res.status(result.status).json(result.data ?? { error: result.error });
|
|
73
81
|
});
|
|
74
82
|
/**
|
|
75
|
-
* GET /api/controlplane/streams?app_id=durable&duration=1h
|
|
76
|
-
* Stream processing statistics
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
* duration: 15m | 30m | 1h | 1d | 7d (default: 1h)
|
|
80
|
-
* stream: optional stream_name filter (specific task queue topic)
|
|
83
|
+
* GET /api/controlplane/streams?app_id=durable&duration=1h
|
|
84
|
+
* Stream processing statistics.
|
|
85
|
+
* Builder-only. app_id is required.
|
|
81
86
|
*/
|
|
82
87
|
router.get('/streams', auth_1.requireBuilder, async (req, res) => {
|
|
88
|
+
const app_id = req.query.app_id;
|
|
89
|
+
if (!app_id) {
|
|
90
|
+
res.status(400).json({ error: 'app_id query parameter is required' });
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
83
93
|
const result = await api.getStreamStats({
|
|
84
|
-
app_id
|
|
94
|
+
app_id,
|
|
85
95
|
duration: req.query.duration || '1h',
|
|
86
96
|
stream: req.query.stream || undefined,
|
|
87
97
|
});
|
|
@@ -89,18 +99,19 @@ router.get('/streams', auth_1.requireBuilder, async (req, res) => {
|
|
|
89
99
|
});
|
|
90
100
|
/**
|
|
91
101
|
* GET /api/controlplane/stream-messages?namespace=durable&source=worker
|
|
92
|
-
* &limit=25&offset=0&sort_by=created_at&order=desc
|
|
93
|
-
* &status=pending&stream_name=hmsh:durable:w:&msg_type=WORKER
|
|
94
|
-
*
|
|
95
102
|
* Browse stream messages with pagination, filtering, and sorting.
|
|
96
|
-
*
|
|
97
|
-
* are separate tables with different schemas.
|
|
98
|
-
* Admin-only.
|
|
103
|
+
* Builder-only. namespace and source are required.
|
|
99
104
|
*/
|
|
100
105
|
router.get('/stream-messages', auth_1.requireBuilder, async (req, res) => {
|
|
106
|
+
const namespace = req.query.namespace;
|
|
107
|
+
const source = req.query.source;
|
|
108
|
+
if (!namespace || !source) {
|
|
109
|
+
res.status(400).json({ error: 'namespace and source query parameters are required' });
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
101
112
|
const result = await api.listStreamMessages({
|
|
102
|
-
namespace
|
|
103
|
-
source
|
|
113
|
+
namespace,
|
|
114
|
+
source,
|
|
104
115
|
limit: req.query.limit ? parseInt(req.query.limit, 10) : undefined,
|
|
105
116
|
offset: req.query.offset ? parseInt(req.query.offset, 10) : undefined,
|
|
106
117
|
sort_by: req.query.sort_by || undefined,
|
|
@@ -117,15 +128,15 @@ router.get('/stream-messages', auth_1.requireBuilder, async (req, res) => {
|
|
|
117
128
|
});
|
|
118
129
|
/**
|
|
119
130
|
* POST /api/controlplane/subscribe
|
|
120
|
-
* Start the quorum→NATS bridge for
|
|
121
|
-
*
|
|
122
|
-
* all control plane messages to NATS on `lt.mesh.*` topics.
|
|
123
|
-
* Admin-only.
|
|
124
|
-
*
|
|
125
|
-
* Body: { appId: string }
|
|
131
|
+
* Start the quorum→NATS bridge for a namespace.
|
|
132
|
+
* Builder-only. appId is required in body.
|
|
126
133
|
*/
|
|
127
134
|
router.post('/subscribe', auth_1.requireBuilder, async (req, res) => {
|
|
128
|
-
const { appId
|
|
135
|
+
const { appId } = req.body;
|
|
136
|
+
if (!appId) {
|
|
137
|
+
res.status(400).json({ error: 'appId is required' });
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
129
140
|
const result = await api.subscribeMesh({ appId });
|
|
130
141
|
res.status(result.status).json(result.data ?? { error: result.error });
|
|
131
142
|
});
|
package/build/routes/dba.js
CHANGED
|
@@ -53,7 +53,13 @@ const router = (0, express_1.Router)();
|
|
|
53
53
|
* Returns: { jobs, streams, attributes, transient, marked }
|
|
54
54
|
*/
|
|
55
55
|
router.post('/prune', auth_1.requireAdmin, async (req, res) => {
|
|
56
|
+
const appId = req.body.app_id;
|
|
57
|
+
if (!appId) {
|
|
58
|
+
res.status(400).json({ error: 'app_id is required' });
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
56
61
|
const result = await api.prune({
|
|
62
|
+
appId,
|
|
57
63
|
expire: req.body.expire,
|
|
58
64
|
jobs: req.body.jobs,
|
|
59
65
|
streams: req.body.streams,
|
|
@@ -73,8 +79,13 @@ router.post('/prune', auth_1.requireAdmin, async (req, res) => {
|
|
|
73
79
|
* Deploy the server-side prune function and run migrations.
|
|
74
80
|
* Idempotent — safe to call on startup or from CI/CD.
|
|
75
81
|
*/
|
|
76
|
-
router.post('/deploy', auth_1.requireAdmin, async (
|
|
77
|
-
const
|
|
82
|
+
router.post('/deploy', auth_1.requireAdmin, async (req, res) => {
|
|
83
|
+
const appId = req.body.app_id;
|
|
84
|
+
if (!appId) {
|
|
85
|
+
res.status(400).json({ error: 'app_id is required' });
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
const result = await api.deploy(appId);
|
|
78
89
|
res.status(result.status).json(result.data ?? { error: result.error });
|
|
79
90
|
});
|
|
80
91
|
exports.default = router;
|
package/build/routes/exports.js
CHANGED
|
@@ -41,7 +41,13 @@ const router = (0, express_1.Router)();
|
|
|
41
41
|
* List workflow jobs with optional filtering and pagination.
|
|
42
42
|
*/
|
|
43
43
|
router.get('/jobs', async (req, res) => {
|
|
44
|
+
const app_id = (req.query.app_id || req.query.namespace);
|
|
45
|
+
if (!app_id) {
|
|
46
|
+
res.status(400).json({ error: 'app_id (or namespace) query parameter is required' });
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
44
49
|
const result = await api.listJobs({
|
|
50
|
+
app_id,
|
|
45
51
|
limit: parseInt(req.query.limit) || undefined,
|
|
46
52
|
offset: parseInt(req.query.offset) || undefined,
|
|
47
53
|
entity: req.query.entity || undefined,
|
package/build/routes/index.js
CHANGED
|
@@ -68,4 +68,6 @@ router.use('/knowledge', knowledge_1.default);
|
|
|
68
68
|
router.use('/agents', agents_1.default);
|
|
69
69
|
router.use('/capabilities', capabilities_1.default);
|
|
70
70
|
router.use('/topics', topics_1.default);
|
|
71
|
+
const overview_1 = __importDefault(require("./overview"));
|
|
72
|
+
router.use('/overview', overview_1.default);
|
|
71
73
|
exports.default = router;
|
|
@@ -54,6 +54,7 @@ router.get('/', (_req, res) => {
|
|
|
54
54
|
*/
|
|
55
55
|
router.put('/', auth_1.requireAdmin, async (req, res) => {
|
|
56
56
|
const result = await api.updateMaintenanceConfig({
|
|
57
|
+
appId: req.body?.appId ?? req.body?.app_id,
|
|
57
58
|
schedule: req.body?.schedule,
|
|
58
59
|
rules: req.body?.rules,
|
|
59
60
|
});
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
const express_1 = require("express");
|
|
37
|
+
const api = __importStar(require("../api/overview"));
|
|
38
|
+
const router = (0, express_1.Router)();
|
|
39
|
+
/**
|
|
40
|
+
* GET /api/overview?period=24h
|
|
41
|
+
* System overview — triage, throughput, trends, infrastructure, processes.
|
|
42
|
+
* Any authenticated user can call this.
|
|
43
|
+
*/
|
|
44
|
+
router.get('/', async (req, res) => {
|
|
45
|
+
const result = await api.overview({
|
|
46
|
+
period: req.query.period || undefined,
|
|
47
|
+
});
|
|
48
|
+
res.status(result.status).json(result.data ?? { error: result.error });
|
|
49
|
+
});
|
|
50
|
+
exports.default = router;
|
|
@@ -91,10 +91,12 @@ async function getStreamStats(schema, duration = '1h', streamName) {
|
|
|
91
91
|
throw new Error(`Invalid duration: ${duration}`);
|
|
92
92
|
const pool = (0, db_1.getPool)();
|
|
93
93
|
const stream = streamName || null;
|
|
94
|
+
// Graceful degradation: HotMesh schema may not exist if no engine has started.
|
|
95
|
+
const emptyCount = { rows: [{ count: 0 }] };
|
|
94
96
|
const [pendingRes, processedRes, byStreamRes] = await Promise.all([
|
|
95
|
-
pool.query((0, sql_1.COUNT_PENDING)(schema), [stream]),
|
|
96
|
-
pool.query((0, sql_1.COUNT_PROCESSED_SINCE)(schema), [interval, stream]),
|
|
97
|
-
pool.query((0, sql_1.VOLUME_BY_STREAM)(schema), [interval, stream]),
|
|
97
|
+
pool.query((0, sql_1.COUNT_PENDING)(schema), [stream]).catch(() => emptyCount),
|
|
98
|
+
pool.query((0, sql_1.COUNT_PROCESSED_SINCE)(schema), [interval, stream]).catch(() => emptyCount),
|
|
99
|
+
pool.query((0, sql_1.VOLUME_BY_STREAM)(schema), [interval, stream]).catch(() => ({ rows: [] })),
|
|
98
100
|
]);
|
|
99
101
|
return {
|
|
100
102
|
pending: pendingRes.rows[0]?.count ?? 0,
|
|
@@ -131,8 +133,8 @@ async function getStreamMessages(schema, params) {
|
|
|
131
133
|
const queryParams = [streamName, status, msgType, topic, workflowName, jid, aid, limit, offset];
|
|
132
134
|
const countParams = [streamName, status, msgType, topic, workflowName, jid, aid];
|
|
133
135
|
const [messagesRes, countRes] = await Promise.all([
|
|
134
|
-
pool.query((0, stream_messages_sql_1.LIST_STREAM_MESSAGES)(schema, sortColumn, sortOrder, source), queryParams),
|
|
135
|
-
pool.query((0, stream_messages_sql_1.COUNT_STREAM_MESSAGES)(schema, source), countParams),
|
|
136
|
+
pool.query((0, stream_messages_sql_1.LIST_STREAM_MESSAGES)(schema, sortColumn, sortOrder, source), queryParams).catch(() => ({ rows: [] })),
|
|
137
|
+
pool.query((0, stream_messages_sql_1.COUNT_STREAM_MESSAGES)(schema, source), countParams).catch(() => ({ rows: [{ count: 0 }] })),
|
|
136
138
|
]);
|
|
137
139
|
return {
|
|
138
140
|
messages: messagesRes.rows,
|
package/build/services/dba.d.ts
CHANGED
|
@@ -4,10 +4,11 @@ import type { PruneOptions, PruneResult } from '@hotmeshio/hotmesh/build/types/d
|
|
|
4
4
|
* any schema migrations (e.g. adding the `pruned_at` column).
|
|
5
5
|
* Idempotent — safe to call on every startup.
|
|
6
6
|
*/
|
|
7
|
-
export declare function deploy(): Promise<void>;
|
|
7
|
+
export declare function deploy(appId: string): Promise<void>;
|
|
8
8
|
/**
|
|
9
9
|
* Prune expired jobs, streams, and/or execution artifacts.
|
|
10
10
|
*
|
|
11
|
+
* - `appId` — HotMesh application namespace (required)
|
|
11
12
|
* - `jobs` — hard-delete expired job rows older than `expire`
|
|
12
13
|
* - `streams` — hard-delete expired stream messages (engine + worker) older than `expire`
|
|
13
14
|
* - `attributes` — strip execution artifacts from completed jobs
|
|
@@ -17,6 +18,7 @@ export declare function deploy(): Promise<void>;
|
|
|
17
18
|
* - `keepHmark` — preserve hmark rows during stripping
|
|
18
19
|
*/
|
|
19
20
|
export declare function prune(options: {
|
|
21
|
+
appId: string;
|
|
20
22
|
expire?: string;
|
|
21
23
|
jobs?: boolean;
|
|
22
24
|
streams?: boolean;
|
package/build/services/dba.js
CHANGED
|
@@ -4,18 +4,18 @@ exports.deploy = deploy;
|
|
|
4
4
|
exports.prune = prune;
|
|
5
5
|
const hotmesh_1 = require("@hotmeshio/hotmesh");
|
|
6
6
|
const db_1 = require("../lib/db");
|
|
7
|
-
const APP_ID = 'durable';
|
|
8
7
|
/**
|
|
9
8
|
* Deploy the server-side prune() Postgres function and run
|
|
10
9
|
* any schema migrations (e.g. adding the `pruned_at` column).
|
|
11
10
|
* Idempotent — safe to call on every startup.
|
|
12
11
|
*/
|
|
13
|
-
async function deploy() {
|
|
14
|
-
await hotmesh_1.DBA.deploy((0, db_1.getConnection)(),
|
|
12
|
+
async function deploy(appId) {
|
|
13
|
+
await hotmesh_1.DBA.deploy((0, db_1.getConnection)(), appId);
|
|
15
14
|
}
|
|
16
15
|
/**
|
|
17
16
|
* Prune expired jobs, streams, and/or execution artifacts.
|
|
18
17
|
*
|
|
18
|
+
* - `appId` — HotMesh application namespace (required)
|
|
19
19
|
* - `jobs` — hard-delete expired job rows older than `expire`
|
|
20
20
|
* - `streams` — hard-delete expired stream messages (engine + worker) older than `expire`
|
|
21
21
|
* - `attributes` — strip execution artifacts from completed jobs
|
|
@@ -25,5 +25,6 @@ async function deploy() {
|
|
|
25
25
|
* - `keepHmark` — preserve hmark rows during stripping
|
|
26
26
|
*/
|
|
27
27
|
async function prune(options) {
|
|
28
|
-
|
|
28
|
+
const { appId, ...rest } = options;
|
|
29
|
+
return hotmesh_1.DBA.prune({ appId, connection: (0, db_1.getConnection)(), ...rest });
|
|
29
30
|
}
|
|
@@ -33,7 +33,7 @@ export declare function getWorkflowState(workflowId: string, taskQueue: string,
|
|
|
33
33
|
state: Record<string, any>;
|
|
34
34
|
}>;
|
|
35
35
|
/**
|
|
36
|
-
* List workflow jobs from
|
|
36
|
+
* List workflow jobs from {schema}.jobs where entity IS NOT NULL.
|
|
37
37
|
* Returns paginated results sorted by active first, then created_at DESC.
|
|
38
38
|
*/
|
|
39
|
-
export declare function listJobs(params: JobListParams): Promise<JobListResult>;
|
|
39
|
+
export declare function listJobs(app_id: string, params: JobListParams): Promise<JobListResult>;
|
|
@@ -6,6 +6,7 @@ exports.exportWorkflowExecution = exportWorkflowExecution;
|
|
|
6
6
|
exports.getWorkflowState = getWorkflowState;
|
|
7
7
|
exports.listJobs = listJobs;
|
|
8
8
|
const db_1 = require("../../lib/db");
|
|
9
|
+
const hotmesh_utils_1 = require("../hotmesh-utils");
|
|
9
10
|
const client_1 = require("./client");
|
|
10
11
|
const post_process_1 = require("./post-process");
|
|
11
12
|
/** Error thrown when a workflow job is not found (expired or never existed). */
|
|
@@ -131,10 +132,13 @@ function buildJobOrderBy(sortBy, order) {
|
|
|
131
132
|
return `j.${sortBy} ${dir}`;
|
|
132
133
|
}
|
|
133
134
|
/**
|
|
134
|
-
* List workflow jobs from
|
|
135
|
+
* List workflow jobs from {schema}.jobs where entity IS NOT NULL.
|
|
135
136
|
* Returns paginated results sorted by active first, then created_at DESC.
|
|
136
137
|
*/
|
|
137
|
-
async function listJobs(params) {
|
|
138
|
+
async function listJobs(app_id, params) {
|
|
139
|
+
const appId = (0, hotmesh_utils_1.sanitizeAppId)(app_id);
|
|
140
|
+
const schema = (0, hotmesh_utils_1.quoteSchema)(appId);
|
|
141
|
+
const keyPrefix = `hmsh:${appId}:j:`;
|
|
138
142
|
const limit = Math.min(params.limit ?? 20, 100);
|
|
139
143
|
const offset = params.offset ?? 0;
|
|
140
144
|
const pool = (0, db_1.getPool)();
|
|
@@ -172,11 +176,13 @@ async function listJobs(params) {
|
|
|
172
176
|
conditions.push('j.status < 0');
|
|
173
177
|
}
|
|
174
178
|
const where = conditions.join(' AND ');
|
|
179
|
+
// Graceful degradation: schema may not exist if no engine has started.
|
|
180
|
+
const emptyCount = { rows: [{ count: '0' }] };
|
|
175
181
|
const [countResult, dataResult] = await Promise.all([
|
|
176
|
-
pool.query(`SELECT COUNT(*) FROM
|
|
182
|
+
pool.query(`SELECT COUNT(*) FROM ${schema}.jobs j WHERE ${where}`, values).catch(() => emptyCount),
|
|
177
183
|
pool.query(`WITH ju_symbols AS (
|
|
178
|
-
SELECT value FROM
|
|
179
|
-
WHERE key LIKE 'hmsh:
|
|
184
|
+
SELECT value FROM ${schema}.symbols
|
|
185
|
+
WHERE key LIKE 'hmsh:${appId}:sym:keys:%' AND field = 'metadata/ju'
|
|
180
186
|
)
|
|
181
187
|
SELECT j.key, j.entity, j.status, j.is_live, j.created_at,
|
|
182
188
|
CASE WHEN j.updated_at != j.created_at THEN j.updated_at
|
|
@@ -184,20 +190,20 @@ async function listJobs(params) {
|
|
|
184
190
|
ELSE j.updated_at
|
|
185
191
|
END as updated_at,
|
|
186
192
|
ws.id as set_id
|
|
187
|
-
FROM
|
|
188
|
-
LEFT JOIN
|
|
193
|
+
FROM ${schema}.jobs j
|
|
194
|
+
LEFT JOIN ${schema}.jobs_attributes ju
|
|
189
195
|
ON ju.job_id = j.id
|
|
190
196
|
AND ju.symbol IN (SELECT value FROM ju_symbols)
|
|
191
197
|
AND (ju.dimension IS NULL OR ju.dimension = '')
|
|
192
198
|
LEFT JOIN lt_workflow_sets ws
|
|
193
|
-
ON ws.source_workflow_id = REPLACE(j.key, '
|
|
199
|
+
ON ws.source_workflow_id = REPLACE(j.key, '${keyPrefix}', '')
|
|
194
200
|
AND j.entity = 'mcpWorkflowPlanner'
|
|
195
201
|
WHERE ${where}
|
|
196
202
|
ORDER BY ${buildJobOrderBy(params.sort_by, params.order)}
|
|
197
|
-
LIMIT $${idx++} OFFSET $${idx++}`, [...values, limit, offset]),
|
|
203
|
+
LIMIT $${idx++} OFFSET $${idx++}`, [...values, limit, offset]).catch(() => ({ rows: [] })),
|
|
198
204
|
]);
|
|
199
205
|
const jobs = dataResult.rows.map((row) => ({
|
|
200
|
-
workflow_id: row.key.replace(
|
|
206
|
+
workflow_id: row.key.replace(keyPrefix, ''),
|
|
201
207
|
entity: row.entity,
|
|
202
208
|
status: (row.status > 0 ? 'running' : row.status === 0 ? 'completed' : 'failed'),
|
|
203
209
|
is_live: row.is_live,
|
|
@@ -43,11 +43,12 @@ const CRON_ID = 'lt-maintenance-nightly';
|
|
|
43
43
|
/**
|
|
44
44
|
* Translate a single maintenance rule into the appropriate dbaService.prune() call.
|
|
45
45
|
*/
|
|
46
|
-
async function executeRule(rule) {
|
|
46
|
+
async function executeRule(appId, rule) {
|
|
47
47
|
switch (true) {
|
|
48
48
|
// Delete stream messages
|
|
49
49
|
case rule.target === 'streams' && rule.action === 'delete':
|
|
50
50
|
await dbaService.prune({
|
|
51
|
+
appId,
|
|
51
52
|
expire: rule.olderThan,
|
|
52
53
|
streams: true,
|
|
53
54
|
jobs: false,
|
|
@@ -56,6 +57,7 @@ async function executeRule(rule) {
|
|
|
56
57
|
// Delete transient jobs (entity IS NULL)
|
|
57
58
|
case rule.target === 'jobs' && rule.action === 'delete' && rule.hasEntity === false:
|
|
58
59
|
await dbaService.prune({
|
|
60
|
+
appId,
|
|
59
61
|
expire: rule.olderThan,
|
|
60
62
|
jobs: false,
|
|
61
63
|
streams: false,
|
|
@@ -65,6 +67,7 @@ async function executeRule(rule) {
|
|
|
65
67
|
// Strip execution artifacts from entity jobs (keep jdata/udata/jmark/hmark)
|
|
66
68
|
case rule.target === 'jobs' && rule.action === 'prune' && rule.hasEntity === true:
|
|
67
69
|
await dbaService.prune({
|
|
70
|
+
appId,
|
|
68
71
|
expire: rule.olderThan,
|
|
69
72
|
jobs: false,
|
|
70
73
|
streams: false,
|
|
@@ -75,6 +78,7 @@ async function executeRule(rule) {
|
|
|
75
78
|
// Hard-delete old pruned jobs
|
|
76
79
|
case rule.target === 'jobs' && rule.action === 'delete' && rule.pruned === true:
|
|
77
80
|
await dbaService.prune({
|
|
81
|
+
appId,
|
|
78
82
|
expire: rule.olderThan,
|
|
79
83
|
jobs: true,
|
|
80
84
|
streams: false,
|
|
@@ -112,8 +116,7 @@ class LTMaintenanceRegistry {
|
|
|
112
116
|
async connect() {
|
|
113
117
|
if (this.connected || !this._config)
|
|
114
118
|
return;
|
|
115
|
-
const rules = this._config
|
|
116
|
-
const schedule = this._config.schedule;
|
|
119
|
+
const { appId, rules, schedule } = this._config;
|
|
117
120
|
const connection = (0, db_1.getConnection)();
|
|
118
121
|
await hotmesh_1.Virtual.cron({
|
|
119
122
|
topic: CRON_TOPIC,
|
|
@@ -122,7 +125,7 @@ class LTMaintenanceRegistry {
|
|
|
122
125
|
logger_1.loggerRegistry.info('[lt-maintenance] starting maintenance cycle...');
|
|
123
126
|
for (const rule of rules) {
|
|
124
127
|
try {
|
|
125
|
-
await executeRule(rule);
|
|
128
|
+
await executeRule(appId, rule);
|
|
126
129
|
}
|
|
127
130
|
catch (err) {
|
|
128
131
|
logger_1.loggerRegistry.error(`[lt-maintenance] rule failed: ${JSON.stringify(rule)} ${err?.message}`);
|