@hotmeshio/hotmesh 0.0.33 → 0.0.35
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 +30 -18
- package/build/modules/enums.d.ts +22 -0
- package/build/modules/enums.js +29 -0
- package/build/modules/errors.d.ts +10 -2
- package/build/modules/errors.js +14 -3
- package/build/modules/key.d.ts +16 -15
- package/build/modules/key.js +18 -15
- package/build/modules/utils.d.ts +1 -0
- package/build/modules/utils.js +6 -1
- package/build/package.json +4 -1
- package/build/services/activities/activity.d.ts +5 -0
- package/build/services/activities/activity.js +27 -6
- package/build/services/activities/await.js +11 -3
- package/build/services/activities/cycle.js +10 -2
- package/build/services/activities/hook.js +8 -2
- package/build/services/activities/index.d.ts +2 -2
- package/build/services/activities/index.js +2 -2
- package/build/services/activities/interrupt.d.ts +16 -0
- package/build/services/activities/interrupt.js +129 -0
- package/build/services/activities/signal.js +9 -2
- package/build/services/activities/trigger.d.ts +4 -0
- package/build/services/activities/trigger.js +14 -4
- package/build/services/activities/worker.js +10 -2
- package/build/services/collator/index.d.ts +4 -0
- package/build/services/collator/index.js +8 -0
- package/build/services/compiler/deployer.js +1 -3
- package/build/services/connector/index.js +2 -3
- package/build/services/durable/client.js +9 -6
- package/build/services/durable/factory.js +65 -284
- package/build/services/durable/handle.d.ts +37 -0
- package/build/services/durable/handle.js +52 -9
- package/build/services/durable/index.d.ts +5 -0
- package/build/services/durable/index.js +10 -0
- package/build/services/durable/meshos.js +3 -6
- package/build/services/durable/worker.js +11 -5
- package/build/services/durable/workflow.d.ts +24 -0
- package/build/services/durable/workflow.js +56 -1
- package/build/services/engine/index.d.ts +14 -6
- package/build/services/engine/index.js +52 -27
- package/build/services/hotmesh/index.d.ts +6 -2
- package/build/services/hotmesh/index.js +23 -5
- package/build/services/quorum/index.d.ts +1 -0
- package/build/services/quorum/index.js +10 -0
- package/build/services/signaler/stream.js +25 -29
- package/build/services/store/index.d.ts +40 -4
- package/build/services/store/index.js +114 -9
- package/build/services/task/index.d.ts +5 -4
- package/build/services/task/index.js +12 -14
- package/build/types/activity.d.ts +35 -5
- package/build/types/durable.d.ts +4 -0
- package/build/types/index.d.ts +1 -1
- package/build/types/job.d.ts +18 -1
- package/build/types/quorum.d.ts +11 -7
- package/build/types/stream.d.ts +4 -1
- package/build/types/stream.js +2 -0
- package/modules/enums.ts +32 -0
- package/modules/errors.ts +24 -9
- package/modules/key.ts +4 -1
- package/modules/utils.ts +5 -0
- package/package.json +4 -1
- package/services/activities/activity.ts +34 -8
- package/services/activities/await.ts +11 -4
- package/services/activities/cycle.ts +10 -3
- package/services/activities/hook.ts +8 -3
- package/services/activities/index.ts +2 -2
- package/services/activities/interrupt.ts +159 -0
- package/services/activities/signal.ts +9 -3
- package/services/activities/trigger.ts +21 -5
- package/services/activities/worker.ts +10 -3
- package/services/collator/index.ts +10 -1
- package/services/compiler/deployer.ts +1 -3
- package/services/connector/index.ts +3 -5
- package/services/durable/client.ts +10 -7
- package/services/durable/factory.ts +65 -284
- package/services/durable/handle.ts +55 -9
- package/services/durable/index.ts +11 -0
- package/services/durable/meshos.ts +3 -7
- package/services/durable/worker.ts +11 -5
- package/services/durable/workflow.ts +66 -2
- package/services/engine/index.ts +74 -26
- package/services/hotmesh/index.ts +28 -6
- package/services/quorum/index.ts +9 -0
- package/services/signaler/stream.ts +28 -25
- package/services/store/index.ts +119 -11
- package/services/task/index.ts +18 -18
- package/types/activity.ts +38 -8
- package/types/durable.ts +8 -4
- package/types/index.ts +1 -1
- package/types/job.ts +30 -1
- package/types/quorum.ts +13 -8
- package/types/stream.ts +3 -0
- package/build/services/activities/iterate.d.ts +0 -9
- package/build/services/activities/iterate.js +0 -13
- package/services/activities/iterate.ts +0 -26
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { EngineService } from '../engine';
|
|
2
|
+
import { Activity, ActivityType } from './activity';
|
|
3
|
+
import {
|
|
4
|
+
ActivityData,
|
|
5
|
+
ActivityMetadata,
|
|
6
|
+
InterruptActivity } from '../../types/activity';
|
|
7
|
+
import { GetStateError, InactiveJobError } from '../../modules/errors';
|
|
8
|
+
import { MultiResponseFlags } from '../../types';
|
|
9
|
+
import { CollatorService } from '../collator';
|
|
10
|
+
import { JobInterruptOptions, JobState } from '../../types/job';
|
|
11
|
+
import { TelemetryService } from '../telemetry';
|
|
12
|
+
import { Pipe } from '../pipe';
|
|
13
|
+
|
|
14
|
+
class Interrupt extends Activity {
|
|
15
|
+
config: InterruptActivity;
|
|
16
|
+
|
|
17
|
+
constructor(
|
|
18
|
+
config: ActivityType,
|
|
19
|
+
data: ActivityData,
|
|
20
|
+
metadata: ActivityMetadata,
|
|
21
|
+
hook: ActivityData | null,
|
|
22
|
+
engine: EngineService,
|
|
23
|
+
context?: JobState
|
|
24
|
+
) {
|
|
25
|
+
super(config, data, metadata, hook, engine, context);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
//******** LEG 1 ENTRY ********//
|
|
30
|
+
async process(): Promise<string> {
|
|
31
|
+
this.logger.debug('interrupt-process', { jid: this.context.metadata.jid, aid: this.metadata.aid });
|
|
32
|
+
let telemetry: TelemetryService;
|
|
33
|
+
try {
|
|
34
|
+
this.setLeg(1);
|
|
35
|
+
await CollatorService.notarizeEntry(this);
|
|
36
|
+
await this.getState();
|
|
37
|
+
CollatorService.assertJobActive(this.context.metadata.js, this.context.metadata.jid, this.metadata.aid); // Ensure job active
|
|
38
|
+
telemetry = new TelemetryService(this.engine.appId, this.config, this.metadata, this.context);
|
|
39
|
+
telemetry.startActivitySpan(this.leg);
|
|
40
|
+
|
|
41
|
+
if (this.isInterruptingSelf()) {
|
|
42
|
+
return await this.interruptSelf(telemetry);
|
|
43
|
+
} else {
|
|
44
|
+
return await this.interruptAnother(telemetry);
|
|
45
|
+
}
|
|
46
|
+
} catch (error) {
|
|
47
|
+
if (error instanceof InactiveJobError) {
|
|
48
|
+
this.logger.error('interrupt-inactive-job-error', { error });
|
|
49
|
+
return;
|
|
50
|
+
} else if (error instanceof GetStateError) {
|
|
51
|
+
this.logger.error('interrupt-get-state-error', { error });
|
|
52
|
+
return;
|
|
53
|
+
} else {
|
|
54
|
+
this.logger.error('interrupt-process-error', { error });
|
|
55
|
+
}
|
|
56
|
+
telemetry.setActivityError(error.message);
|
|
57
|
+
throw error;
|
|
58
|
+
} finally {
|
|
59
|
+
telemetry?.endActivitySpan();
|
|
60
|
+
this.logger.debug('interrupt-process-end', { jid: this.context.metadata.jid, aid: this.metadata.aid });
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async interruptSelf(telemetry: TelemetryService): Promise<string> {
|
|
65
|
+
// Apply final updates to THIS job's state
|
|
66
|
+
if (this.config.job?.maps) {
|
|
67
|
+
this.mapJobData();
|
|
68
|
+
await this.setState();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Interrupt THIS job
|
|
72
|
+
const messageId = await this.interrupt();
|
|
73
|
+
|
|
74
|
+
// Notarize completion and log
|
|
75
|
+
telemetry.mapActivityAttributes();
|
|
76
|
+
const multi = this.store.getMulti();
|
|
77
|
+
await CollatorService.notarizeEarlyCompletion(this, multi);
|
|
78
|
+
await this.setStatus(-1, multi);
|
|
79
|
+
const multiResponse = await multi.exec() as MultiResponseFlags;
|
|
80
|
+
const jobStatus = this.resolveStatus(multiResponse);
|
|
81
|
+
telemetry.setActivityAttributes({
|
|
82
|
+
'app.activity.mid': messageId,
|
|
83
|
+
'app.job.jss': jobStatus
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
return this.context.metadata.aid;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async interruptAnother(telemetry: TelemetryService): Promise<string> {
|
|
90
|
+
// Interrupt ANOTHER job
|
|
91
|
+
const messageId = await this.interrupt();
|
|
92
|
+
const attrs = { 'app.activity.mid': messageId };
|
|
93
|
+
|
|
94
|
+
// Apply updates to THIS job's state
|
|
95
|
+
telemetry.mapActivityAttributes();
|
|
96
|
+
this.adjacencyList = await this.filterAdjacent();
|
|
97
|
+
if (this.config.job?.maps || this.config.output?.maps) {
|
|
98
|
+
this.mapOutputData();
|
|
99
|
+
this.mapJobData();
|
|
100
|
+
const multi = this.store.getMulti();
|
|
101
|
+
await this.setState(multi);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Notarize completion
|
|
105
|
+
const multi = this.store.getMulti();
|
|
106
|
+
await CollatorService.notarizeEarlyCompletion(this, multi);
|
|
107
|
+
await this.setStatus(this.adjacencyList.length - 1, multi);
|
|
108
|
+
const multiResponse = await multi.exec() as MultiResponseFlags;
|
|
109
|
+
const jobStatus = this.resolveStatus(multiResponse);
|
|
110
|
+
attrs['app.job.jss'] = jobStatus;
|
|
111
|
+
|
|
112
|
+
// Transition next generation and log
|
|
113
|
+
const messageIds = await this.transition(this.adjacencyList, jobStatus);
|
|
114
|
+
if (messageIds.length) {
|
|
115
|
+
attrs['app.activity.mids'] = messageIds.join(',');
|
|
116
|
+
}
|
|
117
|
+
telemetry.setActivityAttributes(attrs);
|
|
118
|
+
|
|
119
|
+
return this.context.metadata.aid;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
isInterruptingSelf(): boolean {
|
|
124
|
+
if (!this.config.target) {
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
const resolvedJob = Pipe.resolve(this.config.target, this.context);
|
|
128
|
+
return resolvedJob == this.context.metadata.jid;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
resolveInterruptOptions(): JobInterruptOptions {
|
|
132
|
+
return {
|
|
133
|
+
reason: this.config.reason !== undefined
|
|
134
|
+
? Pipe.resolve(this.config.reason, this.context)
|
|
135
|
+
: undefined,
|
|
136
|
+
throw: this.config.throw !== undefined
|
|
137
|
+
? Pipe.resolve(this.config.throw, this.context)
|
|
138
|
+
: undefined,
|
|
139
|
+
descend: this.config.descend !== undefined
|
|
140
|
+
? Pipe.resolve(this.config.descend, this.context)
|
|
141
|
+
: undefined,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
async interrupt(): Promise<string> {
|
|
146
|
+
const options = this.resolveInterruptOptions();
|
|
147
|
+
return await this.engine.interrupt(
|
|
148
|
+
this.config.topic !== undefined
|
|
149
|
+
? Pipe.resolve(this.config.topic, this.context)
|
|
150
|
+
: this.context.metadata.tpc,
|
|
151
|
+
this.config.target !== undefined
|
|
152
|
+
? Pipe.resolve(this.config.target, this.context)
|
|
153
|
+
: this.context.metadata.jid,
|
|
154
|
+
options as JobInterruptOptions,
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export { Interrupt };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { GetStateError } from '../../modules/errors';
|
|
1
|
+
import { GetStateError, InactiveJobError } from '../../modules/errors';
|
|
2
2
|
import { Activity, ActivityType } from './activity';
|
|
3
3
|
import { CollatorService } from '../collator';
|
|
4
4
|
import { EngineService } from '../engine';
|
|
@@ -37,6 +37,7 @@ class Signal extends Activity {
|
|
|
37
37
|
this.setLeg(1);
|
|
38
38
|
await CollatorService.notarizeEntry(this);
|
|
39
39
|
await this.getState();
|
|
40
|
+
CollatorService.assertJobActive(this.context.metadata.js, this.context.metadata.jid, this.metadata.aid);
|
|
40
41
|
telemetry = new TelemetryService(this.engine.appId, this.config, this.metadata, this.context);
|
|
41
42
|
telemetry.startActivitySpan(this.leg);
|
|
42
43
|
|
|
@@ -50,6 +51,7 @@ class Signal extends Activity {
|
|
|
50
51
|
await this.setStatus(this.adjacencyList.length - 1, multi);
|
|
51
52
|
const multiResponse = await multi.exec() as MultiResponseFlags;
|
|
52
53
|
|
|
54
|
+
//todo: this should execute BEFORE the status is decremented
|
|
53
55
|
if (this.config.subtype === 'all') {
|
|
54
56
|
await this.hookAll();
|
|
55
57
|
} else {
|
|
@@ -68,15 +70,19 @@ class Signal extends Activity {
|
|
|
68
70
|
|
|
69
71
|
return this.context.metadata.aid;
|
|
70
72
|
} catch (error) {
|
|
71
|
-
if (error instanceof
|
|
73
|
+
if (error instanceof InactiveJobError) {
|
|
74
|
+
this.logger.error('signal-inactive-job-error', { error });
|
|
75
|
+
return;
|
|
76
|
+
} else if (error instanceof GetStateError) {
|
|
72
77
|
this.logger.error('signal-get-state-error', { error });
|
|
78
|
+
return;
|
|
73
79
|
} else {
|
|
74
80
|
this.logger.error('signal-process-error', { error });
|
|
75
81
|
}
|
|
76
82
|
telemetry.setActivityError(error.message);
|
|
77
83
|
throw error;
|
|
78
84
|
} finally {
|
|
79
|
-
telemetry
|
|
85
|
+
telemetry?.endActivitySpan();
|
|
80
86
|
this.logger.debug('signal-process-end', { jid: this.context.metadata.jid, aid: this.metadata.aid });
|
|
81
87
|
}
|
|
82
88
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { nanoid } from 'nanoid';
|
|
2
1
|
import { DuplicateJobError } from '../../modules/errors';
|
|
3
|
-
import { formatISODate, getTimeSeries } from '../../modules/utils';
|
|
2
|
+
import { formatISODate, getTimeSeries, guid } from '../../modules/utils';
|
|
4
3
|
import { Activity } from './activity';
|
|
5
4
|
import { CollatorService } from '../collator';
|
|
6
5
|
import { EngineService } from '../engine';
|
|
@@ -47,6 +46,7 @@ class Trigger extends Activity {
|
|
|
47
46
|
const multi = this.store.getMulti();
|
|
48
47
|
await this.setState(multi);
|
|
49
48
|
await this.setStats(multi);
|
|
49
|
+
await this.setDependency(multi);
|
|
50
50
|
await multi.exec();
|
|
51
51
|
|
|
52
52
|
telemetry.mapActivityAttributes();
|
|
@@ -68,8 +68,8 @@ class Trigger extends Activity {
|
|
|
68
68
|
telemetry.setActivityError(error.message);
|
|
69
69
|
throw error;
|
|
70
70
|
} finally {
|
|
71
|
-
telemetry
|
|
72
|
-
telemetry
|
|
71
|
+
telemetry?.endJobSpan();
|
|
72
|
+
telemetry?.endActivitySpan();
|
|
73
73
|
this.logger.debug('trigger-process-end', { subscribes: this.config.subscribes, jid: this.context.metadata.jid });
|
|
74
74
|
}
|
|
75
75
|
}
|
|
@@ -161,7 +161,7 @@ class Trigger extends Activity {
|
|
|
161
161
|
|
|
162
162
|
resolveJobId(context: Partial<JobState>): string {
|
|
163
163
|
const jobId = this.config.stats?.id;
|
|
164
|
-
return jobId ? Pipe.resolve(jobId, context) :
|
|
164
|
+
return jobId ? Pipe.resolve(jobId, context) : guid();
|
|
165
165
|
}
|
|
166
166
|
|
|
167
167
|
resolveJobKey(context: Partial<JobState>): string {
|
|
@@ -176,6 +176,22 @@ class Trigger extends Activity {
|
|
|
176
176
|
}
|
|
177
177
|
}
|
|
178
178
|
|
|
179
|
+
/**
|
|
180
|
+
* Registers this job as a dependent of the parent job
|
|
181
|
+
*/
|
|
182
|
+
async setDependency(multi?: RedisMulti): Promise<void> {
|
|
183
|
+
const depKey = this.config.stats?.parent;
|
|
184
|
+
const resolvedDepKey = depKey ? Pipe.resolve(depKey, this.context) : '';
|
|
185
|
+
if (resolvedDepKey) {
|
|
186
|
+
await this.store.setDependency(
|
|
187
|
+
resolvedDepKey,
|
|
188
|
+
this.context.metadata.tpc,
|
|
189
|
+
this.context.metadata.jid,
|
|
190
|
+
multi,
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
179
195
|
async setStats(multi?: RedisMulti): Promise<void> {
|
|
180
196
|
const md = this.context.metadata;
|
|
181
197
|
if (md.key && this.config.stats?.measures) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { GetStateError } from '../../modules/errors';
|
|
1
|
+
import { GetStateError, InactiveJobError } from '../../modules/errors';
|
|
2
2
|
import { Activity } from './activity';
|
|
3
3
|
import { CollatorService } from '../collator';
|
|
4
4
|
import { EngineService } from '../engine';
|
|
@@ -12,6 +12,7 @@ import { MultiResponseFlags, RedisMulti } from '../../types/redis';
|
|
|
12
12
|
import { StreamData} from '../../types/stream';
|
|
13
13
|
import { TelemetryService } from '../telemetry';
|
|
14
14
|
import { Pipe } from '../pipe';
|
|
15
|
+
import { guid } from '../../modules/utils';
|
|
15
16
|
|
|
16
17
|
class Worker extends Activity {
|
|
17
18
|
config: WorkerActivity;
|
|
@@ -35,6 +36,7 @@ class Worker extends Activity {
|
|
|
35
36
|
this.setLeg(1);
|
|
36
37
|
await CollatorService.notarizeEntry(this);
|
|
37
38
|
await this.getState();
|
|
39
|
+
CollatorService.assertJobActive(this.context.metadata.js, this.context.metadata.jid, this.metadata.aid);
|
|
38
40
|
telemetry = new TelemetryService(this.engine.appId, this.config, this.metadata, this.context);
|
|
39
41
|
telemetry.startActivitySpan(this.leg);
|
|
40
42
|
this.mapInputData();
|
|
@@ -58,15 +60,19 @@ class Worker extends Activity {
|
|
|
58
60
|
|
|
59
61
|
return this.context.metadata.aid;
|
|
60
62
|
} catch (error) {
|
|
61
|
-
if (error instanceof
|
|
63
|
+
if (error instanceof InactiveJobError) {
|
|
64
|
+
this.logger.error('await-inactive-job-error', { error });
|
|
65
|
+
return;
|
|
66
|
+
} else if (error instanceof GetStateError) {
|
|
62
67
|
this.logger.error('worker-get-state-error', { error });
|
|
68
|
+
return;
|
|
63
69
|
} else {
|
|
64
70
|
this.logger.error('worker-process-error', { error });
|
|
65
71
|
}
|
|
66
72
|
telemetry.setActivityError(error.message);
|
|
67
73
|
throw error;
|
|
68
74
|
} finally {
|
|
69
|
-
telemetry
|
|
75
|
+
telemetry?.endActivitySpan();
|
|
70
76
|
this.logger.debug('worker-process-end', { jid: this.context.metadata.jid, aid: this.metadata.aid });
|
|
71
77
|
}
|
|
72
78
|
}
|
|
@@ -75,6 +81,7 @@ class Worker extends Activity {
|
|
|
75
81
|
const topic = Pipe.resolve(this.config.subtype, this.context);
|
|
76
82
|
const streamData: StreamData = {
|
|
77
83
|
metadata: {
|
|
84
|
+
guid: guid(),
|
|
78
85
|
jid: this.context.metadata.jid,
|
|
79
86
|
dad: this.metadata.dad,
|
|
80
87
|
aid: this.metadata.aid,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CollationError } from '../../modules/errors';
|
|
1
|
+
import { CollationError, InactiveJobError } from '../../modules/errors';
|
|
2
2
|
import { RedisMulti } from '../../types/redis';
|
|
3
3
|
import { CollationFaultType, CollationStage } from '../../types/collator';
|
|
4
4
|
import { ActivityDuplex } from '../../types/activity';
|
|
@@ -11,6 +11,15 @@ class CollatorService {
|
|
|
11
11
|
//max int digit count that supports `hincrby`
|
|
12
12
|
static targetLength = 15;
|
|
13
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Upon re/entry, verify that the job status is active
|
|
16
|
+
*/
|
|
17
|
+
static assertJobActive(status: number, jobId: string, activityId: string): void {
|
|
18
|
+
if (status <= 0) {
|
|
19
|
+
throw new InactiveJobError(jobId, status, activityId);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
14
23
|
/**
|
|
15
24
|
* returns the dimensional address (dad) for the target; due
|
|
16
25
|
* to the nature of the notary system, the dad for leg 2 entry
|
|
@@ -143,9 +143,7 @@ class Deployer {
|
|
|
143
143
|
if (graph.publishes) {
|
|
144
144
|
activities[activityKey].publishes = graph.publishes;
|
|
145
145
|
}
|
|
146
|
-
|
|
147
|
-
activities[activityKey].expire = graph.expire;
|
|
148
|
-
}
|
|
146
|
+
activities[activityKey].expire = graph.expire ?? undefined;
|
|
149
147
|
}
|
|
150
148
|
}
|
|
151
149
|
}
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import { identifyRedisTypeFromClass } from '../../modules/utils';
|
|
1
|
+
import { guid, identifyRedisTypeFromClass } from '../../modules/utils';
|
|
4
2
|
import { RedisConnection as IORedisConnection } from '../connector/clients/ioredis';
|
|
5
3
|
import { RedisConnection } from '../connector/clients/redis';
|
|
6
4
|
import {
|
|
@@ -23,14 +21,14 @@ export class ConnectorService {
|
|
|
23
21
|
if (identifyRedisTypeFromClass(Redis) === 'redis') {
|
|
24
22
|
for (let i = 1; i <= 3; i++) {
|
|
25
23
|
instances.push(RedisConnection.connect(
|
|
26
|
-
|
|
24
|
+
guid(),
|
|
27
25
|
Redis as RedisClassType,
|
|
28
26
|
options as RedisClientOptions));
|
|
29
27
|
}
|
|
30
28
|
} else {
|
|
31
29
|
for (let i = 1; i <= 3; i++) {
|
|
32
30
|
instances.push(IORedisConnection.connect(
|
|
33
|
-
|
|
31
|
+
guid(),
|
|
34
32
|
Redis as IORedisClassType,
|
|
35
33
|
options as IORedisClientOptions));
|
|
36
34
|
}
|
|
@@ -11,6 +11,7 @@ import { JobState } from '../../types/job';
|
|
|
11
11
|
import { KeyService, KeyType } from '../../modules/key';
|
|
12
12
|
import { Search } from './search';
|
|
13
13
|
import { StreamStatus } from '../../types';
|
|
14
|
+
import { DURABLE_EXPIRE_SECONDS } from '../../modules/enums';
|
|
14
15
|
|
|
15
16
|
export class ClientService {
|
|
16
17
|
|
|
@@ -96,12 +97,15 @@ export class ClientService {
|
|
|
96
97
|
const workflowName = options.entity ?? options.workflowName;
|
|
97
98
|
const trc = options.workflowTrace;
|
|
98
99
|
const spn = options.workflowSpan;
|
|
99
|
-
//
|
|
100
|
+
//NOTE: HotMesh 'workflowTopic' is a created by concatenating
|
|
101
|
+
// the taskQueue and workflowName used by the Durable module
|
|
100
102
|
const workflowTopic = `${taskQueueName}-${workflowName}`;
|
|
101
103
|
const hotMeshClient = await this.getHotMeshClient(workflowTopic, options.namespace);
|
|
102
|
-
this.configureSearchIndex(hotMeshClient, options.search)
|
|
104
|
+
this.configureSearchIndex(hotMeshClient, options.search);
|
|
103
105
|
const payload = {
|
|
104
106
|
arguments: [...options.args],
|
|
107
|
+
originJobId: options.originJobId,
|
|
108
|
+
expire: options.expire ?? DURABLE_EXPIRE_SECONDS,
|
|
105
109
|
parentWorkflowId: options.parentWorkflowId,
|
|
106
110
|
workflowId: options.workflowId || HotMesh.guid(),
|
|
107
111
|
workflowTopic: workflowTopic,
|
|
@@ -113,12 +117,12 @@ export class ClientService {
|
|
|
113
117
|
payload,
|
|
114
118
|
context as JobState
|
|
115
119
|
);
|
|
116
|
-
// Seed search data
|
|
120
|
+
// Seed search data
|
|
117
121
|
if (jobId && options.search?.data) {
|
|
118
122
|
const searchSessionId = `-search-0`;
|
|
119
123
|
const search = new Search(jobId, hotMeshClient, searchSessionId);
|
|
120
124
|
const entries = Object.entries(options.search.data).flat();
|
|
121
|
-
search.set(...entries);
|
|
125
|
+
await search.set(...entries);
|
|
122
126
|
}
|
|
123
127
|
return new WorkflowHandleService(hotMeshClient, workflowTopic, jobId);
|
|
124
128
|
},
|
|
@@ -198,9 +202,8 @@ export class ClientService {
|
|
|
198
202
|
}
|
|
199
203
|
|
|
200
204
|
static async shutdown(): Promise<void> {
|
|
201
|
-
for (const [
|
|
202
|
-
|
|
203
|
-
await hotMesh.stop();
|
|
205
|
+
for (const [_, hotMeshInstance] of ClientService.instances) {
|
|
206
|
+
(await hotMeshInstance).stop();
|
|
204
207
|
}
|
|
205
208
|
}
|
|
206
209
|
}
|