@hotmeshio/hotmesh 0.0.14 → 0.0.16
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 +1 -1
- package/build/package.json +1 -1
- package/build/services/activities/activity.js +10 -2
- package/build/services/durable/client.d.ts +1 -0
- package/build/services/durable/client.js +5 -0
- package/build/services/durable/factory.d.ts +5 -0
- package/build/services/durable/factory.js +5 -0
- package/build/services/durable/workflow.js +18 -9
- package/build/services/store/index.js +3 -0
- package/package.json +1 -1
- package/services/activities/activity.ts +11 -3
- package/services/durable/client.ts +6 -0
- package/services/durable/factory.ts +5 -0
- package/services/durable/workflow.ts +23 -10
- package/services/store/index.ts +3 -0
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@ The HotMesh SDK is designed to keep your code front-and-center. Write functions
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
export async function saludar(nombre: string): Promise<string> {
|
|
25
|
-
Math.random() > 0.5
|
|
25
|
+
if (Math.random() > 0.5) throw new Error('Random error');
|
|
26
26
|
return `¡Hola, ${nombre}!`;
|
|
27
27
|
}
|
|
28
28
|
```
|
package/build/package.json
CHANGED
|
@@ -136,10 +136,10 @@ class Activity {
|
|
|
136
136
|
try {
|
|
137
137
|
this.setLeg(2);
|
|
138
138
|
await this.getState(jobId);
|
|
139
|
-
const aState = await collator_1.CollatorService.notarizeReentry(this);
|
|
140
|
-
this.adjacentIndex = collator_1.CollatorService.getDimensionalIndex(aState);
|
|
141
139
|
telemetry = new telemetry_1.TelemetryService(this.engine.appId, this.config, this.metadata, this.context);
|
|
142
140
|
telemetry.startActivitySpan(this.leg);
|
|
141
|
+
const aState = await collator_1.CollatorService.notarizeReentry(this);
|
|
142
|
+
this.adjacentIndex = collator_1.CollatorService.getDimensionalIndex(aState);
|
|
143
143
|
this.bindActivityData('hook');
|
|
144
144
|
this.mapJobData();
|
|
145
145
|
this.adjacencyList = await this.filterAdjacent();
|
|
@@ -159,6 +159,10 @@ class Activity {
|
|
|
159
159
|
return jobStatus;
|
|
160
160
|
}
|
|
161
161
|
catch (error) {
|
|
162
|
+
if (error instanceof errors_1.CollationError && error.fault === 'inactive') {
|
|
163
|
+
this.logger.info('process-hook-event-inactive-error', { error });
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
162
166
|
this.logger.error('engine-process-hook-event-error', { error });
|
|
163
167
|
telemetry.setActivityError(error.message);
|
|
164
168
|
throw error;
|
|
@@ -201,6 +205,10 @@ class Activity {
|
|
|
201
205
|
this.transitionAdjacent(multiResponse, telemetry);
|
|
202
206
|
}
|
|
203
207
|
catch (error) {
|
|
208
|
+
if (error instanceof errors_1.CollationError && error.fault === 'inactive') {
|
|
209
|
+
this.logger.info('process-event-inactive-error', { error });
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
204
212
|
this.logger.error('activity-process-event-error', { error });
|
|
205
213
|
telemetry && telemetry.setActivityError(error.message);
|
|
206
214
|
throw error;
|
|
@@ -10,6 +10,7 @@ export declare class ClientService {
|
|
|
10
10
|
workflow: {
|
|
11
11
|
start: (options: WorkflowOptions) => Promise<WorkflowHandleService>;
|
|
12
12
|
signal: (signalId: string, data: Record<any, any>) => Promise<string>;
|
|
13
|
+
getHandle: (taskQueue: string, workflowName: string, workflowId: string) => Promise<WorkflowHandleService>;
|
|
13
14
|
};
|
|
14
15
|
activateWorkflow(hotMesh: HotMesh, appId?: string, version?: string): Promise<void>;
|
|
15
16
|
static shutdown(): Promise<void>;
|
|
@@ -97,6 +97,11 @@ class ClientService {
|
|
|
97
97
|
},
|
|
98
98
|
signal: async (signalId, data) => {
|
|
99
99
|
return await (await this.getHotMeshClient('durable.wfs.signal')).hook('durable.wfs.signal', { id: signalId, data });
|
|
100
|
+
},
|
|
101
|
+
getHandle: async (taskQueue, workflowName, workflowId) => {
|
|
102
|
+
const workflowTopic = `${taskQueue}-${workflowName}`;
|
|
103
|
+
const hotMeshClient = await this.getHotMeshClient(workflowTopic);
|
|
104
|
+
return new handle_1.WorkflowHandleService(hotMeshClient, workflowTopic, workflowId);
|
|
100
105
|
}
|
|
101
106
|
};
|
|
102
107
|
this.connection = config.connection;
|
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
* NOTE: Using `maxSystemRetries = 3` and `backoffCoefficient = 10`, errant
|
|
3
3
|
* workflows will be retried on the following schedule (8 times in 27 hours):
|
|
4
4
|
* => 10ms, 100ms, 1000ms, 10s, 100s, 1_000s, 10_000s, 100_000s
|
|
5
|
+
* 593:
|
|
6
|
+
* 594: waitforsignal
|
|
7
|
+
* 595: sleep
|
|
8
|
+
* 596, 597, 598: fatal
|
|
9
|
+
* 599: retry
|
|
5
10
|
*/
|
|
6
11
|
declare const getWorkflowYAML: (app: string, version: string) => string;
|
|
7
12
|
declare const APP_VERSION = "1";
|
|
@@ -3,6 +3,11 @@
|
|
|
3
3
|
* NOTE: Using `maxSystemRetries = 3` and `backoffCoefficient = 10`, errant
|
|
4
4
|
* workflows will be retried on the following schedule (8 times in 27 hours):
|
|
5
5
|
* => 10ms, 100ms, 1000ms, 10s, 100s, 1_000s, 10_000s, 100_000s
|
|
6
|
+
* 593:
|
|
7
|
+
* 594: waitforsignal
|
|
8
|
+
* 595: sleep
|
|
9
|
+
* 596, 597, 598: fatal
|
|
10
|
+
* 599: retry
|
|
6
11
|
*/
|
|
7
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
13
|
exports.WFS_HOOK_ID = exports.WFSC_PUBLISHES_TOPIC = exports.WFSC_SUBSCRIBES_TOPIC = exports.WFS_PUBLISHES_TOPIC = exports.WFS_SUBSCRIBES_TOPIC = exports.DEFAULT_COEFFICIENT = exports.SLEEP_HOOK_ID = exports.ACTIVITY_HOOK_ID = exports.HOOK_ID = exports.PUBLISHES_TOPIC = exports.SUBSCRIBES_TOPIC = exports.SLEEP_PUBLISHES_TOPIC = exports.SLEEP_SUBSCRIBES_TOPIC = exports.ACTIVITY_PUBLISHES_TOPIC = exports.ACTIVITY_SUBSCRIBES_TOPIC = exports.APP_ID = exports.APP_VERSION = exports.getWorkflowYAML = void 0;
|
|
@@ -51,17 +51,26 @@ class WorkflowService {
|
|
|
51
51
|
const workflowId = store.get('workflowId');
|
|
52
52
|
const workflowTrace = store.get('workflowTrace');
|
|
53
53
|
const workflowSpan = store.get('workflowSpan');
|
|
54
|
+
const COUNTER = store.get('counter');
|
|
55
|
+
const execIndex = COUNTER.counter = COUNTER.counter + 1;
|
|
56
|
+
const childJobId = `${workflowId}-$${options.workflowName}-${execIndex}`;
|
|
54
57
|
const client = new client_1.ClientService({
|
|
55
58
|
connection: await connection_1.ConnectionService.connect(worker_1.WorkerService.connection),
|
|
56
59
|
});
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
60
|
+
let handle = await client.workflow.getHandle(options.taskQueue, options.workflowName, childJobId);
|
|
61
|
+
try {
|
|
62
|
+
return await handle.result();
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
handle = await client.workflow.start({
|
|
66
|
+
...options,
|
|
67
|
+
workflowId: childJobId,
|
|
68
|
+
workflowTrace,
|
|
69
|
+
workflowSpan,
|
|
70
|
+
});
|
|
71
|
+
const result = await handle.result();
|
|
72
|
+
return result;
|
|
73
|
+
}
|
|
65
74
|
}
|
|
66
75
|
static proxyActivities(options) {
|
|
67
76
|
if (options.activities) {
|
|
@@ -168,7 +177,7 @@ class WorkflowService {
|
|
|
168
177
|
const trc = store.get('workflowTrace');
|
|
169
178
|
const spn = store.get('workflowSpan');
|
|
170
179
|
const activityTopic = `${workflowTopic}-activity`;
|
|
171
|
-
const activityJobId = `${workflowId}
|
|
180
|
+
const activityJobId = `${workflowId}-$${activityName}-${execIndex}`;
|
|
172
181
|
let activityState;
|
|
173
182
|
try {
|
|
174
183
|
const hotMeshClient = await worker_1.WorkerService.getHotMesh(activityTopic);
|
|
@@ -373,6 +373,9 @@ class StoreService {
|
|
|
373
373
|
async getStatus(jobId, appId) {
|
|
374
374
|
const jobKey = this.mintKey(key_1.KeyType.JOB_STATE, { appId, jobId });
|
|
375
375
|
const status = await this.redisClient[this.commands.hget](jobKey, ':');
|
|
376
|
+
if (status === null) {
|
|
377
|
+
throw new Error(`Job ${jobId} not found`);
|
|
378
|
+
}
|
|
376
379
|
return Number(status);
|
|
377
380
|
}
|
|
378
381
|
async setState({ ...state }, status, jobId, symbolNames, dIds, multi) {
|
package/package.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { GetStateError } from '../../modules/errors';
|
|
1
|
+
import { CollationError, GetStateError } from '../../modules/errors';
|
|
2
2
|
import {
|
|
3
3
|
formatISODate,
|
|
4
4
|
getValueByPath,
|
|
@@ -183,11 +183,11 @@ class Activity {
|
|
|
183
183
|
try {
|
|
184
184
|
this.setLeg(2);
|
|
185
185
|
await this.getState(jobId);
|
|
186
|
+
telemetry = new TelemetryService(this.engine.appId, this.config, this.metadata, this.context);
|
|
187
|
+
telemetry.startActivitySpan(this.leg);
|
|
186
188
|
const aState = await CollatorService.notarizeReentry(this);
|
|
187
189
|
this.adjacentIndex = CollatorService.getDimensionalIndex(aState);
|
|
188
190
|
|
|
189
|
-
telemetry = new TelemetryService(this.engine.appId, this.config, this.metadata, this.context);
|
|
190
|
-
telemetry.startActivitySpan(this.leg);
|
|
191
191
|
this.bindActivityData('hook');
|
|
192
192
|
this.mapJobData();
|
|
193
193
|
this.adjacencyList = await this.filterAdjacent();
|
|
@@ -209,6 +209,10 @@ class Activity {
|
|
|
209
209
|
telemetry.setActivityAttributes(attrs);
|
|
210
210
|
return jobStatus as number;
|
|
211
211
|
} catch (error) {
|
|
212
|
+
if (error instanceof CollationError && error.fault === 'inactive') {
|
|
213
|
+
this.logger.info('process-hook-event-inactive-error', { error });
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
212
216
|
this.logger.error('engine-process-hook-event-error', { error });
|
|
213
217
|
telemetry.setActivityError(error.message);
|
|
214
218
|
throw error;
|
|
@@ -251,6 +255,10 @@ class Activity {
|
|
|
251
255
|
}
|
|
252
256
|
this.transitionAdjacent(multiResponse, telemetry);
|
|
253
257
|
} catch (error) {
|
|
258
|
+
if (error instanceof CollationError && error.fault === 'inactive') {
|
|
259
|
+
this.logger.info('process-event-inactive-error', { error });
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
254
262
|
this.logger.error('activity-process-event-error', { error });
|
|
255
263
|
telemetry && telemetry.setActivityError(error.message);
|
|
256
264
|
throw error;
|
|
@@ -115,6 +115,12 @@ export class ClientService {
|
|
|
115
115
|
|
|
116
116
|
signal: async (signalId: string, data: Record<any, any>): Promise<string> => {
|
|
117
117
|
return await (await this.getHotMeshClient('durable.wfs.signal')).hook('durable.wfs.signal', { id: signalId, data });
|
|
118
|
+
},
|
|
119
|
+
|
|
120
|
+
getHandle: async (taskQueue: string, workflowName: string, workflowId: string): Promise<WorkflowHandleService> => {
|
|
121
|
+
const workflowTopic = `${taskQueue}-${workflowName}`;
|
|
122
|
+
const hotMeshClient = await this.getHotMeshClient(workflowTopic);
|
|
123
|
+
return new WorkflowHandleService(hotMeshClient, workflowTopic, workflowId);
|
|
118
124
|
}
|
|
119
125
|
}
|
|
120
126
|
|
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
* NOTE: Using `maxSystemRetries = 3` and `backoffCoefficient = 10`, errant
|
|
3
3
|
* workflows will be retried on the following schedule (8 times in 27 hours):
|
|
4
4
|
* => 10ms, 100ms, 1000ms, 10s, 100s, 1_000s, 10_000s, 100_000s
|
|
5
|
+
* 593:
|
|
6
|
+
* 594: waitforsignal
|
|
7
|
+
* 595: sleep
|
|
8
|
+
* 596, 597, 598: fatal
|
|
9
|
+
* 599: retry
|
|
5
10
|
*/
|
|
6
11
|
|
|
7
12
|
//todo: getChildWorkflowYAML (includes key, so flow will cleanup)
|
|
@@ -8,7 +8,6 @@ import { ActivityConfig, ProxyType, WorkflowOptions } from "../../types/durable"
|
|
|
8
8
|
import { JobOutput, JobState } from '../../types';
|
|
9
9
|
import { ACTIVITY_PUBLISHES_TOPIC, ACTIVITY_SUBSCRIBES_TOPIC, SLEEP_SUBSCRIBES_TOPIC, WFS_SUBSCRIBES_TOPIC } from './factory';
|
|
10
10
|
import { DurableIncompleteSignalError, DurableSleepError, DurableWaitForSignalError } from '../../modules/errors';
|
|
11
|
-
import { stringify } from 'querystring';
|
|
12
11
|
|
|
13
12
|
/*
|
|
14
13
|
`proxyActivities` returns a wrapped instance of the
|
|
@@ -52,18 +51,32 @@ export class WorkflowService {
|
|
|
52
51
|
const workflowId = store.get('workflowId');
|
|
53
52
|
const workflowTrace = store.get('workflowTrace');
|
|
54
53
|
const workflowSpan = store.get('workflowSpan');
|
|
54
|
+
const COUNTER = store.get('counter');
|
|
55
|
+
const execIndex = COUNTER.counter = COUNTER.counter + 1;
|
|
56
|
+
const childJobId = `${workflowId}-$${options.workflowName}-${execIndex}`;
|
|
55
57
|
|
|
56
58
|
const client = new Client({
|
|
57
59
|
connection: await Connection.connect(WorkerService.connection),
|
|
58
60
|
});
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
61
|
+
|
|
62
|
+
let handle = await client.workflow.getHandle(
|
|
63
|
+
options.taskQueue,
|
|
64
|
+
options.workflowName,
|
|
65
|
+
childJobId
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
try {
|
|
69
|
+
return await handle.result() as T;
|
|
70
|
+
} catch (error) {
|
|
71
|
+
handle = await client.workflow.start({
|
|
72
|
+
...options,
|
|
73
|
+
workflowId: childJobId,
|
|
74
|
+
workflowTrace,
|
|
75
|
+
workflowSpan,
|
|
76
|
+
});
|
|
77
|
+
const result = await handle.result();
|
|
78
|
+
return result as T;
|
|
79
|
+
}
|
|
67
80
|
}
|
|
68
81
|
|
|
69
82
|
static proxyActivities<ACT>(options?: ActivityConfig): ProxyType<ACT> {
|
|
@@ -172,7 +185,7 @@ export class WorkflowService {
|
|
|
172
185
|
const trc = store.get('workflowTrace');
|
|
173
186
|
const spn = store.get('workflowSpan');
|
|
174
187
|
const activityTopic = `${workflowTopic}-activity`;
|
|
175
|
-
const activityJobId = `${workflowId}
|
|
188
|
+
const activityJobId = `${workflowId}-$${activityName}-${execIndex}`;
|
|
176
189
|
|
|
177
190
|
let activityState: JobOutput
|
|
178
191
|
try {
|
package/services/store/index.ts
CHANGED
|
@@ -452,6 +452,9 @@ abstract class StoreService<T, U extends AbstractRedisClient> {
|
|
|
452
452
|
async getStatus(jobId: string, appId: string): Promise<number> {
|
|
453
453
|
const jobKey = this.mintKey(KeyType.JOB_STATE, { appId, jobId });
|
|
454
454
|
const status = await this.redisClient[this.commands.hget](jobKey, ':');
|
|
455
|
+
if (status === null) {
|
|
456
|
+
throw new Error(`Job ${jobId} not found`);
|
|
457
|
+
}
|
|
455
458
|
return Number(status);
|
|
456
459
|
}
|
|
457
460
|
|