@gadmin2n/schematics 0.0.72 → 0.0.74
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/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/config/prisma/job.prisma +62 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/config/prisma/system.prisma +0 -21
- package/dist/lib/application/files/gadmin2-game-angle-demo/config/prisma/workflow.prisma +171 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/AgendaJob.ts +60 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/Event.ts +1 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/WorkflowEventOutbox.ts +62 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/WorkflowNodeInstance.ts +62 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/WorkflowNodeType.ts +62 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/.env +5 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/package.json +5 -4
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/prisma.config.ts +14 -7
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/index.ts +4 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/permissions.ts +49 -3
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/workflow-node-types.ts +746 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/workflows.ts +786 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/agenda/agenda.controller.ts +6 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/agenda/agenda.service.ts +79 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/agendaJob/agendaJob.controller.spec.ts +20 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/agendaJob/agendaJob.controller.ts +145 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/agendaJob/agendaJob.module.ts +10 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/{canvas/canvas.service.spec.ts → agendaJob/agendaJob.service.spec.ts} +71 -65
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/agendaJob/agendaJob.service.ts +83 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/index.ts +2 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/temporal.module.ts +9 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/temporal.service.ts +100 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-execution.dto.ts +19 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-export.dto.ts +43 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-export.service.ts +317 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-node-type.controller.ts +16 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-node-type.service.ts +13 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.controller.ts +220 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.dto.ts +82 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.module.ts +16 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.service.ts +505 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowEventOutbox/workflowEventOutbox.controller.spec.ts +22 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowEventOutbox/workflowEventOutbox.controller.ts +147 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowEventOutbox/workflowEventOutbox.module.ts +10 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowEventOutbox/workflowEventOutbox.service.spec.ts +356 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowEventOutbox/workflowEventOutbox.service.ts +110 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeInstance/workflowNodeInstance.controller.spec.ts +22 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeInstance/workflowNodeInstance.controller.ts +216 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeInstance/workflowNodeInstance.module.ts +10 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeInstance/workflowNodeInstance.service.spec.ts +356 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeInstance/workflowNodeInstance.service.ts +168 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeType/workflowNodeType.controller.spec.ts +22 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeType/workflowNodeType.controller.ts +199 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeType/workflowNodeType.module.ts +10 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeType/workflowNodeType.service.spec.ts +348 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeType/workflowNodeType.service.ts +106 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/yarn.lock +579 -1082
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/README.md +278 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/config/development-sql.yaml +5 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/docker-compose.yml +25 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/package.json +13 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/sql/create-event-trigger.sql +87 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/.env +7 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/SANDBOX.md +122 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/package-lock.json +4285 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/package.json +28 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/__tests__/activities/code-execute.test.ts +44 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/__tests__/activities/http-request.test.ts +87 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/__tests__/helpers.test.ts +225 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/__tests__/node-type-consistency.test.ts +101 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/code-execute.ts +51 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/db-execute.ts +85 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/db-query.ts +35 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/http-request.ts +54 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/index.ts +6 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/reporting.ts +62 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/send-notification.ts +47 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/config.ts +13 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/condition.ts +101 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/context.ts +58 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/graph.ts +184 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/helpers.ts +133 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/node-types.ts +57 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/types.ts +77 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/index.ts +36 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/outbox-poller.ts +226 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/workflows/dsl-workflow.ts +411 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/tsconfig.json +19 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/vitest.config.ts +8 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/yarn.lock +1905 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/package-lock.json +17555 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/package.json +5 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/App.tsx +1 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/sider.tsx +5 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/title.tsx +1 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/config/routeRegistry.tsx +63 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/DevShell.tsx +91 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/list.tsx +48 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/show.tsx +43 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/en/common.json +14 -9
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/zh_CN/common.json +14 -9
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agenda/index.tsx +309 -56
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agenda/show.tsx +1 -3
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agendaJob/create.tsx +108 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agendaJob/edit.tsx +124 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agendaJob/index.tsx +4 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agendaJob/list.tsx +245 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agendaJob/show.tsx +70 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasListPage.tsx +0 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasPage.tsx +160 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasToolbar.tsx +120 -148
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CodeFloatWindow.tsx +74 -181
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/LivePreview.tsx +15 -13
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/canvasConfigRegistry.tsx +2 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/canvasContextMenuRegistry.tsx +338 -3
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/canvasDefaults.ts +18 -17
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/BarChartDataSourceModal.tsx +10 -4
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/LineChartDataSourceModal.tsx +10 -4
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/{ChartViewerConfigModal.tsx → MultiChartConfigModal.tsx} +30 -18
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/MultiChartDataSourceModal.tsx +427 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/NumCardDataSourceModal.tsx +10 -4
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/PromptModal.tsx +6 -14
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/RadarChartDataSourceModal.tsx +10 -4
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/TableDataSourceModal.tsx +10 -4
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/canvasModalProps.ts +24 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/demos.ts +45 -63
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/CustomNode.tsx +99 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/ExportModal.tsx +87 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/FlowRenderer.tsx +322 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/ImportModal.tsx +175 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NodeEditModal.tsx +60 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NodePropertyPanel.tsx +1150 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/RunWorkflowModal.tsx +101 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/StatusCards.tsx +198 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/VersionPanel.tsx +81 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/editor.tsx +566 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/hooks/useWorkflowAgent.ts +224 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/index.tsx +524 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/instance-detail.tsx +343 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/instances.tsx +243 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/components/CreateNodeInstanceModal.tsx +363 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/components/DynamicConfigForm.tsx +154 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/components/NodeInstanceForm.tsx +176 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/create.tsx +77 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/edit.tsx +112 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/index.tsx +305 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/show.tsx +282 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/show.tsx +469 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/types.ts +92 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/create.tsx +111 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/edit.tsx +127 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/index.tsx +4 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/list.tsx +254 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/show.tsx +74 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/yarn.lock +1501 -1199
- package/package.json +1 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/app.controller.spec.ts +0 -22
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/BarChart/index.tsx +0 -896
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/ChartSwitcher/index.tsx +0 -219
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/ChartViewer/index.tsx +0 -159
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/Filter/index.tsx +0 -192
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/LineChart/index.tsx +0 -1034
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/NumCard/NumCard.module.css +0 -8
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/NumCard/index.tsx +0 -509
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/NumLineCard/index.tsx +0 -66
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/PieChart/index.tsx +0 -552
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/RadarChart/index.tsx +0 -263
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/Section/index.tsx +0 -35
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/Table/index.tsx +0 -207
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/TreemapChart/index.tsx +0 -382
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/WorldMap/index.tsx +0 -135
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/chart-constants.ts +0 -53
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/icon/InfoIcon.tsx +0 -8
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/icon/index.ts +0 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/map/config.ts +0 -31
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/map/nameMap.json +0 -9
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/map/world.geo.json +0 -39349
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/metric-info-tooltip/index.tsx +0 -19
package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/node-types.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical list of all workflow node types.
|
|
3
|
+
*
|
|
4
|
+
* This is the SINGLE SOURCE OF TRUTH for node type strings.
|
|
5
|
+
* When you add a new type here, TypeScript will force you to handle it
|
|
6
|
+
* in the executeNode() switch — otherwise the build fails.
|
|
7
|
+
*/
|
|
8
|
+
export const ALL_NODE_TYPES = [
|
|
9
|
+
// TRIGGER
|
|
10
|
+
'cron_trigger',
|
|
11
|
+
'webhook_trigger',
|
|
12
|
+
'event_trigger',
|
|
13
|
+
'manual_trigger',
|
|
14
|
+
// ACTION (calls an activity)
|
|
15
|
+
'http_request',
|
|
16
|
+
'db_query',
|
|
17
|
+
'db_execute',
|
|
18
|
+
'send_notification',
|
|
19
|
+
'code',
|
|
20
|
+
// DATA PROCESSING (inline logic)
|
|
21
|
+
'set_variable',
|
|
22
|
+
// CONDITION (inline logic)
|
|
23
|
+
'if_else',
|
|
24
|
+
'switch',
|
|
25
|
+
// FLOW CONTROL
|
|
26
|
+
'for_each',
|
|
27
|
+
'delay',
|
|
28
|
+
'parallel',
|
|
29
|
+
'error_handler',
|
|
30
|
+
// APPROVAL (Temporal signal)
|
|
31
|
+
'approval',
|
|
32
|
+
// SUB WORKFLOW
|
|
33
|
+
'sub_workflow',
|
|
34
|
+
] as const;
|
|
35
|
+
|
|
36
|
+
/** Union of all supported node type strings. */
|
|
37
|
+
export type NodeType = (typeof ALL_NODE_TYPES)[number];
|
|
38
|
+
|
|
39
|
+
/** Node types that require a Temporal activity call. */
|
|
40
|
+
export const ACTIVITY_NODE_TYPES = [
|
|
41
|
+
'http_request',
|
|
42
|
+
'db_query',
|
|
43
|
+
'db_execute',
|
|
44
|
+
'send_notification',
|
|
45
|
+
'code',
|
|
46
|
+
] as const satisfies readonly NodeType[];
|
|
47
|
+
|
|
48
|
+
export type ActivityNodeType = (typeof ACTIVITY_NODE_TYPES)[number];
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Compile-time exhaustiveness check.
|
|
52
|
+
* Place in the `default` of a switch over NodeType — if a case is missing,
|
|
53
|
+
* TypeScript emits: "Argument of type 'X' is not assignable to parameter of type 'never'."
|
|
54
|
+
*/
|
|
55
|
+
export function assertNever(x: never): never {
|
|
56
|
+
throw new Error(`Unhandled node type: ${x}`);
|
|
57
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// ─── DSL Types (mirrors frontend WorkflowDSL) ─────────────────────────────────
|
|
2
|
+
|
|
3
|
+
import type { NodeType } from './node-types';
|
|
4
|
+
|
|
5
|
+
export interface DslNode {
|
|
6
|
+
id: string;
|
|
7
|
+
type: NodeType;
|
|
8
|
+
label: string;
|
|
9
|
+
position: { x: number; y: number };
|
|
10
|
+
config: Record<string, any>;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface DslEdge {
|
|
14
|
+
id: string;
|
|
15
|
+
source: string;
|
|
16
|
+
target: string;
|
|
17
|
+
sourceHandle?: string; // for condition branches: "true"/"false" or case labels
|
|
18
|
+
label?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface WorkflowDSL {
|
|
22
|
+
nodes: DslNode[];
|
|
23
|
+
edges: DslEdge[];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// ─── Workflow Execution Types ──────────────────────────────────────────────────
|
|
27
|
+
|
|
28
|
+
export interface WorkflowInput {
|
|
29
|
+
instanceId: number;
|
|
30
|
+
workflowId: number;
|
|
31
|
+
versionId: number;
|
|
32
|
+
dsl: WorkflowDSL;
|
|
33
|
+
context: Record<string, any>;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface WorkflowResult {
|
|
37
|
+
status: 'COMPLETED' | 'FAILED' | 'CANCELLED';
|
|
38
|
+
context: Record<string, any>;
|
|
39
|
+
error?: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// ─── Node Execution Context ───────────────────────────────────────────────────
|
|
43
|
+
|
|
44
|
+
export interface NodeExecutionResult {
|
|
45
|
+
output: Record<string, any>;
|
|
46
|
+
branch?: string; // For condition nodes: which branch to take
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export type NodeStatus = 'PENDING' | 'RUNNING' | 'COMPLETED' | 'FAILED' | 'CANCELLED';
|
|
50
|
+
|
|
51
|
+
// ─── Activity Input Types ─────────────────────────────────────────────────────
|
|
52
|
+
|
|
53
|
+
export interface ReportNodeStatusInput {
|
|
54
|
+
instanceId: number;
|
|
55
|
+
nodeId: string;
|
|
56
|
+
nodeType: string;
|
|
57
|
+
nodeLabel?: string;
|
|
58
|
+
status: NodeStatus;
|
|
59
|
+
input?: Record<string, any>;
|
|
60
|
+
output?: Record<string, any>;
|
|
61
|
+
error?: Record<string, any>;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface ReportWorkflowStatusInput {
|
|
65
|
+
instanceId: number;
|
|
66
|
+
status: 'RUNNING' | 'COMPLETED' | 'FAILED' | 'CANCELLED';
|
|
67
|
+
result?: Record<string, any>;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// ─── Signals ──────────────────────────────────────────────────────────────────
|
|
71
|
+
|
|
72
|
+
export interface ApprovalSignalPayload {
|
|
73
|
+
nodeId: string;
|
|
74
|
+
approved: boolean;
|
|
75
|
+
comment?: string;
|
|
76
|
+
approvedBy: string;
|
|
77
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { NativeConnection, Worker } from '@temporalio/worker';
|
|
2
|
+
import * as activities from './activities';
|
|
3
|
+
import { config } from './config';
|
|
4
|
+
import { startOutboxPoller } from './outbox-poller';
|
|
5
|
+
|
|
6
|
+
async function run() {
|
|
7
|
+
console.log(`[Worker] Connecting to Temporal at ${config.temporal.address}...`);
|
|
8
|
+
|
|
9
|
+
const connection = await NativeConnection.connect({
|
|
10
|
+
address: config.temporal.address,
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const worker = await Worker.create({
|
|
14
|
+
connection,
|
|
15
|
+
namespace: config.temporal.namespace,
|
|
16
|
+
taskQueue: config.temporal.taskQueue,
|
|
17
|
+
workflowsPath: require.resolve('./workflows/dsl-workflow'),
|
|
18
|
+
activities,
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
console.log(`[Worker] Started. Polling task queue: ${config.temporal.taskQueue}`);
|
|
22
|
+
console.log(`[Worker] Namespace: ${config.temporal.namespace}`);
|
|
23
|
+
|
|
24
|
+
// Start outbox poller for event_trigger workflows
|
|
25
|
+
startOutboxPoller().catch((err) => {
|
|
26
|
+
console.error('[OutboxPoller] Failed to start:', err.message);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
// Start polling for workflow tasks
|
|
30
|
+
await worker.run();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
run().catch((err) => {
|
|
34
|
+
console.error('[Worker] Fatal error:', err);
|
|
35
|
+
process.exit(1);
|
|
36
|
+
});
|
package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/outbox-poller.ts
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import { Client as PgClient } from "pg";
|
|
2
|
+
import { Client, Connection } from "@temporalio/client";
|
|
3
|
+
import { config } from "./config";
|
|
4
|
+
|
|
5
|
+
const POLL_INTERVAL = Number(process.env.EVENT_POLL_INTERVAL_MS) || 10_000; // 默认 10 秒
|
|
6
|
+
const BATCH_SIZE = 50;
|
|
7
|
+
const MAX_RETRIES = Number(process.env.OUTBOX_MAX_RETRIES) || 5;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Outbox Poller — 定时扫描 t_workflow_event_outbox 未处理事件,匹配并触发 workflow。
|
|
11
|
+
*
|
|
12
|
+
* 工作原理:
|
|
13
|
+
* 1. 业务表的 AFTER 触发器写入 outbox 行(同一事务,保证不丢)
|
|
14
|
+
* 2. 本轮询器每 N 秒扫描未处理行
|
|
15
|
+
* 3. 匹配 event_trigger workflow → 启动 Temporal 执行
|
|
16
|
+
* 4. 标记行为已处理
|
|
17
|
+
*/
|
|
18
|
+
export async function startOutboxPoller() {
|
|
19
|
+
const pg = new PgClient({ connectionString: config.database.url });
|
|
20
|
+
await pg.connect();
|
|
21
|
+
|
|
22
|
+
const temporalConn = await Connection.connect({
|
|
23
|
+
address: config.temporal.address,
|
|
24
|
+
});
|
|
25
|
+
const temporalClient = new Client({
|
|
26
|
+
connection: temporalConn,
|
|
27
|
+
namespace: config.temporal.namespace,
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
console.log(`[OutboxPoller] Started. Polling every ${POLL_INTERVAL}ms, max retries: ${MAX_RETRIES}`);
|
|
31
|
+
|
|
32
|
+
const poll = async () => {
|
|
33
|
+
try {
|
|
34
|
+
// 用 FOR UPDATE SKIP LOCKED 保证多实例不重复消费
|
|
35
|
+
const { rows } = await pg.query(
|
|
36
|
+
`UPDATE t_workflow_event_outbox
|
|
37
|
+
SET processed = TRUE, processed_at = NOW()
|
|
38
|
+
WHERE id IN (
|
|
39
|
+
SELECT id FROM t_workflow_event_outbox
|
|
40
|
+
WHERE processed = FALSE
|
|
41
|
+
ORDER BY created_at
|
|
42
|
+
LIMIT $1
|
|
43
|
+
FOR UPDATE SKIP LOCKED
|
|
44
|
+
)
|
|
45
|
+
RETURNING id, event_name, payload, retry_count`,
|
|
46
|
+
[BATCH_SIZE],
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
if (rows.length === 0) return;
|
|
50
|
+
console.log(`[OutboxPoller] Processing ${rows.length} events`);
|
|
51
|
+
|
|
52
|
+
for (const row of rows) {
|
|
53
|
+
try {
|
|
54
|
+
const matched = await matchAndTrigger(
|
|
55
|
+
pg,
|
|
56
|
+
temporalClient,
|
|
57
|
+
row.event_name,
|
|
58
|
+
row.payload,
|
|
59
|
+
);
|
|
60
|
+
if (matched === 0) {
|
|
61
|
+
console.warn(
|
|
62
|
+
`[OutboxPoller] No workflow matched event "${row.event_name}" (id=${row.id}). Event consumed without action.`,
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
} catch (err: any) {
|
|
66
|
+
const nextRetry = (row.retry_count ?? 0) + 1;
|
|
67
|
+
const errMsg = String(err?.message ?? err);
|
|
68
|
+
if (nextRetry >= MAX_RETRIES) {
|
|
69
|
+
// 终态失败:保持 processed=true,仅记录 retry_count + last_error,不再重试
|
|
70
|
+
console.error(
|
|
71
|
+
`[OutboxPoller] Event ${row.id} (${row.event_name}) failed ${nextRetry} times. Marking as terminal failure: ${errMsg}`,
|
|
72
|
+
);
|
|
73
|
+
await pg.query(
|
|
74
|
+
`UPDATE t_workflow_event_outbox
|
|
75
|
+
SET retry_count = $1, last_error = $2
|
|
76
|
+
WHERE id = $3`,
|
|
77
|
+
[nextRetry, errMsg, row.id],
|
|
78
|
+
);
|
|
79
|
+
} else {
|
|
80
|
+
console.error(
|
|
81
|
+
`[OutboxPoller] Event ${row.id} (${row.event_name}) failed (retry ${nextRetry}/${MAX_RETRIES}): ${errMsg}`,
|
|
82
|
+
);
|
|
83
|
+
// 标记回未处理,下次重试
|
|
84
|
+
await pg.query(
|
|
85
|
+
`UPDATE t_workflow_event_outbox
|
|
86
|
+
SET processed = FALSE, processed_at = NULL, retry_count = $1, last_error = $2
|
|
87
|
+
WHERE id = $3`,
|
|
88
|
+
[nextRetry, errMsg, row.id],
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
} catch (err: any) {
|
|
94
|
+
console.error("[OutboxPoller] Poll error:", err.message);
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
// 自调度循环:每次 poll 完成后再排下一次,避免 setInterval 在 poll 慢于 POLL_INTERVAL 时重叠调用
|
|
99
|
+
const loop = async () => {
|
|
100
|
+
try {
|
|
101
|
+
await poll();
|
|
102
|
+
} finally {
|
|
103
|
+
setTimeout(loop, POLL_INTERVAL);
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
loop();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* 查找监听该 eventName 的 workflow 并启动执行。
|
|
111
|
+
*
|
|
112
|
+
* @returns 实际匹配并启动的 workflow 数量;0 表示无人订阅。
|
|
113
|
+
*/
|
|
114
|
+
async function matchAndTrigger(
|
|
115
|
+
pg: PgClient,
|
|
116
|
+
temporalClient: Client,
|
|
117
|
+
eventName: string,
|
|
118
|
+
payload: Record<string, any>,
|
|
119
|
+
): Promise<number> {
|
|
120
|
+
// 查询所有已发布且启用的 workflow 的最新版本 DSL
|
|
121
|
+
const result = await pg.query(`
|
|
122
|
+
SELECT w.id AS workflow_id, wv.id AS version_id, wv.dsl
|
|
123
|
+
FROM t_workflow w
|
|
124
|
+
JOIN t_workflow_version wv ON wv.workflow_id = w.id
|
|
125
|
+
WHERE w.status = 'PUBLISHED'
|
|
126
|
+
AND w.is_enabled = true
|
|
127
|
+
AND wv.version = (
|
|
128
|
+
SELECT MAX(wv2.version)
|
|
129
|
+
FROM t_workflow_version wv2
|
|
130
|
+
WHERE wv2.workflow_id = w.id
|
|
131
|
+
)
|
|
132
|
+
`);
|
|
133
|
+
|
|
134
|
+
let matchedCount = 0;
|
|
135
|
+
|
|
136
|
+
for (const row of result.rows) {
|
|
137
|
+
const dsl = row.dsl;
|
|
138
|
+
if (!dsl?.nodes) continue;
|
|
139
|
+
|
|
140
|
+
// 找 event_trigger 节点且 eventName 匹配
|
|
141
|
+
const trigger = dsl.nodes.find(
|
|
142
|
+
(n: any) =>
|
|
143
|
+
n.type === "event_trigger" &&
|
|
144
|
+
matchEventName(n.config?.eventName, eventName),
|
|
145
|
+
);
|
|
146
|
+
if (!trigger) continue;
|
|
147
|
+
|
|
148
|
+
// 可选: filterExpression 过滤
|
|
149
|
+
if (trigger.config?.filterExpression) {
|
|
150
|
+
if (!evaluateFilter(trigger.config.filterExpression, payload)) continue;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// 创建 WorkflowInstance
|
|
154
|
+
const instance = await pg.query(
|
|
155
|
+
`INSERT INTO t_workflow_instance (workflow_id, version_id, status, context, creator, created_at, updated_at)
|
|
156
|
+
VALUES ($1, $2, 'PENDING', $3, 'event_trigger', NOW(), NOW())
|
|
157
|
+
RETURNING id`,
|
|
158
|
+
[row.workflow_id, row.version_id, JSON.stringify(payload)],
|
|
159
|
+
);
|
|
160
|
+
const instanceId = Number(instance.rows[0].id);
|
|
161
|
+
|
|
162
|
+
// 启动 Temporal workflow
|
|
163
|
+
const workflowId = `wf-${row.workflow_id}-${instanceId}`;
|
|
164
|
+
const handle = await temporalClient.workflow.start("dslWorkflow", {
|
|
165
|
+
taskQueue: config.temporal.taskQueue,
|
|
166
|
+
workflowId,
|
|
167
|
+
args: [
|
|
168
|
+
{
|
|
169
|
+
instanceId,
|
|
170
|
+
workflowId: Number(row.workflow_id),
|
|
171
|
+
versionId: Number(row.version_id),
|
|
172
|
+
dsl,
|
|
173
|
+
context: payload,
|
|
174
|
+
},
|
|
175
|
+
],
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
// 回写 temporal_run_id
|
|
179
|
+
await pg.query(
|
|
180
|
+
`UPDATE t_workflow_instance SET temporal_run_id = $1 WHERE id = $2`,
|
|
181
|
+
[handle.workflowId, instanceId],
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
console.log(
|
|
185
|
+
`[OutboxPoller] Triggered workflow ${row.workflow_id} for event "${eventName}", instance=${instanceId}`,
|
|
186
|
+
);
|
|
187
|
+
matchedCount++;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return matchedCount;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* 匹配事件名,支持通配符:
|
|
195
|
+
* - "t_order.insert" 精确匹配
|
|
196
|
+
* - "t_order.*" 匹配该表所有操作
|
|
197
|
+
* - "*.insert" 匹配所有表的 insert
|
|
198
|
+
*/
|
|
199
|
+
function matchEventName(pattern: string | undefined, actual: string): boolean {
|
|
200
|
+
if (!pattern) return false;
|
|
201
|
+
if (pattern === actual) return true;
|
|
202
|
+
if (pattern === "*") return true;
|
|
203
|
+
|
|
204
|
+
const [patTable, patOp] = pattern.split(".");
|
|
205
|
+
const [actTable, actOp] = actual.split(".");
|
|
206
|
+
|
|
207
|
+
const tableMatch = patTable === "*" || patTable === actTable;
|
|
208
|
+
const opMatch = !patOp || patOp === "*" || patOp === actOp;
|
|
209
|
+
|
|
210
|
+
return tableMatch && opMatch;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* 简单的 filter 表达式求值。
|
|
215
|
+
*/
|
|
216
|
+
function evaluateFilter(
|
|
217
|
+
expression: string,
|
|
218
|
+
payload: Record<string, any>,
|
|
219
|
+
): boolean {
|
|
220
|
+
try {
|
|
221
|
+
const fn = new Function("data", `return ${expression}`);
|
|
222
|
+
return !!fn(payload);
|
|
223
|
+
} catch {
|
|
224
|
+
return true;
|
|
225
|
+
}
|
|
226
|
+
}
|