@hotmeshio/hotmesh 0.21.1 → 0.22.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -129
- package/build/modules/utils.d.ts +2 -0
- package/build/modules/utils.js +9 -1
- package/build/package.json +8 -2
- package/build/services/activities/hook.d.ts +178 -58
- package/build/services/activities/hook.js +244 -58
- package/build/services/activities/trigger.js +5 -1
- package/build/services/durable/client.d.ts +273 -67
- package/build/services/durable/client.js +351 -126
- package/build/services/durable/index.d.ts +7 -3
- package/build/services/durable/index.js +6 -0
- package/build/services/durable/schemas/factory.js +40 -0
- package/build/services/durable/worker.js +5 -28
- package/build/services/durable/workflow/condition.d.ts +69 -37
- package/build/services/durable/workflow/condition.js +70 -39
- package/build/services/hotmesh/index.d.ts +31 -4
- package/build/services/hotmesh/index.js +31 -4
- package/build/services/store/index.d.ts +1 -1
- package/build/services/store/providers/postgres/kvsql.d.ts +1 -1
- package/build/services/store/providers/postgres/kvtables.js +83 -122
- package/build/services/store/providers/postgres/kvtypes/hash/basic.d.ts +1 -1
- package/build/services/store/providers/postgres/kvtypes/hash/basic.js +8 -8
- package/build/services/store/providers/postgres/kvtypes/hash/index.d.ts +1 -1
- package/build/services/store/providers/postgres/postgres.d.ts +51 -188
- package/build/services/store/providers/postgres/postgres.js +542 -285
- package/build/types/activity.d.ts +2 -0
- package/build/types/hmsh_escalations.d.ts +240 -0
- package/build/types/index.d.ts +1 -1
- package/build/types/provider.d.ts +2 -0
- package/package.json +9 -2
- package/build/types/signal.d.ts +0 -147
- /package/build/types/{signal.js → hmsh_escalations.js} +0 -0
|
@@ -806,45 +806,22 @@ class WorkerService {
|
|
|
806
806
|
const workflowInput = data.data;
|
|
807
807
|
const execIndex = counter.counter;
|
|
808
808
|
const { workflowId, workflowDimension, originJobId } = workflowInput;
|
|
809
|
-
const
|
|
810
|
-
//if condition() was called with queueConfig, create a signal queue record
|
|
811
|
-
if (payload.queueConfig) {
|
|
812
|
-
const store = this.workflowRunner.engine.store;
|
|
813
|
-
if (typeof store.enqueueSignal === 'function') {
|
|
814
|
-
const ns = config.namespace ?? factory_1.APP_ID;
|
|
815
|
-
try {
|
|
816
|
-
await store.enqueueSignal({
|
|
817
|
-
namespace: ns,
|
|
818
|
-
appId: store.appId,
|
|
819
|
-
signalKey: payload.signalId,
|
|
820
|
-
workflowId,
|
|
821
|
-
topic: `${ns}.wfs.wait`,
|
|
822
|
-
taskQueue: config.taskQueue ?? payload.queueConfig.taskQueue,
|
|
823
|
-
...payload.queueConfig,
|
|
824
|
-
});
|
|
825
|
-
}
|
|
826
|
-
catch (enqueueErr) {
|
|
827
|
-
this.workflowRunner.engine.logger.warn('signal-queue-enqueue-err', {
|
|
828
|
-
signalId: payload.signalId,
|
|
829
|
-
error: enqueueErr,
|
|
830
|
-
});
|
|
831
|
-
}
|
|
832
|
-
}
|
|
833
|
-
}
|
|
809
|
+
const pendingInterruption = interruptionRegistry[0];
|
|
834
810
|
return withPatchMarkers({
|
|
835
811
|
status: stream_1.StreamStatus.SUCCESS,
|
|
836
812
|
code: enums_1.HMSH_CODE_DURABLE_WAIT,
|
|
837
813
|
metadata: { ...data.metadata },
|
|
838
814
|
data: {
|
|
839
815
|
code: enums_1.HMSH_CODE_DURABLE_WAIT,
|
|
840
|
-
signalId:
|
|
816
|
+
signalId: pendingInterruption.signalId,
|
|
841
817
|
index: execIndex,
|
|
842
|
-
workflowDimension:
|
|
818
|
+
workflowDimension: pendingInterruption.workflowDimension ||
|
|
843
819
|
workflowDimension ||
|
|
844
820
|
'',
|
|
845
|
-
duration:
|
|
821
|
+
duration: pendingInterruption.duration,
|
|
846
822
|
workflowId,
|
|
847
823
|
originJobId: originJobId || workflowId,
|
|
824
|
+
queueConfig: pendingInterruption.queueConfig ?? null,
|
|
848
825
|
},
|
|
849
826
|
});
|
|
850
827
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
export type { ConditionQueueConfig };
|
|
1
|
+
import { ConditionQueueConfig } from '../../../types/hmsh_escalations';
|
|
3
2
|
/**
|
|
4
3
|
* Pauses the workflow until a signal with the given `signalId` is received.
|
|
5
4
|
* The workflow suspends durably — it survives process restarts and will
|
|
@@ -7,64 +6,97 @@ export type { ConditionQueueConfig };
|
|
|
7
6
|
*
|
|
8
7
|
* `condition` is the **receive** side of the signal coordination pair.
|
|
9
8
|
* The **send** side is `signal()`, which can be called from another
|
|
10
|
-
* workflow, a hook function, or externally via `
|
|
9
|
+
* workflow, a hook function, or externally via `client.workflow.signal()`.
|
|
11
10
|
*
|
|
12
11
|
* On replay, `condition` returns the previously stored signal payload
|
|
13
|
-
* immediately
|
|
12
|
+
* immediately — no actual suspension occurs.
|
|
14
13
|
*
|
|
15
|
-
* ##
|
|
14
|
+
* ## Basic usage
|
|
16
15
|
*
|
|
17
16
|
* ```typescript
|
|
18
17
|
* import { Durable } from '@hotmeshio/hotmesh';
|
|
19
18
|
*
|
|
20
|
-
* // Human-in-the-loop approval pattern
|
|
21
19
|
* export async function approvalWorkflow(orderId: string): Promise<boolean> {
|
|
22
20
|
* const { submitForReview } = Durable.workflow.proxyActivities<typeof activities>();
|
|
23
|
-
*
|
|
24
21
|
* await submitForReview(orderId);
|
|
25
22
|
*
|
|
26
|
-
* // Pause
|
|
23
|
+
* // Pause until a human approves or rejects
|
|
27
24
|
* const decision = await Durable.workflow.condition<{ approved: boolean }>('approval');
|
|
28
|
-
*
|
|
29
25
|
* return decision.approved;
|
|
30
26
|
* }
|
|
31
27
|
*
|
|
32
|
-
* //
|
|
28
|
+
* // From an API handler or another workflow:
|
|
33
29
|
* await client.workflow.signal('approval', { approved: true });
|
|
34
30
|
* ```
|
|
35
31
|
*
|
|
32
|
+
* ## With timeout
|
|
33
|
+
*
|
|
34
|
+
* Pass a duration string as the second argument to set a deadline.
|
|
35
|
+
* `condition` returns `false` if the timeout fires before a signal arrives.
|
|
36
|
+
*
|
|
36
37
|
* ```typescript
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
* return [name, score];
|
|
44
|
-
* }
|
|
38
|
+
* const decision = await Durable.workflow.condition<{ approved: boolean }>(
|
|
39
|
+
* 'approval',
|
|
40
|
+
* '72h', // give reviewers 72 hours; returns false on timeout
|
|
41
|
+
* );
|
|
42
|
+
* if (decision === false) return 'auto-rejected-timeout';
|
|
43
|
+
* return decision.approved ? 'approved' : 'rejected';
|
|
45
44
|
* ```
|
|
46
45
|
*
|
|
46
|
+
* ## With escalation queue config
|
|
47
|
+
*
|
|
48
|
+
* Pass a {@link ConditionQueueConfig} as the second argument to surface the
|
|
49
|
+
* pause as a claimable row in `public.hmsh_escalations`. The INSERT is
|
|
50
|
+
* committed atomically with the workflow checkpoint — one write, no
|
|
51
|
+
* enrichment step, no secondary round-trip.
|
|
52
|
+
*
|
|
47
53
|
* ```typescript
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
54
|
+
* const decision = await Durable.workflow.condition<{ approved: boolean }>(
|
|
55
|
+
* 'manager-approval',
|
|
56
|
+
* {
|
|
57
|
+
* role: 'manager',
|
|
58
|
+
* type: 'order-approval',
|
|
59
|
+
* subtype: 'regional',
|
|
60
|
+
* priority: 2,
|
|
61
|
+
* description: 'Approve or reject the regional order',
|
|
62
|
+
* metadata: { orderId, region },
|
|
63
|
+
* envelope: { instructions: 'Review the attached order' },
|
|
64
|
+
* },
|
|
65
|
+
* );
|
|
66
|
+
*
|
|
67
|
+
* // Elsewhere: list, claim, then resolve (resumes the workflow)
|
|
68
|
+
* const [item] = await client.escalations.list({ role: 'manager', status: 'pending' });
|
|
69
|
+
* await client.escalations.claim({ id: item.id, assignee: 'alice@company.com' });
|
|
70
|
+
* await client.escalations.resolve({ id: item.id, resolverPayload: { approved: true } });
|
|
71
|
+
* ```
|
|
72
|
+
*
|
|
73
|
+
* ## Fan-in: wait for multiple signals in parallel
|
|
74
|
+
*
|
|
75
|
+
* ```typescript
|
|
76
|
+
* const [name, score] = await Promise.all([
|
|
77
|
+
* Durable.workflow.condition<string>('name-signal'),
|
|
78
|
+
* Durable.workflow.condition<number>('score-signal'),
|
|
79
|
+
* ]);
|
|
80
|
+
* ```
|
|
81
|
+
*
|
|
82
|
+
* ## Paired with hook: spawn work, wait for its signal
|
|
83
|
+
*
|
|
84
|
+
* ```typescript
|
|
85
|
+
* const signalId = `result-${Durable.workflow.random()}`;
|
|
86
|
+
* await Durable.workflow.hook({
|
|
87
|
+
* taskQueue: 'processors',
|
|
88
|
+
* workflowName: 'processItem',
|
|
89
|
+
* args: [input, signalId],
|
|
90
|
+
* });
|
|
91
|
+
* return await Durable.workflow.condition<string>(signalId);
|
|
62
92
|
* ```
|
|
63
93
|
*
|
|
64
94
|
* @template T - The type of data expected in the signal payload.
|
|
65
|
-
* @param
|
|
66
|
-
* @param
|
|
67
|
-
*
|
|
68
|
-
*
|
|
95
|
+
* @param signalId - A unique signal identifier shared by the sender and receiver.
|
|
96
|
+
* @param timeoutOrConfig - Optional timeout string (e.g. `'30s'`, `'24h'`) OR a
|
|
97
|
+
* {@link ConditionQueueConfig} that writes one row to `public.hmsh_escalations`
|
|
98
|
+
* atomically at suspension time. Cannot specify both; use the config object's
|
|
99
|
+
* `expiresAt` field for deadline enforcement when an escalation is involved.
|
|
100
|
+
* @returns The signal payload, or `false` if a timeout string was given and it expired.
|
|
69
101
|
*/
|
|
70
|
-
export declare function condition<T>(signalId: string, timeoutOrConfig?: string | ConditionQueueConfig
|
|
102
|
+
export declare function condition<T>(signalId: string, timeoutOrConfig?: string | ConditionQueueConfig): Promise<T | false>;
|
|
@@ -11,71 +11,102 @@ const didRun_1 = require("./didRun");
|
|
|
11
11
|
*
|
|
12
12
|
* `condition` is the **receive** side of the signal coordination pair.
|
|
13
13
|
* The **send** side is `signal()`, which can be called from another
|
|
14
|
-
* workflow, a hook function, or externally via `
|
|
14
|
+
* workflow, a hook function, or externally via `client.workflow.signal()`.
|
|
15
15
|
*
|
|
16
16
|
* On replay, `condition` returns the previously stored signal payload
|
|
17
|
-
* immediately
|
|
17
|
+
* immediately — no actual suspension occurs.
|
|
18
18
|
*
|
|
19
|
-
* ##
|
|
19
|
+
* ## Basic usage
|
|
20
20
|
*
|
|
21
21
|
* ```typescript
|
|
22
22
|
* import { Durable } from '@hotmeshio/hotmesh';
|
|
23
23
|
*
|
|
24
|
-
* // Human-in-the-loop approval pattern
|
|
25
24
|
* export async function approvalWorkflow(orderId: string): Promise<boolean> {
|
|
26
25
|
* const { submitForReview } = Durable.workflow.proxyActivities<typeof activities>();
|
|
27
|
-
*
|
|
28
26
|
* await submitForReview(orderId);
|
|
29
27
|
*
|
|
30
|
-
* // Pause
|
|
28
|
+
* // Pause until a human approves or rejects
|
|
31
29
|
* const decision = await Durable.workflow.condition<{ approved: boolean }>('approval');
|
|
32
|
-
*
|
|
33
30
|
* return decision.approved;
|
|
34
31
|
* }
|
|
35
32
|
*
|
|
36
|
-
* //
|
|
33
|
+
* // From an API handler or another workflow:
|
|
37
34
|
* await client.workflow.signal('approval', { approved: true });
|
|
38
35
|
* ```
|
|
39
36
|
*
|
|
37
|
+
* ## With timeout
|
|
38
|
+
*
|
|
39
|
+
* Pass a duration string as the second argument to set a deadline.
|
|
40
|
+
* `condition` returns `false` if the timeout fires before a signal arrives.
|
|
41
|
+
*
|
|
40
42
|
* ```typescript
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
* return [name, score];
|
|
48
|
-
* }
|
|
43
|
+
* const decision = await Durable.workflow.condition<{ approved: boolean }>(
|
|
44
|
+
* 'approval',
|
|
45
|
+
* '72h', // give reviewers 72 hours; returns false on timeout
|
|
46
|
+
* );
|
|
47
|
+
* if (decision === false) return 'auto-rejected-timeout';
|
|
48
|
+
* return decision.approved ? 'approved' : 'rejected';
|
|
49
49
|
* ```
|
|
50
50
|
*
|
|
51
|
+
* ## With escalation queue config
|
|
52
|
+
*
|
|
53
|
+
* Pass a {@link ConditionQueueConfig} as the second argument to surface the
|
|
54
|
+
* pause as a claimable row in `public.hmsh_escalations`. The INSERT is
|
|
55
|
+
* committed atomically with the workflow checkpoint — one write, no
|
|
56
|
+
* enrichment step, no secondary round-trip.
|
|
57
|
+
*
|
|
51
58
|
* ```typescript
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
59
|
+
* const decision = await Durable.workflow.condition<{ approved: boolean }>(
|
|
60
|
+
* 'manager-approval',
|
|
61
|
+
* {
|
|
62
|
+
* role: 'manager',
|
|
63
|
+
* type: 'order-approval',
|
|
64
|
+
* subtype: 'regional',
|
|
65
|
+
* priority: 2,
|
|
66
|
+
* description: 'Approve or reject the regional order',
|
|
67
|
+
* metadata: { orderId, region },
|
|
68
|
+
* envelope: { instructions: 'Review the attached order' },
|
|
69
|
+
* },
|
|
70
|
+
* );
|
|
71
|
+
*
|
|
72
|
+
* // Elsewhere: list, claim, then resolve (resumes the workflow)
|
|
73
|
+
* const [item] = await client.escalations.list({ role: 'manager', status: 'pending' });
|
|
74
|
+
* await client.escalations.claim({ id: item.id, assignee: 'alice@company.com' });
|
|
75
|
+
* await client.escalations.resolve({ id: item.id, resolverPayload: { approved: true } });
|
|
76
|
+
* ```
|
|
77
|
+
*
|
|
78
|
+
* ## Fan-in: wait for multiple signals in parallel
|
|
79
|
+
*
|
|
80
|
+
* ```typescript
|
|
81
|
+
* const [name, score] = await Promise.all([
|
|
82
|
+
* Durable.workflow.condition<string>('name-signal'),
|
|
83
|
+
* Durable.workflow.condition<number>('score-signal'),
|
|
84
|
+
* ]);
|
|
85
|
+
* ```
|
|
86
|
+
*
|
|
87
|
+
* ## Paired with hook: spawn work, wait for its signal
|
|
88
|
+
*
|
|
89
|
+
* ```typescript
|
|
90
|
+
* const signalId = `result-${Durable.workflow.random()}`;
|
|
91
|
+
* await Durable.workflow.hook({
|
|
92
|
+
* taskQueue: 'processors',
|
|
93
|
+
* workflowName: 'processItem',
|
|
94
|
+
* args: [input, signalId],
|
|
95
|
+
* });
|
|
96
|
+
* return await Durable.workflow.condition<string>(signalId);
|
|
66
97
|
* ```
|
|
67
98
|
*
|
|
68
99
|
* @template T - The type of data expected in the signal payload.
|
|
69
|
-
* @param
|
|
70
|
-
* @param
|
|
71
|
-
*
|
|
72
|
-
*
|
|
100
|
+
* @param signalId - A unique signal identifier shared by the sender and receiver.
|
|
101
|
+
* @param timeoutOrConfig - Optional timeout string (e.g. `'30s'`, `'24h'`) OR a
|
|
102
|
+
* {@link ConditionQueueConfig} that writes one row to `public.hmsh_escalations`
|
|
103
|
+
* atomically at suspension time. Cannot specify both; use the config object's
|
|
104
|
+
* `expiresAt` field for deadline enforcement when an escalation is involved.
|
|
105
|
+
* @returns The signal payload, or `false` if a timeout string was given and it expired.
|
|
73
106
|
*/
|
|
74
|
-
async function condition(signalId, timeoutOrConfig
|
|
107
|
+
async function condition(signalId, timeoutOrConfig) {
|
|
75
108
|
const timeout = typeof timeoutOrConfig === 'string' ? timeoutOrConfig : undefined;
|
|
76
|
-
const
|
|
77
|
-
? timeoutOrConfig
|
|
78
|
-
: queueConfig;
|
|
109
|
+
const queueConfig = timeoutOrConfig && typeof timeoutOrConfig === 'object' ? timeoutOrConfig : undefined;
|
|
79
110
|
const [didRunAlready, execIndex, result] = await (0, didRun_1.didRun)('wait');
|
|
80
111
|
(0, cancellationScope_1.checkCancellation)();
|
|
81
112
|
if (didRunAlready) {
|
|
@@ -122,7 +153,7 @@ async function condition(signalId, timeoutOrConfig, queueConfig) {
|
|
|
122
153
|
type: 'DurableWaitForError',
|
|
123
154
|
code: common_1.HMSH_CODE_DURABLE_WAIT,
|
|
124
155
|
...(timeout ? { duration: (0, common_1.s)(timeout) } : {}),
|
|
125
|
-
...(
|
|
156
|
+
...(queueConfig ? { queueConfig } : {}),
|
|
126
157
|
};
|
|
127
158
|
interruptionRegistry.push(interruptionMessage);
|
|
128
159
|
await (0, common_1.sleepImmediate)();
|
|
@@ -320,11 +320,38 @@ declare class HotMesh {
|
|
|
320
320
|
*/
|
|
321
321
|
scrub(jobId: string): Promise<void>;
|
|
322
322
|
/**
|
|
323
|
-
* Sends a signal to a paused workflow,
|
|
324
|
-
*
|
|
323
|
+
* Sends a signal to a paused workflow, resuming its execution with the
|
|
324
|
+
* provided data. This is the low-level primitive used by both the Durable
|
|
325
|
+
* `client.workflow.signal()` wrapper and `client.escalations.resolve()`.
|
|
325
326
|
*
|
|
326
|
-
*
|
|
327
|
-
*
|
|
327
|
+
* The signal is matched to the waiting activity by the `id` field inside
|
|
328
|
+
* `data` — it must equal the value used in the hook rule's
|
|
329
|
+
* `conditions.match[0].expected` expression (typically the job ID).
|
|
330
|
+
*
|
|
331
|
+
* **YAML DAG hook example** — signal a workflow paused at a webhook:
|
|
332
|
+
*
|
|
333
|
+
* ```typescript
|
|
334
|
+
* // The hook activity is waiting on topic 'order.approval'
|
|
335
|
+
* // The hook rule expects: actual '{$self.hook.data.id}' === '{t1.output.data.id}'
|
|
336
|
+
* await hotMesh.signal('order.approval', { id: jobId, approved: true });
|
|
337
|
+
* ```
|
|
338
|
+
*
|
|
339
|
+
* **Durable workflow** — use `client.workflow.signal()` instead, which
|
|
340
|
+
* resolves the topic internally:
|
|
341
|
+
*
|
|
342
|
+
* ```typescript
|
|
343
|
+
* await client.workflow.signal('manager-approval', { approved: true });
|
|
344
|
+
* ```
|
|
345
|
+
*
|
|
346
|
+
* **With escalation** — use `client.escalations.resolve()` to atomically
|
|
347
|
+
* deliver the signal and mark the escalation row resolved:
|
|
348
|
+
*
|
|
349
|
+
* ```typescript
|
|
350
|
+
* await client.escalations.resolve({ id: escalationId, resolverPayload: { approved: true } });
|
|
351
|
+
* ```
|
|
352
|
+
*
|
|
353
|
+
* @param topic - The signal topic (must match a deployed hook rule).
|
|
354
|
+
* @param data - Signal payload. Must contain `id` matching the hook rule's expected value.
|
|
328
355
|
*/
|
|
329
356
|
signal(topic: string, data: JobData, status?: StreamStatus, code?: StreamCode): Promise<string>;
|
|
330
357
|
/** @private */
|
|
@@ -428,11 +428,38 @@ class HotMesh {
|
|
|
428
428
|
return Jobs.scrub(this, jobId);
|
|
429
429
|
}
|
|
430
430
|
/**
|
|
431
|
-
* Sends a signal to a paused workflow,
|
|
432
|
-
*
|
|
431
|
+
* Sends a signal to a paused workflow, resuming its execution with the
|
|
432
|
+
* provided data. This is the low-level primitive used by both the Durable
|
|
433
|
+
* `client.workflow.signal()` wrapper and `client.escalations.resolve()`.
|
|
433
434
|
*
|
|
434
|
-
*
|
|
435
|
-
*
|
|
435
|
+
* The signal is matched to the waiting activity by the `id` field inside
|
|
436
|
+
* `data` — it must equal the value used in the hook rule's
|
|
437
|
+
* `conditions.match[0].expected` expression (typically the job ID).
|
|
438
|
+
*
|
|
439
|
+
* **YAML DAG hook example** — signal a workflow paused at a webhook:
|
|
440
|
+
*
|
|
441
|
+
* ```typescript
|
|
442
|
+
* // The hook activity is waiting on topic 'order.approval'
|
|
443
|
+
* // The hook rule expects: actual '{$self.hook.data.id}' === '{t1.output.data.id}'
|
|
444
|
+
* await hotMesh.signal('order.approval', { id: jobId, approved: true });
|
|
445
|
+
* ```
|
|
446
|
+
*
|
|
447
|
+
* **Durable workflow** — use `client.workflow.signal()` instead, which
|
|
448
|
+
* resolves the topic internally:
|
|
449
|
+
*
|
|
450
|
+
* ```typescript
|
|
451
|
+
* await client.workflow.signal('manager-approval', { approved: true });
|
|
452
|
+
* ```
|
|
453
|
+
*
|
|
454
|
+
* **With escalation** — use `client.escalations.resolve()` to atomically
|
|
455
|
+
* deliver the signal and mark the escalation row resolved:
|
|
456
|
+
*
|
|
457
|
+
* ```typescript
|
|
458
|
+
* await client.escalations.resolve({ id: escalationId, resolverPayload: { approved: true } });
|
|
459
|
+
* ```
|
|
460
|
+
*
|
|
461
|
+
* @param topic - The signal topic (must match a deployed hook rule).
|
|
462
|
+
* @param data - Signal payload. Must contain `id` matching the hook rule's expected value.
|
|
436
463
|
*/
|
|
437
464
|
async signal(topic, data, status, code) {
|
|
438
465
|
return Jobs.signal(this, topic, data, status, code);
|
|
@@ -45,7 +45,7 @@ declare abstract class StoreService<Provider extends ProviderClient, Transaction
|
|
|
45
45
|
jobId: string, appId: string, guidField: string, //
|
|
46
46
|
guidWeight: number, transaction?: ProviderTransaction): Promise<any>;
|
|
47
47
|
abstract getStatus(jobId: string, appId: string): Promise<number>;
|
|
48
|
-
abstract setStateNX(jobId: string, appId: string, status?: number, entity?: string, transaction?: ProviderTransaction): Promise<boolean>;
|
|
48
|
+
abstract setStateNX(jobId: string, appId: string, status?: number, entity?: string, transaction?: ProviderTransaction, originId?: string, parentId?: string): Promise<boolean>;
|
|
49
49
|
abstract setState(state: StringAnyType, status: number | null, jobId: string, symbolNames: string[], dIds: StringStringType, transaction?: TransactionProvider): Promise<string>;
|
|
50
50
|
abstract getQueryState(jobId: string, fields: string[]): Promise<StringAnyType>;
|
|
51
51
|
abstract getState(jobId: string, consumes: Consumes, dIds: StringStringType): Promise<[StringAnyType, number] | undefined>;
|
|
@@ -59,7 +59,7 @@ export declare class KVSQL {
|
|
|
59
59
|
setnxex: (key: string, value: string, delay: number, multi?: ProviderTransaction) => Promise<boolean>;
|
|
60
60
|
hset: (key: string, fields: Record<string, string>, options?: import("./kvtypes/hash/index").HSetOptions, multi?: any) => Promise<any>;
|
|
61
61
|
_hset: (key: string, fields: Record<string, string>, options?: import("./kvtypes/hash/index").HSetOptions) => import("./kvtypes/hash/types").SqlResult;
|
|
62
|
-
hsetnx: (key: string, field: string, value: string, multi?: ProviderTransaction, entity?: string) => Promise<number>;
|
|
62
|
+
hsetnx: (key: string, field: string, value: string, multi?: ProviderTransaction, entity?: string, originId?: string, parentId?: string) => Promise<number>;
|
|
63
63
|
hget: (key: string, field: string, multi?: ProviderTransaction) => Promise<string>;
|
|
64
64
|
_hget: (key: string, field: string) => import("./kvtypes/hash/types").SqlResult;
|
|
65
65
|
hdel: (key: string, fields: string[], multi?: unknown) => Promise<number>;
|