@open-mercato/core 0.6.3-develop.3876.1.d40fe4ec2d → 0.6.3-develop.3894.1.352abf4240
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/.turbo/turbo-build.log +1 -1
- package/dist/modules/attachments/api/file/[id]/route.js +7 -2
- package/dist/modules/attachments/api/file/[id]/route.js.map +2 -2
- package/dist/modules/attachments/api/image/[id]/[[...slug]]/route.js +7 -4
- package/dist/modules/attachments/api/image/[id]/[[...slug]]/route.js.map +2 -2
- package/dist/modules/audit_logs/services/accessLogService.js +127 -8
- package/dist/modules/audit_logs/services/accessLogService.js.map +2 -2
- package/dist/modules/auth/backend/auth/profile/page.js +1 -1
- package/dist/modules/auth/backend/auth/profile/page.js.map +2 -2
- package/dist/modules/auth/backend/profile/change-password/page.js +1 -1
- package/dist/modules/auth/backend/profile/change-password/page.js.map +2 -2
- package/dist/modules/auth/backend/users/[id]/edit/page.js +1 -1
- package/dist/modules/auth/backend/users/[id]/edit/page.js.map +2 -2
- package/dist/modules/auth/backend/users/create/page.js +6 -1
- package/dist/modules/auth/backend/users/create/page.js.map +2 -2
- package/dist/modules/auth/di.js +17 -3
- package/dist/modules/auth/di.js.map +2 -2
- package/dist/modules/auth/services/rbacDefaultCache.js +110 -0
- package/dist/modules/auth/services/rbacDefaultCache.js.map +7 -0
- package/dist/modules/catalog/backend/catalog/products/[id]/page.js +8 -1
- package/dist/modules/catalog/backend/catalog/products/[id]/page.js.map +2 -2
- package/dist/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.js +3 -2
- package/dist/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.js.map +2 -2
- package/dist/modules/catalog/backend/catalog/products/[productId]/variants/create/page.js +3 -2
- package/dist/modules/catalog/backend/catalog/products/[productId]/variants/create/page.js.map +2 -2
- package/dist/modules/configs/cli.js +27 -14
- package/dist/modules/configs/cli.js.map +2 -2
- package/dist/modules/currencies/api/currencies/route.js +3 -4
- package/dist/modules/currencies/api/currencies/route.js.map +2 -2
- package/dist/modules/currencies/api/exchange-rates/route.js +3 -4
- package/dist/modules/currencies/api/exchange-rates/route.js.map +2 -2
- package/dist/modules/customers/api/people/route.js +26 -24
- package/dist/modules/customers/api/people/route.js.map +2 -2
- package/dist/modules/directory/subscribers/invalidateOrgScopeCache.js +26 -0
- package/dist/modules/directory/subscribers/invalidateOrgScopeCache.js.map +7 -0
- package/dist/modules/directory/utils/organizationScope.js +85 -0
- package/dist/modules/directory/utils/organizationScope.js.map +2 -2
- package/dist/modules/resources/backend/resources/resource-types/[id]/edit/page.js +1 -1
- package/dist/modules/resources/backend/resources/resource-types/[id]/edit/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/[channelId]/edit/page.js +1 -1
- package/dist/modules/sales/backend/sales/channels/[channelId]/edit/page.js.map +2 -2
- package/dist/modules/sales/components/channels/ChannelOfferForm.js +1 -1
- package/dist/modules/sales/components/channels/ChannelOfferForm.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/[id]/page.js +2 -1
- package/dist/modules/workflows/backend/definitions/[id]/page.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/create/page.js +4 -2
- package/dist/modules/workflows/backend/definitions/create/page.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/visual-editor/page.js +20 -3
- package/dist/modules/workflows/backend/definitions/visual-editor/page.js.map +2 -2
- package/dist/modules/workflows/components/ActivitiesEditor.js +34 -1
- package/dist/modules/workflows/components/ActivitiesEditor.js.map +2 -2
- package/dist/modules/workflows/components/NodeEditDialog.js +153 -17
- package/dist/modules/workflows/components/NodeEditDialog.js.map +2 -2
- package/dist/modules/workflows/components/StepsEditor.js +31 -0
- package/dist/modules/workflows/components/StepsEditor.js.map +2 -2
- package/dist/modules/workflows/components/WorkflowGraph.js +3 -2
- package/dist/modules/workflows/components/WorkflowGraph.js.map +2 -2
- package/dist/modules/workflows/components/nodes/WaitForTimerNode.js +54 -0
- package/dist/modules/workflows/components/nodes/WaitForTimerNode.js.map +7 -0
- package/dist/modules/workflows/components/nodes/index.js +3 -1
- package/dist/modules/workflows/components/nodes/index.js.map +2 -2
- package/dist/modules/workflows/data/validators.js +117 -0
- package/dist/modules/workflows/data/validators.js.map +2 -2
- package/dist/modules/workflows/di.js +5 -1
- package/dist/modules/workflows/di.js.map +2 -2
- package/dist/modules/workflows/lib/activity-executor.js +42 -1
- package/dist/modules/workflows/lib/activity-executor.js.map +2 -2
- package/dist/modules/workflows/lib/activity-queue-types.js.map +2 -2
- package/dist/modules/workflows/lib/activity-worker-handler.js +24 -0
- package/dist/modules/workflows/lib/activity-worker-handler.js.map +2 -2
- package/dist/modules/workflows/lib/duration.js +32 -0
- package/dist/modules/workflows/lib/duration.js.map +7 -0
- package/dist/modules/workflows/lib/event-logger.js +1 -0
- package/dist/modules/workflows/lib/event-logger.js.map +2 -2
- package/dist/modules/workflows/lib/format-validation-error.js +12 -0
- package/dist/modules/workflows/lib/format-validation-error.js.map +7 -0
- package/dist/modules/workflows/lib/graph-utils.js +6 -3
- package/dist/modules/workflows/lib/graph-utils.js.map +2 -2
- package/dist/modules/workflows/lib/node-type-icons.js +9 -5
- package/dist/modules/workflows/lib/node-type-icons.js.map +2 -2
- package/dist/modules/workflows/lib/signal-handler.js +55 -23
- package/dist/modules/workflows/lib/signal-handler.js.map +2 -2
- package/dist/modules/workflows/lib/step-handler.js +79 -29
- package/dist/modules/workflows/lib/step-handler.js.map +2 -2
- package/dist/modules/workflows/lib/timer-handler.js +159 -0
- package/dist/modules/workflows/lib/timer-handler.js.map +7 -0
- package/dist/modules/workflows/lib/workflow-executor.js +1 -1
- package/dist/modules/workflows/lib/workflow-executor.js.map +2 -2
- package/dist/modules/workflows/workers/workflow-activities.worker.js +20 -4
- package/dist/modules/workflows/workers/workflow-activities.worker.js.map +2 -2
- package/package.json +7 -7
- package/src/modules/attachments/api/file/[id]/route.ts +7 -2
- package/src/modules/attachments/api/image/[id]/[[...slug]]/route.ts +7 -4
- package/src/modules/audit_logs/services/accessLogService.ts +179 -15
- package/src/modules/auth/backend/auth/profile/page.tsx +1 -1
- package/src/modules/auth/backend/profile/change-password/page.tsx +1 -1
- package/src/modules/auth/backend/users/[id]/edit/page.tsx +1 -1
- package/src/modules/auth/backend/users/create/page.tsx +6 -1
- package/src/modules/auth/di.ts +26 -3
- package/src/modules/auth/services/rbacDefaultCache.ts +145 -0
- package/src/modules/catalog/backend/catalog/products/[id]/page.tsx +8 -1
- package/src/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.tsx +3 -2
- package/src/modules/catalog/backend/catalog/products/[productId]/variants/create/page.tsx +3 -2
- package/src/modules/configs/cli.ts +34 -13
- package/src/modules/currencies/api/currencies/route.ts +3 -4
- package/src/modules/currencies/api/exchange-rates/route.ts +3 -4
- package/src/modules/customers/api/people/route.ts +27 -25
- package/src/modules/directory/subscribers/invalidateOrgScopeCache.ts +39 -0
- package/src/modules/directory/utils/organizationScope.ts +121 -0
- package/src/modules/resources/backend/resources/resource-types/[id]/edit/page.tsx +1 -1
- package/src/modules/sales/backend/sales/channels/[channelId]/edit/page.tsx +1 -1
- package/src/modules/sales/components/channels/ChannelOfferForm.tsx +1 -1
- package/src/modules/workflows/backend/definitions/[id]/page.tsx +3 -2
- package/src/modules/workflows/backend/definitions/create/page.tsx +4 -2
- package/src/modules/workflows/backend/definitions/visual-editor/page.tsx +18 -1
- package/src/modules/workflows/components/ActivitiesEditor.tsx +40 -0
- package/src/modules/workflows/components/NodeEditDialog.tsx +218 -30
- package/src/modules/workflows/components/StepsEditor.tsx +36 -0
- package/src/modules/workflows/components/WorkflowGraph.tsx +2 -1
- package/src/modules/workflows/components/nodes/WaitForTimerNode.tsx +70 -0
- package/src/modules/workflows/components/nodes/index.ts +3 -0
- package/src/modules/workflows/data/validators.ts +121 -0
- package/src/modules/workflows/di.ts +4 -0
- package/src/modules/workflows/i18n/de.json +10 -1
- package/src/modules/workflows/i18n/en.json +10 -1
- package/src/modules/workflows/i18n/es.json +10 -1
- package/src/modules/workflows/i18n/pl.json +10 -1
- package/src/modules/workflows/lib/activity-executor.ts +86 -2
- package/src/modules/workflows/lib/activity-queue-types.ts +18 -11
- package/src/modules/workflows/lib/activity-worker-handler.ts +29 -0
- package/src/modules/workflows/lib/duration.ts +51 -0
- package/src/modules/workflows/lib/event-logger.ts +1 -0
- package/src/modules/workflows/lib/format-validation-error.ts +30 -0
- package/src/modules/workflows/lib/graph-utils.ts +3 -0
- package/src/modules/workflows/lib/node-type-icons.ts +6 -2
- package/src/modules/workflows/lib/signal-handler.ts +62 -24
- package/src/modules/workflows/lib/step-handler.ts +107 -50
- package/src/modules/workflows/lib/timer-handler.ts +213 -0
- package/src/modules/workflows/lib/workflow-executor.ts +1 -1
- package/src/modules/workflows/workers/workflow-activities.worker.ts +33 -7
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Timer Handler Service
|
|
3
|
+
*
|
|
4
|
+
* Fires timers for WAIT_FOR_TIMER steps: resumes a paused workflow instance
|
|
5
|
+
* when its scheduled timer job is processed by the activity worker.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { EntityManager } from '@mikro-orm/core'
|
|
9
|
+
import type { EntityManager as PostgreSqlEntityManager } from '@mikro-orm/postgresql'
|
|
10
|
+
import type { AwilixContainer } from 'awilix'
|
|
11
|
+
import { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'
|
|
12
|
+
import { WorkflowInstance, WorkflowDefinition, StepInstance } from '../data/entities'
|
|
13
|
+
import type * as eventLoggerModule from './event-logger'
|
|
14
|
+
import type * as stepHandlerModule from './step-handler'
|
|
15
|
+
import type * as transitionHandlerModule from './transition-handler'
|
|
16
|
+
import type * as workflowExecutorModule from './workflow-executor'
|
|
17
|
+
|
|
18
|
+
export interface FireTimerOptions {
|
|
19
|
+
instanceId: string
|
|
20
|
+
stepInstanceId?: string
|
|
21
|
+
userId?: string
|
|
22
|
+
tenantId: string
|
|
23
|
+
organizationId: string
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export class TimerError extends Error {
|
|
27
|
+
constructor(
|
|
28
|
+
message: string,
|
|
29
|
+
public code: string,
|
|
30
|
+
public details?: any
|
|
31
|
+
) {
|
|
32
|
+
super(message)
|
|
33
|
+
this.name = 'TimerError'
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Fire a timer and resume workflow execution.
|
|
39
|
+
*
|
|
40
|
+
* Mirrors `sendSignal` from signal-handler.ts — verifies the instance is
|
|
41
|
+
* paused at a WAIT_FOR_TIMER step, logs TIMER_FIRED, exits the step, then
|
|
42
|
+
* executes auto transitions and resumes the workflow.
|
|
43
|
+
*/
|
|
44
|
+
export async function fireTimer(
|
|
45
|
+
em: EntityManager,
|
|
46
|
+
container: AwilixContainer,
|
|
47
|
+
options: FireTimerOptions
|
|
48
|
+
): Promise<void> {
|
|
49
|
+
const { instanceId, stepInstanceId, userId, tenantId, organizationId } = options
|
|
50
|
+
|
|
51
|
+
const eventLogger = container.resolve<typeof eventLoggerModule>('eventLogger')
|
|
52
|
+
const stepHandler = container.resolve<typeof stepHandlerModule>('stepHandler')
|
|
53
|
+
const transitionHandler = container.resolve<typeof transitionHandlerModule>('transitionHandler')
|
|
54
|
+
const workflowExecutor = container.resolve<typeof workflowExecutorModule>('workflowExecutor')
|
|
55
|
+
|
|
56
|
+
const instance = await findOneWithDecryption(
|
|
57
|
+
em as PostgreSqlEntityManager,
|
|
58
|
+
WorkflowInstance,
|
|
59
|
+
{
|
|
60
|
+
id: instanceId,
|
|
61
|
+
tenantId,
|
|
62
|
+
organizationId,
|
|
63
|
+
},
|
|
64
|
+
undefined,
|
|
65
|
+
{ tenantId, organizationId },
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
if (!instance) {
|
|
69
|
+
throw new TimerError(
|
|
70
|
+
'Workflow instance not found',
|
|
71
|
+
'INSTANCE_NOT_FOUND',
|
|
72
|
+
{ instanceId }
|
|
73
|
+
)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (instance.status !== 'PAUSED') {
|
|
77
|
+
throw new TimerError(
|
|
78
|
+
'Workflow is not paused',
|
|
79
|
+
'WORKFLOW_NOT_PAUSED',
|
|
80
|
+
{ instanceId, status: instance.status }
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const definition = await findOneWithDecryption(
|
|
85
|
+
em as PostgreSqlEntityManager,
|
|
86
|
+
WorkflowDefinition,
|
|
87
|
+
{
|
|
88
|
+
id: instance.definitionId,
|
|
89
|
+
tenantId: instance.tenantId,
|
|
90
|
+
organizationId: instance.organizationId,
|
|
91
|
+
deletedAt: null,
|
|
92
|
+
},
|
|
93
|
+
undefined,
|
|
94
|
+
{ tenantId: instance.tenantId, organizationId: instance.organizationId },
|
|
95
|
+
)
|
|
96
|
+
if (!definition) {
|
|
97
|
+
throw new TimerError(
|
|
98
|
+
'Workflow definition not found',
|
|
99
|
+
'DEFINITION_NOT_FOUND',
|
|
100
|
+
{ definitionId: instance.definitionId }
|
|
101
|
+
)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const currentStep = definition.definition.steps.find(
|
|
105
|
+
(s: any) => s.stepId === instance.currentStepId
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
if (!currentStep || currentStep.stepType !== 'WAIT_FOR_TIMER') {
|
|
109
|
+
throw new TimerError(
|
|
110
|
+
'Workflow is not waiting for timer',
|
|
111
|
+
'NOT_WAITING_FOR_TIMER',
|
|
112
|
+
{ instanceId, currentStepId: instance.currentStepId }
|
|
113
|
+
)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const now = new Date()
|
|
117
|
+
instance.updatedAt = now
|
|
118
|
+
|
|
119
|
+
await eventLogger.logWorkflowEvent(em, {
|
|
120
|
+
workflowInstanceId: instance.id,
|
|
121
|
+
stepInstanceId,
|
|
122
|
+
eventType: 'TIMER_FIRED',
|
|
123
|
+
eventData: {
|
|
124
|
+
stepId: instance.currentStepId,
|
|
125
|
+
firedAt: now.toISOString(),
|
|
126
|
+
},
|
|
127
|
+
userId,
|
|
128
|
+
tenantId: instance.tenantId,
|
|
129
|
+
organizationId: instance.organizationId,
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
const stepInstance = stepInstanceId
|
|
133
|
+
? await findOneWithDecryption(
|
|
134
|
+
em as PostgreSqlEntityManager,
|
|
135
|
+
StepInstance,
|
|
136
|
+
{
|
|
137
|
+
id: stepInstanceId,
|
|
138
|
+
workflowInstanceId: instance.id,
|
|
139
|
+
tenantId: instance.tenantId,
|
|
140
|
+
organizationId: instance.organizationId,
|
|
141
|
+
},
|
|
142
|
+
undefined,
|
|
143
|
+
{ tenantId: instance.tenantId, organizationId: instance.organizationId },
|
|
144
|
+
)
|
|
145
|
+
: await findOneWithDecryption(
|
|
146
|
+
em as PostgreSqlEntityManager,
|
|
147
|
+
StepInstance,
|
|
148
|
+
{
|
|
149
|
+
workflowInstanceId: instance.id,
|
|
150
|
+
stepId: instance.currentStepId,
|
|
151
|
+
status: 'ACTIVE',
|
|
152
|
+
tenantId: instance.tenantId,
|
|
153
|
+
organizationId: instance.organizationId,
|
|
154
|
+
},
|
|
155
|
+
undefined,
|
|
156
|
+
{ tenantId: instance.tenantId, organizationId: instance.organizationId },
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
if (stepInstance) {
|
|
160
|
+
await stepHandler.exitStep(em, stepInstance, {
|
|
161
|
+
firedAt: now.toISOString(),
|
|
162
|
+
})
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const autoTransitions = (definition.definition.transitions || []).filter(
|
|
166
|
+
(t: any) => t.fromStepId === instance.currentStepId && t.trigger === 'auto'
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
if (autoTransitions.length === 0) {
|
|
170
|
+
instance.status = 'RUNNING'
|
|
171
|
+
await em.flush()
|
|
172
|
+
return
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const transitionContext = {
|
|
176
|
+
workflowContext: instance.context,
|
|
177
|
+
userId,
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const validTransitions = await transitionHandler.findValidTransitions(
|
|
181
|
+
em,
|
|
182
|
+
instance,
|
|
183
|
+
instance.currentStepId,
|
|
184
|
+
transitionContext
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
const firstValidTransition = validTransitions.find((t) => t.isValid)
|
|
188
|
+
|
|
189
|
+
if (!firstValidTransition || !firstValidTransition.transition) {
|
|
190
|
+
instance.status = 'RUNNING'
|
|
191
|
+
await em.flush()
|
|
192
|
+
return
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const transitionResult = await transitionHandler.executeTransition(
|
|
196
|
+
em,
|
|
197
|
+
container,
|
|
198
|
+
instance,
|
|
199
|
+
instance.currentStepId,
|
|
200
|
+
firstValidTransition.transition.toStepId,
|
|
201
|
+
transitionContext
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
if (!transitionResult.success) {
|
|
205
|
+
throw new TimerError(
|
|
206
|
+
'Transition failed after timer fired',
|
|
207
|
+
'TRANSITION_FAILED',
|
|
208
|
+
{ error: transitionResult.error }
|
|
209
|
+
)
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
await workflowExecutor.executeWorkflow(em, container, instance.id, { userId })
|
|
213
|
+
}
|
|
@@ -325,7 +325,7 @@ export async function executeWorkflow(
|
|
|
325
325
|
if (
|
|
326
326
|
currentStep?.stepType === 'USER_TASK' ||
|
|
327
327
|
currentStep?.stepType === 'WAIT_FOR_SIGNAL' ||
|
|
328
|
-
currentStep?.stepType === '
|
|
328
|
+
currentStep?.stepType === 'WAIT_FOR_TIMER'
|
|
329
329
|
) {
|
|
330
330
|
return {
|
|
331
331
|
status: 'RUNNING',
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import type { QueuedJob, JobContext, WorkerMeta } from '@open-mercato/queue'
|
|
12
|
-
import {
|
|
12
|
+
import type { WorkflowActivityJob } from '../lib/activity-queue-types'
|
|
13
13
|
import type { EntityManager } from '@mikro-orm/core'
|
|
14
14
|
import type { AwilixContainer } from 'awilix'
|
|
15
15
|
import { WorkflowInstance } from '../data/entities'
|
|
@@ -23,12 +23,18 @@ import {
|
|
|
23
23
|
executeFunction,
|
|
24
24
|
} from '../lib/activity-executor'
|
|
25
25
|
|
|
26
|
-
// Worker metadata for auto-discovery
|
|
26
|
+
// Worker metadata for auto-discovery.
|
|
27
|
+
// NOTE: `queue` MUST be a string literal (or locally-declared const) so the
|
|
28
|
+
// generator's AST-based extractor can resolve it when Node cannot import the
|
|
29
|
+
// .ts source file directly. Importing `WORKFLOW_ACTIVITIES_QUEUE_NAME` from
|
|
30
|
+
// another module breaks auto-discovery and silently drops the worker from
|
|
31
|
+
// `modules.generated.ts`.
|
|
32
|
+
const WORKFLOW_ACTIVITIES_QUEUE = 'workflow-activities'
|
|
27
33
|
const DEFAULT_CONCURRENCY = 1
|
|
28
34
|
const envConcurrency = process.env.WORKERS_WORKFLOW_ACTIVITIES_CONCURRENCY
|
|
29
35
|
|
|
30
36
|
export const metadata: WorkerMeta = {
|
|
31
|
-
queue:
|
|
37
|
+
queue: WORKFLOW_ACTIVITIES_QUEUE,
|
|
32
38
|
id: 'workflows:workflow-activities',
|
|
33
39
|
concurrency: envConcurrency ? parseInt(envConcurrency, 10) : DEFAULT_CONCURRENCY,
|
|
34
40
|
}
|
|
@@ -54,10 +60,6 @@ export default async function handle(
|
|
|
54
60
|
const { payload } = job
|
|
55
61
|
const startTime = Date.now()
|
|
56
62
|
|
|
57
|
-
console.log(
|
|
58
|
-
`[workflows:activity-worker] Processing activity ${payload.activityId} (${payload.activityType}) for workflow instance ${payload.workflowInstanceId} (job ${ctx.jobId}, attempt ${ctx.attemptNumber})`
|
|
59
|
-
)
|
|
60
|
-
|
|
61
63
|
// Resolve services from DI container
|
|
62
64
|
const em = ctx.resolve<EntityManager>('em')
|
|
63
65
|
|
|
@@ -65,6 +67,27 @@ export default async function handle(
|
|
|
65
67
|
// The ctx already has the resolve method we need, we just need to cast it
|
|
66
68
|
const container = ctx as unknown as AwilixContainer
|
|
67
69
|
|
|
70
|
+
// Timer jobs (kind: 'timer') are a distinct flow — they resume a paused
|
|
71
|
+
// workflow at a WAIT_FOR_TIMER step rather than running an activity.
|
|
72
|
+
if (payload.kind === 'timer') {
|
|
73
|
+
console.log(
|
|
74
|
+
`[workflows:activity-worker] Firing timer for instance ${payload.workflowInstanceId} (job ${ctx.jobId})`
|
|
75
|
+
)
|
|
76
|
+
const { fireTimer } = await import('../lib/timer-handler')
|
|
77
|
+
await fireTimer(em, container, {
|
|
78
|
+
instanceId: payload.workflowInstanceId,
|
|
79
|
+
stepInstanceId: payload.stepInstanceId,
|
|
80
|
+
tenantId: payload.tenantId,
|
|
81
|
+
organizationId: payload.organizationId,
|
|
82
|
+
userId: payload.userId,
|
|
83
|
+
})
|
|
84
|
+
return
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
console.log(
|
|
88
|
+
`[workflows:activity-worker] Processing activity ${payload.activityId} (${payload.activityType}) for workflow instance ${payload.workflowInstanceId} (job ${ctx.jobId}, attempt ${ctx.attemptNumber})`
|
|
89
|
+
)
|
|
90
|
+
|
|
68
91
|
try {
|
|
69
92
|
// Fetch workflow instance with tenant/org scoping
|
|
70
93
|
const instance = await em.findOne(WorkflowInstance, {
|
|
@@ -114,6 +137,9 @@ export default async function handle(
|
|
|
114
137
|
return await executeCallWebhook(payload.activityConfig, activityContext, { signal })
|
|
115
138
|
case 'EXECUTE_FUNCTION':
|
|
116
139
|
return await executeFunction(payload.activityConfig, activityContext, container)
|
|
140
|
+
case 'WAIT':
|
|
141
|
+
// Delay already handled by queue's delayMs — return success immediately
|
|
142
|
+
return { waited: true }
|
|
117
143
|
default:
|
|
118
144
|
throw new Error(`Unsupported activity type: ${payload.activityType}`)
|
|
119
145
|
}
|