@hotmeshio/hotmesh 0.0.19 → 0.0.20
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 +4 -4
- package/build/modules/errors.d.ts +2 -1
- package/build/modules/errors.js +2 -1
- package/build/package.json +2 -1
- package/build/services/activities/activity.d.ts +2 -2
- package/build/services/activities/activity.js +10 -8
- package/build/services/activities/hook.d.ts +2 -1
- package/build/services/activities/hook.js +12 -9
- package/build/services/activities/signal.d.ts +4 -0
- package/build/services/activities/signal.js +16 -2
- package/build/services/durable/client.d.ts +15 -5
- package/build/services/durable/client.js +37 -14
- package/build/services/durable/factory.d.ts +2 -16
- package/build/services/durable/factory.js +276 -46
- package/build/services/durable/handle.d.ts +1 -1
- package/build/services/durable/handle.js +18 -5
- package/build/services/durable/search.d.ts +8 -1
- package/build/services/durable/search.js +34 -7
- package/build/services/durable/worker.d.ts +7 -9
- package/build/services/durable/worker.js +29 -23
- package/build/services/durable/workflow.d.ts +18 -1
- package/build/services/durable/workflow.js +99 -35
- package/build/services/engine/index.d.ts +2 -2
- package/build/services/engine/index.js +7 -12
- package/build/services/hotmesh/index.d.ts +2 -2
- package/build/services/hotmesh/index.js +2 -2
- package/build/services/signaler/store.d.ts +2 -2
- package/build/services/signaler/store.js +17 -7
- package/build/services/signaler/stream.js +1 -0
- package/build/services/store/clients/redis.js +1 -1
- package/build/services/store/index.js +3 -0
- package/build/services/telemetry/index.js +7 -1
- package/build/types/activity.d.ts +5 -3
- package/build/types/durable.d.ts +12 -1
- package/build/types/hook.d.ts +0 -1
- package/build/types/index.d.ts +1 -1
- package/modules/errors.ts +4 -2
- package/package.json +2 -1
- package/services/activities/activity.ts +10 -8
- package/services/activities/hook.ts +13 -10
- package/services/activities/signal.ts +17 -3
- package/services/durable/client.ts +40 -15
- package/services/durable/factory.ts +274 -46
- package/services/durable/handle.ts +18 -5
- package/services/durable/search.ts +36 -7
- package/services/durable/worker.ts +30 -24
- package/services/durable/workflow.ts +111 -38
- package/services/engine/index.ts +8 -12
- package/services/hotmesh/index.ts +3 -3
- package/services/signaler/store.ts +18 -8
- package/services/signaler/stream.ts +1 -0
- package/services/store/clients/redis.ts +1 -1
- package/services/store/index.ts +2 -0
- package/services/telemetry/index.ts +6 -1
- package/types/activity.ts +10 -8
- package/types/durable.ts +13 -0
- package/types/hook.ts +0 -1
- package/types/index.ts +1 -0
package/build/types/durable.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ type WorkflowSearchOptions = {
|
|
|
15
15
|
data?: Record<string, string>;
|
|
16
16
|
};
|
|
17
17
|
type WorkflowOptions = {
|
|
18
|
+
namespace?: string;
|
|
18
19
|
taskQueue: string;
|
|
19
20
|
args: any[];
|
|
20
21
|
workflowId: string;
|
|
@@ -25,6 +26,15 @@ type WorkflowOptions = {
|
|
|
25
26
|
search?: WorkflowSearchOptions;
|
|
26
27
|
config?: WorkflowConfig;
|
|
27
28
|
};
|
|
29
|
+
type HookOptions = {
|
|
30
|
+
namespace?: string;
|
|
31
|
+
taskQueue: string;
|
|
32
|
+
args: any[];
|
|
33
|
+
workflowId: string;
|
|
34
|
+
workflowName?: string;
|
|
35
|
+
search?: WorkflowSearchOptions;
|
|
36
|
+
config?: WorkflowConfig;
|
|
37
|
+
};
|
|
28
38
|
type SignalOptions = {
|
|
29
39
|
taskQueue: string;
|
|
30
40
|
data: Record<string, any>;
|
|
@@ -63,6 +73,7 @@ type WorkerConfig = {
|
|
|
63
73
|
search?: WorkflowSearchOptions;
|
|
64
74
|
};
|
|
65
75
|
type WorkerOptions = {
|
|
76
|
+
logLevel?: string;
|
|
66
77
|
maxSystemRetries?: number;
|
|
67
78
|
backoffCoefficient?: number;
|
|
68
79
|
};
|
|
@@ -84,4 +95,4 @@ type ActivityConfig = {
|
|
|
84
95
|
maximumInterval: string;
|
|
85
96
|
};
|
|
86
97
|
};
|
|
87
|
-
export { ActivityConfig, ActivityWorkflowDataType, ClientConfig, ContextType, ConnectionConfig, Connection, NativeConnection, ProxyType, Registry, SignalOptions, WorkerConfig, WorkflowConfig, WorkerOptions, WorkflowSearchOptions, WorkflowDataType, WorkflowOptions, };
|
|
98
|
+
export { ActivityConfig, ActivityWorkflowDataType, ClientConfig, ContextType, ConnectionConfig, Connection, NativeConnection, ProxyType, Registry, SignalOptions, HookOptions, WorkerConfig, WorkflowConfig, WorkerOptions, WorkflowSearchOptions, WorkflowDataType, WorkflowOptions, };
|
package/build/types/hook.d.ts
CHANGED
package/build/types/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export { App, AppVID, AppTransitions, AppSubscriptions } from './app';
|
|
|
3
3
|
export { AsyncSignal } from './async';
|
|
4
4
|
export { CacheMode } from './cache';
|
|
5
5
|
export { CollationFaultType, CollationStage } from './collator';
|
|
6
|
-
export { ActivityConfig, ActivityWorkflowDataType, ClientConfig, ContextType, ConnectionConfig, Connection, NativeConnection, ProxyType, Registry, WorkflowConfig, WorkerConfig, WorkerOptions, WorkflowSearchOptions, WorkflowDataType, WorkflowOptions, } from './durable';
|
|
6
|
+
export { ActivityConfig, ActivityWorkflowDataType, ClientConfig, ContextType, ConnectionConfig, Connection, NativeConnection, ProxyType, Registry, HookOptions, WorkflowConfig, WorkerConfig, WorkerOptions, WorkflowSearchOptions, WorkflowDataType, WorkflowOptions, } from './durable';
|
|
7
7
|
export { HookCondition, HookConditions, HookGate, HookInterface, HookRule, HookRules, HookSignal } from './hook';
|
|
8
8
|
export { RedisClientType as IORedisClientType, RedisMultiType as IORedisMultiType } from './ioredisclient';
|
|
9
9
|
export { ILogger } from './logger';
|
package/modules/errors.ts
CHANGED
|
@@ -36,11 +36,13 @@ class DurableWaitForSignalError extends Error {
|
|
|
36
36
|
class DurableSleepError extends Error {
|
|
37
37
|
code: number;
|
|
38
38
|
duration: number; //seconds
|
|
39
|
-
index: number; //execution order in the workflow
|
|
40
|
-
|
|
39
|
+
index: number; //execution order in the workflow
|
|
40
|
+
dimension: string; //hook dimension (e.g., ',0,1,0') (uses empty string for `null`)
|
|
41
|
+
constructor(message: string, duration: number, index: number, dimension: string) {
|
|
41
42
|
super(message);
|
|
42
43
|
this.duration = duration;
|
|
43
44
|
this.index = index;
|
|
45
|
+
this.dimension = dimension;
|
|
44
46
|
this.code = 595;
|
|
45
47
|
}
|
|
46
48
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hotmeshio/hotmesh",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.20",
|
|
4
4
|
"description": "Unbreakable Workflows",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -45,6 +45,7 @@
|
|
|
45
45
|
"test:durable": "NODE_ENV=test jest ./tests/durable/*/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
46
46
|
"test:durable:hello": "NODE_ENV=test jest ./tests/durable/helloworld/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
47
47
|
"test:durable:goodbye": "NODE_ENV=test jest ./tests/durable/goodbye/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
48
|
+
"test:durable:hook": "NODE_ENV=test jest ./tests/durable/hook/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
48
49
|
"test:durable:retry": "NODE_ENV=test jest ./tests/durable/retry/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
49
50
|
"test:durable:fatal": "NODE_ENV=test jest ./tests/durable/fatal/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
50
51
|
"test:durable:sleep": "NODE_ENV=test jest ./tests/durable/sleep/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
@@ -70,16 +70,20 @@ class Activity {
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
//******** DUPLEX RE-ENTRY POINT ********//
|
|
73
|
-
async processEvent(status: StreamStatus = StreamStatus.SUCCESS, code: StreamCode = 200, type: 'hook' | 'output' = 'output'
|
|
73
|
+
async processEvent(status: StreamStatus = StreamStatus.SUCCESS, code: StreamCode = 200, type: 'hook' | 'output' = 'output'): Promise<void> {
|
|
74
74
|
this.setLeg(2);
|
|
75
|
-
const jid = this.context.metadata.jid
|
|
75
|
+
const jid = this.context.metadata.jid;
|
|
76
|
+
if (!jid) {
|
|
77
|
+
this.logger.error('activity-process-event-error', { message: 'job id is undefined' });
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
76
80
|
const aid = this.metadata.aid;
|
|
77
81
|
this.status = status;
|
|
78
82
|
this.code = code;
|
|
79
83
|
this.logger.debug('activity-process-event', { topic: this.config.subtype, jid, aid, status, code });
|
|
80
84
|
let telemetry: TelemetryService;
|
|
81
85
|
try {
|
|
82
|
-
await this.getState(
|
|
86
|
+
await this.getState();
|
|
83
87
|
const aState = await CollatorService.notarizeReentry(this);
|
|
84
88
|
this.adjacentIndex = CollatorService.getDimensionalIndex(aState);
|
|
85
89
|
|
|
@@ -107,7 +111,6 @@ class Activity {
|
|
|
107
111
|
this.logger.info('process-event-inactive-error', { error });
|
|
108
112
|
return;
|
|
109
113
|
}
|
|
110
|
-
console.error(error);
|
|
111
114
|
this.logger.error('activity-process-event-error', { error });
|
|
112
115
|
telemetry && telemetry.setActivityError(error.message);
|
|
113
116
|
throw error;
|
|
@@ -323,7 +326,7 @@ class Activity {
|
|
|
323
326
|
return MDATA_SYMBOLS[keys_to_save].KEYS.map((key) => `output/metadata/${key}`);
|
|
324
327
|
}
|
|
325
328
|
|
|
326
|
-
async getState(
|
|
329
|
+
async getState() {
|
|
327
330
|
//assemble list of paths necessary to create 'job state' from the 'symbol hash'
|
|
328
331
|
const jobSymbolHashName = `$${this.config.subscribes}`;
|
|
329
332
|
const consumes: Consumes = {
|
|
@@ -348,10 +351,9 @@ class Activity {
|
|
|
348
351
|
}
|
|
349
352
|
TelemetryService.addTargetTelemetryPaths(consumes, this.config, this.metadata, this.leg);
|
|
350
353
|
let { dad, jid } = this.context.metadata;
|
|
351
|
-
|
|
352
|
-
const dIds = CollatorService.getDimensionsById([...this.config.ancestors, this.metadata.aid], dad);
|
|
354
|
+
const dIds = CollatorService.getDimensionsById([...this.config.ancestors, this.metadata.aid], dad || '');
|
|
353
355
|
//`state` is a flat hash; context is a tree
|
|
354
|
-
const [state, status] = await this.store.getState(
|
|
356
|
+
const [state, status] = await this.store.getState(jid, consumes, dIds);
|
|
355
357
|
this.context = restoreHierarchy(state) as JobState;
|
|
356
358
|
this.initDimensionalAddress(dad);
|
|
357
359
|
this.initSelf(this.context);
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
MultiResponseFlags,
|
|
17
17
|
RedisMulti } from '../../types/redis';
|
|
18
18
|
import { StringScalarType } from '../../types/serializer';
|
|
19
|
-
import { StreamStatus } from '../../types/stream';
|
|
19
|
+
import { StreamCode, StreamStatus } from '../../types/stream';
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* Listens for `webhook`, `timehook`, and `cycle` (repeat) signals
|
|
@@ -108,7 +108,7 @@ class Hook extends Activity {
|
|
|
108
108
|
async registerHook(multi?: RedisMulti): Promise<string | void> {
|
|
109
109
|
if (this.config.hook?.topic) {
|
|
110
110
|
const signaler = new StoreSignaler(this.store, this.logger);
|
|
111
|
-
return await signaler.registerWebHook(this.config.hook.topic, this.context, multi);
|
|
111
|
+
return await signaler.registerWebHook(this.config.hook.topic, this.context, this.resolveDad(), multi);
|
|
112
112
|
} else if (this.config.sleep) {
|
|
113
113
|
const durationInSeconds = Pipe.resolve(this.config.sleep, this.context);
|
|
114
114
|
const jobId = this.context.metadata.jid;
|
|
@@ -119,19 +119,22 @@ class Hook extends Activity {
|
|
|
119
119
|
}
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
async processWebHookEvent(): Promise<JobStatus | void> {
|
|
122
|
+
async processWebHookEvent(status: StreamStatus = StreamStatus.SUCCESS, code: StreamCode = 200): Promise<JobStatus | void> {
|
|
123
123
|
this.logger.debug('hook-process-web-hook-event', {
|
|
124
124
|
topic: this.config.hook.topic,
|
|
125
|
-
aid: this.metadata.aid
|
|
125
|
+
aid: this.metadata.aid,
|
|
126
|
+
status,
|
|
127
|
+
code,
|
|
126
128
|
});
|
|
127
129
|
const signaler = new StoreSignaler(this.store, this.logger);
|
|
128
130
|
const data = { ...this.data };
|
|
129
|
-
const
|
|
130
|
-
if (
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
131
|
+
const signal = await signaler.processWebHookSignal(this.config.hook.topic, data);
|
|
132
|
+
if (signal) {
|
|
133
|
+
const [jobId, aid, dad] = signal;
|
|
134
|
+
this.context.metadata.jid = jobId;
|
|
135
|
+
this.context.metadata.dad = dad;
|
|
136
|
+
await this.processEvent(status, code, 'hook');
|
|
137
|
+
if (code === 200) { //otherwise 202 for pending/keepalive
|
|
135
138
|
await signaler.deleteWebHookSignal(this.config.hook.topic, data);
|
|
136
139
|
}
|
|
137
140
|
} //else => already resolved
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
ActivityMetadata,
|
|
11
11
|
SignalActivity } from '../../types/activity';
|
|
12
12
|
import { JobState } from '../../types/job';
|
|
13
|
-
import { MultiResponseFlags
|
|
13
|
+
import { MultiResponseFlags } from '../../types/redis';
|
|
14
14
|
import { StringScalarType } from '../../types/serializer';
|
|
15
15
|
import { JobStatsInput } from '../../types/stats';
|
|
16
16
|
|
|
@@ -50,8 +50,11 @@ class Signal extends Activity {
|
|
|
50
50
|
await this.setStatus(this.adjacencyList.length - 1, multi);
|
|
51
51
|
const multiResponse = await multi.exec() as MultiResponseFlags;
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
if (this.config.subtype === 'all') {
|
|
54
|
+
await this.hookAll();
|
|
55
|
+
} else {
|
|
56
|
+
await this.hookOne();
|
|
57
|
+
}
|
|
55
58
|
|
|
56
59
|
//transition to adjacent activities
|
|
57
60
|
const jobStatus = this.resolveStatus(multiResponse);
|
|
@@ -92,6 +95,17 @@ class Signal extends Activity {
|
|
|
92
95
|
}
|
|
93
96
|
}
|
|
94
97
|
|
|
98
|
+
/**
|
|
99
|
+
* The signal activity will hook one
|
|
100
|
+
*/
|
|
101
|
+
async hookOne(): Promise<string> {
|
|
102
|
+
const topic = Pipe.resolve(this.config.topic, this.context);
|
|
103
|
+
const signalInputData = this.mapSignalData();
|
|
104
|
+
const status = Pipe.resolve(this.config.status, this.context);
|
|
105
|
+
const code = Pipe.resolve(this.config.code, this.context);
|
|
106
|
+
return await this.engine.hook(topic, signalInputData, status, code);
|
|
107
|
+
}
|
|
108
|
+
|
|
95
109
|
/**
|
|
96
110
|
* The signal activity will hook all paused jobs that share the same job key.
|
|
97
111
|
*/
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import { nanoid } from 'nanoid';
|
|
2
|
-
import { APP_ID, APP_VERSION, DEFAULT_COEFFICIENT,
|
|
2
|
+
import { APP_ID, APP_VERSION, DEFAULT_COEFFICIENT, getWorkflowYAML } from './factory';
|
|
3
3
|
import { WorkflowHandleService } from './handle';
|
|
4
4
|
import { HotMeshService as HotMesh } from '../hotmesh';
|
|
5
5
|
import {
|
|
6
6
|
ClientConfig,
|
|
7
7
|
Connection,
|
|
8
|
+
HookOptions,
|
|
8
9
|
WorkflowOptions,
|
|
9
10
|
WorkflowSearchOptions} from '../../types/durable';
|
|
10
11
|
import { JobState } from '../../types/job';
|
|
11
12
|
import { KeyService, KeyType } from '../../modules/key';
|
|
12
13
|
import { Search } from './search';
|
|
14
|
+
import { StreamStatus } from '../../types';
|
|
13
15
|
|
|
14
16
|
export class ClientService {
|
|
15
17
|
|
|
@@ -21,14 +23,14 @@ export class ClientService {
|
|
|
21
23
|
this.connection = config.connection;
|
|
22
24
|
}
|
|
23
25
|
|
|
24
|
-
getHotMeshClient = async (worflowTopic: string) => {
|
|
26
|
+
getHotMeshClient = async (worflowTopic: string, namespace?: string) => {
|
|
25
27
|
//NOTE: every unique topic inits a new engine
|
|
26
28
|
if (ClientService.instances.has(worflowTopic)) {
|
|
27
29
|
return await ClientService.instances.get(worflowTopic);
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
const hotMeshClient = HotMesh.init({
|
|
31
|
-
appId: APP_ID,
|
|
33
|
+
appId: namespace ?? APP_ID,
|
|
32
34
|
engine: {
|
|
33
35
|
redis: {
|
|
34
36
|
class: this.connection.class,
|
|
@@ -40,14 +42,14 @@ export class ClientService {
|
|
|
40
42
|
|
|
41
43
|
//since the YAML topic is dynamic, it MUST be manually created before use
|
|
42
44
|
const store = (await hotMeshClient).engine.store;
|
|
43
|
-
const params = { appId: APP_ID, topic: worflowTopic };
|
|
45
|
+
const params = { appId: namespace ?? APP_ID, topic: worflowTopic };
|
|
44
46
|
const streamKey = store.mintKey(KeyType.STREAMS, params);
|
|
45
47
|
try {
|
|
46
48
|
await store.xgroup('CREATE', streamKey, 'WORKER', '$', 'MKSTREAM');
|
|
47
49
|
} catch (err) {
|
|
48
50
|
//ignore if already exists
|
|
49
51
|
}
|
|
50
|
-
await this.activateWorkflow(await hotMeshClient);
|
|
52
|
+
await this.activateWorkflow(await hotMeshClient, namespace ?? APP_ID);
|
|
51
53
|
return hotMeshClient;
|
|
52
54
|
}
|
|
53
55
|
|
|
@@ -60,7 +62,7 @@ export class ClientService {
|
|
|
60
62
|
const store = hotMeshClient.engine.store;
|
|
61
63
|
const schema: string[] = [];
|
|
62
64
|
for (const [key, value] of Object.entries(search.schema)) {
|
|
63
|
-
//prefix with
|
|
65
|
+
//prefix with an underscore (avoids collisions with hotmesh reserved symbols)
|
|
64
66
|
schema.push(`_${key}`);
|
|
65
67
|
schema.push(value.type);
|
|
66
68
|
if (value.sortable) {
|
|
@@ -94,7 +96,7 @@ export class ClientService {
|
|
|
94
96
|
const spn = options.workflowSpan;
|
|
95
97
|
//topic is concat of taskQueue and workflowName
|
|
96
98
|
const workflowTopic = `${taskQueueName}-${workflowName}`;
|
|
97
|
-
const hotMeshClient = await this.getHotMeshClient(workflowTopic);
|
|
99
|
+
const hotMeshClient = await this.getHotMeshClient(workflowTopic, options.namespace);
|
|
98
100
|
this.configureSearchIndex(hotMeshClient, options.search)
|
|
99
101
|
const payload = {
|
|
100
102
|
arguments: [...options.args],
|
|
@@ -105,12 +107,13 @@ export class ClientService {
|
|
|
105
107
|
}
|
|
106
108
|
const context = { metadata: { trc, spn }, data: {}};
|
|
107
109
|
const jobId = await hotMeshClient.pub(
|
|
108
|
-
|
|
110
|
+
`${options.namespace ?? APP_ID}.execute`,
|
|
109
111
|
payload,
|
|
110
112
|
context as JobState);
|
|
111
113
|
if (jobId && options.search?.data) {
|
|
112
114
|
//job successfully kicked off; there is default job data to persist
|
|
113
|
-
const
|
|
115
|
+
const searchSessionId = `-search-0`;
|
|
116
|
+
const search = new Search(jobId, hotMeshClient, searchSessionId);
|
|
114
117
|
for (const [key, value] of Object.entries(options.search.data)) {
|
|
115
118
|
search.set(key, value);
|
|
116
119
|
}
|
|
@@ -118,19 +121,41 @@ export class ClientService {
|
|
|
118
121
|
return new WorkflowHandleService(hotMeshClient, workflowTopic, jobId);
|
|
119
122
|
},
|
|
120
123
|
|
|
121
|
-
|
|
122
|
-
|
|
124
|
+
/**
|
|
125
|
+
* send a message to a running workflow that is paused and awaiting the signal
|
|
126
|
+
*/
|
|
127
|
+
signal: async (signalId: string, data: Record<any, any>, namespace?: string): Promise<string> => {
|
|
128
|
+
const topic = `${namespace ?? APP_ID}.wfs.signal`;
|
|
129
|
+
return await (await this.getHotMeshClient(topic, namespace)).hook(topic, { id: signalId, data });
|
|
123
130
|
},
|
|
124
131
|
|
|
125
|
-
|
|
132
|
+
/**
|
|
133
|
+
* send a message to spawn an parallel in-process thread of execution
|
|
134
|
+
* with the same job state as the main thread but bound to a different
|
|
135
|
+
* handler function. All job state will be journaled to the same hash
|
|
136
|
+
* as is used by the main thread.
|
|
137
|
+
*/
|
|
138
|
+
hook: async (options: HookOptions): Promise<string> => {
|
|
139
|
+
const workflowTopic = `${options.taskQueue}-${options.workflowName}`;
|
|
140
|
+
const payload = {
|
|
141
|
+
arguments: [...options.args],
|
|
142
|
+
id: options.workflowId,
|
|
143
|
+
workflowTopic,
|
|
144
|
+
backoffCoefficient: options.config?.backoffCoefficient || DEFAULT_COEFFICIENT,
|
|
145
|
+
}
|
|
146
|
+
const hotMeshClient = await this.getHotMeshClient(workflowTopic, options.namespace);
|
|
147
|
+
return await hotMeshClient.hook(`${hotMeshClient.appId}.flow.signal`, payload, StreamStatus.PENDING, 202);
|
|
148
|
+
},
|
|
149
|
+
|
|
150
|
+
getHandle: async (taskQueue: string, workflowName: string, workflowId: string, namespace?: string): Promise<WorkflowHandleService> => {
|
|
126
151
|
const workflowTopic = `${taskQueue}-${workflowName}`;
|
|
127
|
-
const hotMeshClient = await this.getHotMeshClient(workflowTopic);
|
|
152
|
+
const hotMeshClient = await this.getHotMeshClient(workflowTopic, namespace);
|
|
128
153
|
return new WorkflowHandleService(hotMeshClient, workflowTopic, workflowId);
|
|
129
154
|
},
|
|
130
155
|
|
|
131
|
-
search: async (taskQueue: string, workflowName: string, index: string, ...query: string[]): Promise<string[]> => {
|
|
156
|
+
search: async (taskQueue: string, workflowName: string, namespace: null | string, index: string, ...query: string[]): Promise<string[]> => {
|
|
132
157
|
const workflowTopic = `${taskQueue}-${workflowName}`;
|
|
133
|
-
const hotMeshClient = await this.getHotMeshClient(workflowTopic);
|
|
158
|
+
const hotMeshClient = await this.getHotMeshClient(workflowTopic, namespace);
|
|
134
159
|
try {
|
|
135
160
|
return await this.search(hotMeshClient, index, query);
|
|
136
161
|
} catch (err) {
|