@hotmeshio/hotmesh 0.0.55 → 0.0.56
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/build/modules/enums.js +1 -10
- package/build/modules/key.d.ts +0 -38
- package/build/modules/key.js +4 -46
- package/build/modules/utils.d.ts +0 -8
- package/build/modules/utils.js +0 -14
- package/build/package.json +11 -4
- package/build/services/activities/activity.d.ts +0 -28
- package/build/services/activities/activity.js +1 -46
- package/build/services/activities/await.js +0 -4
- package/build/services/activities/cycle.d.ts +0 -7
- package/build/services/activities/cycle.js +1 -16
- package/build/services/activities/hook.d.ts +0 -6
- package/build/services/activities/hook.js +2 -12
- package/build/services/activities/interrupt.js +0 -8
- package/build/services/activities/signal.d.ts +0 -6
- package/build/services/activities/signal.js +0 -15
- package/build/services/activities/trigger.d.ts +0 -4
- package/build/services/activities/trigger.js +1 -7
- package/build/services/activities/worker.js +0 -4
- package/build/services/collator/index.d.ts +0 -70
- package/build/services/collator/index.js +1 -91
- package/build/services/compiler/deployer.js +6 -38
- package/build/services/compiler/index.d.ts +0 -15
- package/build/services/compiler/index.js +0 -20
- package/build/services/compiler/validator.d.ts +0 -3
- package/build/services/compiler/validator.js +0 -25
- package/build/services/connector/clients/ioredis.d.ts +2 -2
- package/build/services/connector/clients/ioredis.js +0 -2
- package/build/services/connector/clients/redis.d.ts +4 -4
- package/build/services/connector/clients/redis.js +1 -3
- package/build/services/connector/index.d.ts +1 -1
- package/build/services/connector/index.js +0 -2
- package/build/services/durable/client.d.ts +1 -26
- package/build/services/durable/client.js +0 -56
- package/build/services/durable/exporter.d.ts +0 -22
- package/build/services/durable/exporter.js +1 -30
- package/build/services/durable/handle.d.ts +0 -36
- package/build/services/durable/handle.js +0 -46
- package/build/services/durable/index.d.ts +0 -4
- package/build/services/durable/index.js +0 -4
- package/build/services/durable/schemas/factory.d.ts +0 -29
- package/build/services/durable/schemas/factory.js +0 -29
- package/build/services/durable/search.d.ts +1 -36
- package/build/services/durable/search.js +57 -56
- package/build/services/durable/worker.js +2 -22
- package/build/services/durable/workflow.d.ts +0 -114
- package/build/services/durable/workflow.js +1 -141
- package/build/services/engine/index.d.ts +1 -6
- package/build/services/engine/index.js +1 -43
- package/build/services/exporter/index.d.ts +0 -27
- package/build/services/exporter/index.js +0 -33
- package/build/services/hotmesh/index.d.ts +2 -2
- package/build/services/hotmesh/index.js +1 -9
- package/build/services/logger/index.js +0 -2
- package/build/services/mapper/index.d.ts +0 -14
- package/build/services/mapper/index.js +0 -14
- package/build/services/pipe/functions/date.d.ts +0 -7
- package/build/services/pipe/functions/date.js +0 -7
- package/build/services/pipe/functions/math.js +0 -2
- package/build/services/pipe/index.d.ts +0 -15
- package/build/services/pipe/index.js +2 -23
- package/build/services/quorum/index.d.ts +0 -7
- package/build/services/quorum/index.js +0 -21
- package/build/services/reporter/index.d.ts +0 -5
- package/build/services/reporter/index.js +0 -9
- package/build/services/router/index.d.ts +0 -9
- package/build/services/router/index.js +2 -38
- package/build/services/serializer/index.js +7 -26
- package/build/services/store/cache.d.ts +0 -18
- package/build/services/store/cache.js +0 -18
- package/build/services/store/clients/ioredis.d.ts +1 -1
- package/build/services/store/clients/ioredis.js +0 -1
- package/build/services/store/clients/redis.d.ts +1 -1
- package/build/services/store/index.d.ts +0 -55
- package/build/services/store/index.js +5 -81
- package/build/services/stream/clients/ioredis.d.ts +1 -1
- package/build/services/stream/clients/ioredis.js +1 -4
- package/build/services/stream/clients/redis.d.ts +1 -1
- package/build/services/sub/clients/ioredis.d.ts +1 -1
- package/build/services/sub/clients/redis.d.ts +1 -1
- package/build/services/task/index.d.ts +0 -9
- package/build/services/task/index.js +0 -31
- package/build/services/telemetry/index.d.ts +0 -7
- package/build/services/telemetry/index.js +1 -13
- package/build/services/worker/index.d.ts +0 -4
- package/build/services/worker/index.js +2 -6
- package/build/types/activity.d.ts +0 -81
- package/build/types/durable.d.ts +25 -177
- package/build/types/exporter.d.ts +0 -13
- package/build/types/hotmesh.d.ts +4 -16
- package/build/types/hotmesh.js +0 -3
- package/build/types/index.d.ts +4 -6
- package/build/types/index.js +4 -3
- package/build/types/job.d.ts +1 -86
- package/build/types/pipe.d.ts +0 -65
- package/build/types/quorum.d.ts +15 -10
- package/build/types/redis.d.ts +225 -7
- package/build/types/redis.js +9 -0
- package/build/types/stream.d.ts +0 -58
- package/build/types/stream.js +0 -4
- package/package.json +11 -4
- package/types/durable.ts +121 -3
- package/types/hotmesh.ts +3 -6
- package/types/index.ts +23 -10
- package/types/job.ts +1 -1
- package/types/quorum.ts +22 -0
- package/types/redis.ts +267 -18
- package/build/types/ioredisclient.d.ts +0 -5
- package/build/types/ioredisclient.js +0 -5
- package/build/types/redisclient.d.ts +0 -26
- package/build/types/redisclient.js +0 -2
- package/modules/enums.ts +0 -62
- package/modules/errors.ts +0 -280
- package/modules/key.ts +0 -101
- package/modules/storage.ts +0 -3
- package/modules/utils.ts +0 -242
- package/services/activities/activity.ts +0 -589
- package/services/activities/await.ts +0 -113
- package/services/activities/cycle.ts +0 -115
- package/services/activities/hook.ts +0 -197
- package/services/activities/index.ts +0 -19
- package/services/activities/interrupt.ts +0 -172
- package/services/activities/signal.ts +0 -148
- package/services/activities/trigger.ts +0 -295
- package/services/activities/worker.ts +0 -107
- package/services/collator/README.md +0 -102
- package/services/collator/index.ts +0 -291
- package/services/compiler/deployer.ts +0 -504
- package/services/compiler/index.ts +0 -98
- package/services/compiler/validator.ts +0 -158
- package/services/connector/clients/ioredis.ts +0 -57
- package/services/connector/clients/redis.ts +0 -72
- package/services/connector/index.ts +0 -42
- package/services/durable/client.ts +0 -266
- package/services/durable/connection.ts +0 -10
- package/services/durable/exporter.ts +0 -232
- package/services/durable/handle.ts +0 -160
- package/services/durable/index.ts +0 -27
- package/services/durable/schemas/factory.ts +0 -2358
- package/services/durable/search.ts +0 -196
- package/services/durable/worker.ts +0 -401
- package/services/durable/workflow.ts +0 -557
- package/services/engine/index.ts +0 -761
- package/services/exporter/index.ts +0 -146
- package/services/hotmesh/index.ts +0 -237
- package/services/logger/index.ts +0 -79
- package/services/mapper/index.ts +0 -89
- package/services/pipe/functions/array.ts +0 -78
- package/services/pipe/functions/bitwise.ts +0 -27
- package/services/pipe/functions/conditional.ts +0 -35
- package/services/pipe/functions/date.ts +0 -220
- package/services/pipe/functions/index.ts +0 -27
- package/services/pipe/functions/json.ts +0 -11
- package/services/pipe/functions/logical.ts +0 -11
- package/services/pipe/functions/math.ts +0 -217
- package/services/pipe/functions/number.ts +0 -75
- package/services/pipe/functions/object.ts +0 -98
- package/services/pipe/functions/string.ts +0 -86
- package/services/pipe/functions/symbol.ts +0 -39
- package/services/pipe/functions/unary.ts +0 -19
- package/services/pipe/index.ts +0 -216
- package/services/quorum/index.ts +0 -319
- package/services/reporter/index.ts +0 -387
- package/services/router/index.ts +0 -426
- package/services/serializer/README.md +0 -10
- package/services/serializer/index.ts +0 -285
- package/services/store/cache.ts +0 -172
- package/services/store/clients/ioredis.ts +0 -145
- package/services/store/clients/redis.ts +0 -191
- package/services/store/index.ts +0 -1091
- package/services/stream/clients/ioredis.ts +0 -157
- package/services/stream/clients/redis.ts +0 -158
- package/services/stream/index.ts +0 -58
- package/services/sub/clients/ioredis.ts +0 -83
- package/services/sub/clients/redis.ts +0 -74
- package/services/sub/index.ts +0 -25
- package/services/task/index.ts +0 -250
- package/services/telemetry/index.ts +0 -273
- package/services/worker/index.ts +0 -248
- package/types/ioredisclient.ts +0 -10
- package/types/redisclient.ts +0 -30
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
GenerationalError,
|
|
3
|
-
GetStateError,
|
|
4
|
-
InactiveJobError } from '../../modules/errors';
|
|
5
|
-
import { guid } from '../../modules/utils';
|
|
6
|
-
import { CollatorService } from '../collator';
|
|
7
|
-
import { EngineService } from '../engine';
|
|
8
|
-
import { Activity } from './activity';
|
|
9
|
-
import {
|
|
10
|
-
ActivityData,
|
|
11
|
-
ActivityMetadata,
|
|
12
|
-
ActivityType,
|
|
13
|
-
CycleActivity } from '../../types/activity';
|
|
14
|
-
import { JobState } from '../../types/job';
|
|
15
|
-
import { MultiResponseFlags, RedisMulti } from '../../types/redis';
|
|
16
|
-
import { StreamData } from '../../types/stream';
|
|
17
|
-
import { TelemetryService } from '../telemetry';
|
|
18
|
-
|
|
19
|
-
class Cycle extends Activity {
|
|
20
|
-
config: CycleActivity;
|
|
21
|
-
|
|
22
|
-
constructor(
|
|
23
|
-
config: ActivityType,
|
|
24
|
-
data: ActivityData,
|
|
25
|
-
metadata: ActivityMetadata,
|
|
26
|
-
hook: ActivityData | null,
|
|
27
|
-
engine: EngineService,
|
|
28
|
-
context?: JobState) {
|
|
29
|
-
super(config, data, metadata, hook, engine, context);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
//******** LEG 1 ENTRY ********//
|
|
34
|
-
async process(): Promise<string> {
|
|
35
|
-
this.logger.debug('cycle-process', { jid: this.context.metadata.jid, gid: this.context.metadata.gid, aid: this.metadata.aid });
|
|
36
|
-
let telemetry: TelemetryService;
|
|
37
|
-
try {
|
|
38
|
-
await this.verifyEntry();
|
|
39
|
-
|
|
40
|
-
telemetry = new TelemetryService(this.engine.appId, this.config, this.metadata, this.context);
|
|
41
|
-
telemetry.startActivitySpan(this.leg);
|
|
42
|
-
this.mapInputData();
|
|
43
|
-
|
|
44
|
-
//set state/status
|
|
45
|
-
let multi = this.store.getMulti();
|
|
46
|
-
await this.setState(multi);
|
|
47
|
-
await this.setStatus(0, multi); //leg 1 never changes job status
|
|
48
|
-
const multiResponse = await multi.exec() as MultiResponseFlags;
|
|
49
|
-
telemetry.mapActivityAttributes();
|
|
50
|
-
const jobStatus = this.resolveStatus(multiResponse);
|
|
51
|
-
|
|
52
|
-
//cycle the target ancestor
|
|
53
|
-
multi = this.store.getMulti();
|
|
54
|
-
const messageId = await this.cycleAncestorActivity(multi);
|
|
55
|
-
telemetry.setActivityAttributes({
|
|
56
|
-
'app.activity.mid': messageId,
|
|
57
|
-
'app.job.jss': jobStatus
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
//exit early (`Cycle` activities only execute Leg 1)
|
|
61
|
-
await CollatorService.notarizeEarlyExit(this, multi);
|
|
62
|
-
await multi.exec() as MultiResponseFlags;
|
|
63
|
-
|
|
64
|
-
return this.context.metadata.aid;
|
|
65
|
-
} catch (error) {
|
|
66
|
-
if (error instanceof InactiveJobError) {
|
|
67
|
-
this.logger.error('cycle-inactive-job-error', { ...error });
|
|
68
|
-
return;
|
|
69
|
-
} else if (error instanceof GenerationalError) {
|
|
70
|
-
this.logger.info('process-event-generational-job-error', { ...error });
|
|
71
|
-
return;
|
|
72
|
-
} else if (error instanceof GetStateError) {
|
|
73
|
-
this.logger.error('cycle-get-state-error', { ...error });
|
|
74
|
-
return;
|
|
75
|
-
} else {
|
|
76
|
-
this.logger.error('cycle-process-error', { ...error });
|
|
77
|
-
}
|
|
78
|
-
telemetry.setActivityError(error.message);
|
|
79
|
-
throw error;
|
|
80
|
-
} finally {
|
|
81
|
-
telemetry?.endActivitySpan();
|
|
82
|
-
this.logger.debug('cycle-process-end', { jid: this.context.metadata.jid, gid: this.context.metadata.gid, aid: this.metadata.aid });
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Trigger the target ancestor to execute in a cycle,
|
|
88
|
-
* without violating the constraints of the DAG. Immutable
|
|
89
|
-
* `individual activity state` will execute in a new dimensional
|
|
90
|
-
* thread while `shared job state` can change. This
|
|
91
|
-
* pattern allows for retries without violating the DAG.
|
|
92
|
-
*/
|
|
93
|
-
async cycleAncestorActivity(multi: RedisMulti): Promise<string> {
|
|
94
|
-
//Cycle activity L1 is a standin for the target ancestor L1.
|
|
95
|
-
//Input data mapping (mapInputData) allows for the
|
|
96
|
-
//next dimensonal thread to execute with different
|
|
97
|
-
//input data than the current dimensional thread
|
|
98
|
-
this.mapInputData();
|
|
99
|
-
const streamData: StreamData = {
|
|
100
|
-
metadata: {
|
|
101
|
-
guid: guid(),
|
|
102
|
-
jid: this.context.metadata.jid,
|
|
103
|
-
gid: this.context.metadata.gid,
|
|
104
|
-
dad: CollatorService.resolveReentryDimension(this),
|
|
105
|
-
aid: this.config.ancestor,
|
|
106
|
-
spn: this.context['$self'].output.metadata?.l1s,
|
|
107
|
-
trc: this.context.metadata.trc,
|
|
108
|
-
},
|
|
109
|
-
data: this.context.data
|
|
110
|
-
};
|
|
111
|
-
return (await this.engine.router?.publishMessage(null, streamData, multi)) as string;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
export { Cycle };
|
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
GenerationalError,
|
|
3
|
-
GetStateError,
|
|
4
|
-
InactiveJobError } from '../../modules/errors';
|
|
5
|
-
import { Activity } from './activity';
|
|
6
|
-
import { CollatorService } from '../collator';
|
|
7
|
-
import { EngineService } from '../engine';
|
|
8
|
-
import { Pipe } from '../pipe';
|
|
9
|
-
import { TaskService } from '../task';
|
|
10
|
-
import { TelemetryService } from '../telemetry';
|
|
11
|
-
import {
|
|
12
|
-
ActivityData,
|
|
13
|
-
ActivityMetadata,
|
|
14
|
-
ActivityType,
|
|
15
|
-
HookActivity } from '../../types/activity';
|
|
16
|
-
import { HookRule } from '../../types/hook';
|
|
17
|
-
import { JobState, JobStatus } from '../../types/job';
|
|
18
|
-
import {
|
|
19
|
-
MultiResponseFlags,
|
|
20
|
-
RedisMulti } from '../../types/redis';
|
|
21
|
-
import { StringScalarType } from '../../types/serializer';
|
|
22
|
-
import { StreamCode, StreamStatus } from '../../types/stream';
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Supports `signal hook`, `time hook`, and `cycle hook` patterns
|
|
26
|
-
*/
|
|
27
|
-
class Hook extends Activity {
|
|
28
|
-
config: HookActivity;
|
|
29
|
-
|
|
30
|
-
constructor(
|
|
31
|
-
config: ActivityType,
|
|
32
|
-
data: ActivityData,
|
|
33
|
-
metadata: ActivityMetadata,
|
|
34
|
-
hook: ActivityData | null,
|
|
35
|
-
engine: EngineService,
|
|
36
|
-
context?: JobState) {
|
|
37
|
-
super(config, data, metadata, hook, engine, context);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
//******** INITIAL ENTRY POINT (A) ********//
|
|
41
|
-
async process(): Promise<string> {
|
|
42
|
-
this.logger.debug('hook-process', {
|
|
43
|
-
jid: this.context.metadata.jid,
|
|
44
|
-
gid: this.context.metadata.gid,
|
|
45
|
-
aid: this.metadata.aid,
|
|
46
|
-
});
|
|
47
|
-
let telemetry: TelemetryService;
|
|
48
|
-
|
|
49
|
-
try {
|
|
50
|
-
await this.verifyEntry();
|
|
51
|
-
|
|
52
|
-
telemetry = new TelemetryService(this.engine.appId, this.config, this.metadata, this.context);
|
|
53
|
-
telemetry.startActivitySpan(this.leg);
|
|
54
|
-
|
|
55
|
-
if (this.doesHook()) {
|
|
56
|
-
//sleep and wait to awaken upon a signal
|
|
57
|
-
await this.doHook(telemetry);
|
|
58
|
-
} else {
|
|
59
|
-
//end the activity and transition to its children
|
|
60
|
-
await this.doPassThrough(telemetry);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
return this.context.metadata.aid;
|
|
64
|
-
} catch (error) {
|
|
65
|
-
if (error instanceof InactiveJobError) {
|
|
66
|
-
this.logger.error('hook-inactive-job-error', { ...error });
|
|
67
|
-
return;
|
|
68
|
-
} else if (error instanceof GenerationalError) {
|
|
69
|
-
this.logger.info('process-event-generational-job-error', { ...error });
|
|
70
|
-
return;
|
|
71
|
-
} else if (error instanceof GetStateError) {
|
|
72
|
-
this.logger.error('hook-get-state-error', { ...error });
|
|
73
|
-
return;
|
|
74
|
-
} else {
|
|
75
|
-
this.logger.error('hook-process-error', { ...error });
|
|
76
|
-
}
|
|
77
|
-
telemetry.setActivityError(error.message);
|
|
78
|
-
throw error;
|
|
79
|
-
} finally {
|
|
80
|
-
telemetry?.endActivitySpan();
|
|
81
|
-
this.logger.debug('hook-process-end', { jid: this.context.metadata.jid, gid: this.context.metadata.gid, aid: this.metadata.aid });
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* does this activity use a time-hook or web-hook
|
|
87
|
-
*/
|
|
88
|
-
doesHook(): boolean {
|
|
89
|
-
if (this.config.sleep) {
|
|
90
|
-
const duration = Pipe.resolve(
|
|
91
|
-
this.config.sleep,
|
|
92
|
-
this.context,
|
|
93
|
-
);
|
|
94
|
-
return !isNaN(duration) && Number(duration) > 0
|
|
95
|
-
}
|
|
96
|
-
return !!this.config.hook?.topic;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
async doHook(telemetry: TelemetryService) {
|
|
100
|
-
const multi = this.store.getMulti();
|
|
101
|
-
await this.registerHook(multi);
|
|
102
|
-
this.mapOutputData();
|
|
103
|
-
this.mapJobData();
|
|
104
|
-
await this.setState(multi);
|
|
105
|
-
await CollatorService.authorizeReentry(this, multi);
|
|
106
|
-
|
|
107
|
-
await this.setStatus(0, multi);
|
|
108
|
-
await multi.exec();
|
|
109
|
-
telemetry.mapActivityAttributes();
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
async doPassThrough(telemetry: TelemetryService) {
|
|
113
|
-
const multi = this.store.getMulti();
|
|
114
|
-
let multiResponse: MultiResponseFlags;
|
|
115
|
-
|
|
116
|
-
this.adjacencyList = await this.filterAdjacent();
|
|
117
|
-
this.mapOutputData();
|
|
118
|
-
this.mapJobData();
|
|
119
|
-
await this.setState(multi);
|
|
120
|
-
await CollatorService.notarizeEarlyCompletion(this, multi);
|
|
121
|
-
|
|
122
|
-
await this.setStatus(this.adjacencyList.length - 1, multi);
|
|
123
|
-
multiResponse = await multi.exec() as MultiResponseFlags;
|
|
124
|
-
telemetry.mapActivityAttributes();
|
|
125
|
-
const jobStatus = this.resolveStatus(multiResponse);
|
|
126
|
-
const attrs: StringScalarType = { 'app.job.jss': jobStatus };
|
|
127
|
-
const messageIds = await this.transition(this.adjacencyList, jobStatus);
|
|
128
|
-
if (messageIds.length) {
|
|
129
|
-
attrs['app.activity.mids'] = messageIds.join(',')
|
|
130
|
-
}
|
|
131
|
-
telemetry.setActivityAttributes(attrs);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
async getHookRule(topic: string): Promise<HookRule | undefined> {
|
|
135
|
-
const rules = await this.store.getHookRules();
|
|
136
|
-
return rules?.[topic]?.[0] as HookRule;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
async registerHook(multi?: RedisMulti): Promise<string | void> {
|
|
140
|
-
if (this.config.hook?.topic) {
|
|
141
|
-
return await this.engine.taskService.registerWebHook(
|
|
142
|
-
this.config.hook.topic,
|
|
143
|
-
this.context,
|
|
144
|
-
this.resolveDad(),
|
|
145
|
-
multi
|
|
146
|
-
);
|
|
147
|
-
} else if (this.config.sleep) {
|
|
148
|
-
const duration = Pipe.resolve(
|
|
149
|
-
this.config.sleep,
|
|
150
|
-
this.context,
|
|
151
|
-
);
|
|
152
|
-
await this.engine.taskService.registerTimeHook(
|
|
153
|
-
this.context.metadata.jid,
|
|
154
|
-
this.context.metadata.gid,
|
|
155
|
-
`${this.metadata.aid}${this.metadata.dad || ''}`,
|
|
156
|
-
'sleep',
|
|
157
|
-
duration,
|
|
158
|
-
this.metadata.dad || '',
|
|
159
|
-
);
|
|
160
|
-
return this.context.metadata.jid;
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
//******** SIGNAL RE-ENTRY POINT ********//
|
|
165
|
-
async processWebHookEvent(status: StreamStatus = StreamStatus.SUCCESS, code: StreamCode = 200): Promise<JobStatus | void> {
|
|
166
|
-
this.logger.debug('hook-process-web-hook-event', {
|
|
167
|
-
topic: this.config.hook.topic,
|
|
168
|
-
aid: this.metadata.aid,
|
|
169
|
-
status,
|
|
170
|
-
code,
|
|
171
|
-
});
|
|
172
|
-
const taskService = new TaskService(this.store, this.logger);
|
|
173
|
-
const data = { ...this.data };
|
|
174
|
-
const signal = await taskService.processWebHookSignal(this.config.hook.topic, data);
|
|
175
|
-
if (signal) {
|
|
176
|
-
const [jobId, _aid, dad, gId] = signal;
|
|
177
|
-
this.context.metadata.jid = jobId;
|
|
178
|
-
this.context.metadata.gid = gId;
|
|
179
|
-
this.context.metadata.dad = dad;
|
|
180
|
-
await this.processEvent(status, code, 'hook');
|
|
181
|
-
if (code === 200) {
|
|
182
|
-
await taskService.deleteWebHookSignal(this.config.hook.topic, data);
|
|
183
|
-
} //else => 202/keep alive
|
|
184
|
-
} //else => already resolved
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
async processTimeHookEvent(jobId: string): Promise<JobStatus | void> {
|
|
188
|
-
this.logger.debug('hook-process-time-hook-event', {
|
|
189
|
-
jid: jobId,
|
|
190
|
-
gid: this.context.metadata.gid,
|
|
191
|
-
aid: this.metadata.aid
|
|
192
|
-
});
|
|
193
|
-
await this.processEvent(StreamStatus.SUCCESS, 200, 'hook');
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
export { Hook };
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { Activity } from './activity';
|
|
2
|
-
import { Await } from './await';
|
|
3
|
-
import { Cycle } from './cycle';
|
|
4
|
-
import { Hook } from './hook';
|
|
5
|
-
import { Interrupt } from './interrupt';
|
|
6
|
-
import { Signal } from './signal';
|
|
7
|
-
import { Trigger } from './trigger';
|
|
8
|
-
import { Worker } from './worker';
|
|
9
|
-
|
|
10
|
-
export default {
|
|
11
|
-
activity: Activity,
|
|
12
|
-
await: Await,
|
|
13
|
-
cycle: Cycle,
|
|
14
|
-
hook: Hook,
|
|
15
|
-
interrupt: Interrupt,
|
|
16
|
-
signal: Signal,
|
|
17
|
-
trigger: Trigger,
|
|
18
|
-
worker: Worker,
|
|
19
|
-
};
|
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
GenerationalError,
|
|
3
|
-
GetStateError,
|
|
4
|
-
InactiveJobError } from '../../modules/errors';
|
|
5
|
-
import { CollatorService } from '../collator';
|
|
6
|
-
import { Activity } from './activity';
|
|
7
|
-
import { EngineService } from '../engine';
|
|
8
|
-
import { Pipe } from '../pipe';
|
|
9
|
-
import { TelemetryService } from '../telemetry';
|
|
10
|
-
import {
|
|
11
|
-
ActivityData,
|
|
12
|
-
ActivityMetadata,
|
|
13
|
-
ActivityType,
|
|
14
|
-
InterruptActivity } from '../../types/activity';
|
|
15
|
-
import { JobInterruptOptions, JobState } from '../../types/job';
|
|
16
|
-
import { MultiResponseFlags } from '../../types/redis';
|
|
17
|
-
|
|
18
|
-
class Interrupt extends Activity {
|
|
19
|
-
config: InterruptActivity;
|
|
20
|
-
|
|
21
|
-
constructor(
|
|
22
|
-
config: ActivityType,
|
|
23
|
-
data: ActivityData,
|
|
24
|
-
metadata: ActivityMetadata,
|
|
25
|
-
hook: ActivityData | null,
|
|
26
|
-
engine: EngineService,
|
|
27
|
-
context?: JobState
|
|
28
|
-
) {
|
|
29
|
-
super(config, data, metadata, hook, engine, context);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
//******** LEG 1 ENTRY ********//
|
|
34
|
-
async process(): Promise<string> {
|
|
35
|
-
this.logger.debug('interrupt-process', { jid: this.context.metadata.jid, gid: this.context.metadata.gid, aid: this.metadata.aid });
|
|
36
|
-
let telemetry: TelemetryService;
|
|
37
|
-
try {
|
|
38
|
-
await this.verifyEntry();
|
|
39
|
-
|
|
40
|
-
telemetry = new TelemetryService(this.engine.appId, this.config, this.metadata, this.context);
|
|
41
|
-
telemetry.startActivitySpan(this.leg);
|
|
42
|
-
|
|
43
|
-
if (this.isInterruptingSelf()) {
|
|
44
|
-
await this.interruptSelf(telemetry);
|
|
45
|
-
} else {
|
|
46
|
-
await this.interruptAnother(telemetry);
|
|
47
|
-
}
|
|
48
|
-
} catch (error) {
|
|
49
|
-
if (error instanceof InactiveJobError) {
|
|
50
|
-
this.logger.error('interrupt-inactive-job-error', { ...error });
|
|
51
|
-
return;
|
|
52
|
-
} else if (error instanceof GenerationalError) {
|
|
53
|
-
this.logger.info('process-event-generational-job-error', { ...error });
|
|
54
|
-
return;
|
|
55
|
-
} else if (error instanceof GetStateError) {
|
|
56
|
-
this.logger.error('interrupt-get-state-error', { ...error });
|
|
57
|
-
return;
|
|
58
|
-
} else {
|
|
59
|
-
this.logger.error('interrupt-process-error', { ...error });
|
|
60
|
-
}
|
|
61
|
-
telemetry.setActivityError(error.message);
|
|
62
|
-
throw error;
|
|
63
|
-
} finally {
|
|
64
|
-
telemetry?.endActivitySpan();
|
|
65
|
-
this.logger.debug('interrupt-process-end', { jid: this.context.metadata.jid, gid: this.context.metadata.gid, aid: this.metadata.aid });
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
async interruptSelf(telemetry: TelemetryService): Promise<string> {
|
|
70
|
-
// Apply final updates to THIS job's state
|
|
71
|
-
if (this.config.job?.maps) {
|
|
72
|
-
this.mapJobData();
|
|
73
|
-
await this.setState();
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// Interrupt THIS job
|
|
77
|
-
const messageId = await this.interrupt();
|
|
78
|
-
|
|
79
|
-
// Notarize completion and log
|
|
80
|
-
telemetry.mapActivityAttributes();
|
|
81
|
-
const multi = this.store.getMulti();
|
|
82
|
-
await CollatorService.notarizeEarlyCompletion(this, multi);
|
|
83
|
-
await this.setStatus(-1, multi);
|
|
84
|
-
const multiResponse = await multi.exec() as MultiResponseFlags;
|
|
85
|
-
const jobStatus = this.resolveStatus(multiResponse);
|
|
86
|
-
telemetry.setActivityAttributes({
|
|
87
|
-
'app.activity.mid': messageId,
|
|
88
|
-
'app.job.jss': jobStatus
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
return this.context.metadata.aid;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
async interruptAnother(telemetry: TelemetryService): Promise<string> {
|
|
95
|
-
// Interrupt ANOTHER job
|
|
96
|
-
const messageId = await this.interrupt();
|
|
97
|
-
const attrs = { 'app.activity.mid': messageId };
|
|
98
|
-
|
|
99
|
-
// Apply updates to THIS job's state
|
|
100
|
-
telemetry.mapActivityAttributes();
|
|
101
|
-
this.adjacencyList = await this.filterAdjacent();
|
|
102
|
-
if (this.config.job?.maps || this.config.output?.maps) {
|
|
103
|
-
this.mapOutputData();
|
|
104
|
-
this.mapJobData();
|
|
105
|
-
const multi = this.store.getMulti();
|
|
106
|
-
await this.setState(multi);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// Notarize completion
|
|
110
|
-
const multi = this.store.getMulti();
|
|
111
|
-
await CollatorService.notarizeEarlyCompletion(this, multi);
|
|
112
|
-
await this.setStatus(this.adjacencyList.length - 1, multi);
|
|
113
|
-
const multiResponse = await multi.exec() as MultiResponseFlags;
|
|
114
|
-
const jobStatus = this.resolveStatus(multiResponse);
|
|
115
|
-
attrs['app.job.jss'] = jobStatus;
|
|
116
|
-
|
|
117
|
-
// Transition next generation and log
|
|
118
|
-
const messageIds = await this.transition(this.adjacencyList, jobStatus);
|
|
119
|
-
if (messageIds.length) {
|
|
120
|
-
attrs['app.activity.mids'] = messageIds.join(',');
|
|
121
|
-
}
|
|
122
|
-
telemetry.setActivityAttributes(attrs);
|
|
123
|
-
|
|
124
|
-
return this.context.metadata.aid;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
isInterruptingSelf(): boolean {
|
|
128
|
-
if (!this.config.target) {
|
|
129
|
-
return true;
|
|
130
|
-
}
|
|
131
|
-
const resolvedJob = Pipe.resolve(this.config.target, this.context);
|
|
132
|
-
return resolvedJob == this.context.metadata.jid;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
resolveInterruptOptions(): JobInterruptOptions {
|
|
136
|
-
return {
|
|
137
|
-
reason: this.config.reason !== undefined
|
|
138
|
-
? Pipe.resolve(this.config.reason, this.context)
|
|
139
|
-
: undefined,
|
|
140
|
-
throw: this.config.throw !== undefined
|
|
141
|
-
? Pipe.resolve(this.config.throw, this.context)
|
|
142
|
-
: undefined,
|
|
143
|
-
descend: this.config.descend !== undefined
|
|
144
|
-
? Pipe.resolve(this.config.descend, this.context)
|
|
145
|
-
: undefined,
|
|
146
|
-
code: this.config.code !== undefined
|
|
147
|
-
? Pipe.resolve(this.config.code, this.context)
|
|
148
|
-
: undefined,
|
|
149
|
-
expire: this.config.expire !== undefined
|
|
150
|
-
? Pipe.resolve(this.config.expire, this.context)
|
|
151
|
-
: undefined,
|
|
152
|
-
stack: this.config.stack !== undefined
|
|
153
|
-
? Pipe.resolve(this.config.stack, this.context)
|
|
154
|
-
: undefined,
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
async interrupt(): Promise<string> {
|
|
159
|
-
const options = this.resolveInterruptOptions();
|
|
160
|
-
return await this.engine.interrupt(
|
|
161
|
-
this.config.topic !== undefined
|
|
162
|
-
? Pipe.resolve(this.config.topic, this.context)
|
|
163
|
-
: this.context.metadata.tpc,
|
|
164
|
-
this.config.target !== undefined
|
|
165
|
-
? Pipe.resolve(this.config.target, this.context)
|
|
166
|
-
: this.context.metadata.jid,
|
|
167
|
-
options as JobInterruptOptions,
|
|
168
|
-
);
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
export { Interrupt };
|
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
GenerationalError,
|
|
3
|
-
GetStateError,
|
|
4
|
-
InactiveJobError } from '../../modules/errors';
|
|
5
|
-
import { Activity } from './activity';
|
|
6
|
-
import { CollatorService } from '../collator';
|
|
7
|
-
import { EngineService } from '../engine';
|
|
8
|
-
import { MapperService } from '../mapper';
|
|
9
|
-
import { Pipe } from '../pipe';
|
|
10
|
-
import { TelemetryService } from '../telemetry';
|
|
11
|
-
import {
|
|
12
|
-
ActivityData,
|
|
13
|
-
ActivityMetadata,
|
|
14
|
-
ActivityType,
|
|
15
|
-
SignalActivity } from '../../types/activity';
|
|
16
|
-
import { JobState } from '../../types/job';
|
|
17
|
-
import { MultiResponseFlags } from '../../types/redis';
|
|
18
|
-
import { StringScalarType } from '../../types/serializer';
|
|
19
|
-
import { JobStatsInput } from '../../types/stats';
|
|
20
|
-
|
|
21
|
-
class Signal extends Activity {
|
|
22
|
-
config: SignalActivity;
|
|
23
|
-
|
|
24
|
-
constructor(
|
|
25
|
-
config: ActivityType,
|
|
26
|
-
data: ActivityData,
|
|
27
|
-
metadata: ActivityMetadata,
|
|
28
|
-
hook: ActivityData | null,
|
|
29
|
-
engine: EngineService,
|
|
30
|
-
context?: JobState) {
|
|
31
|
-
super(config, data, metadata, hook, engine, context);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
//******** LEG 1 ENTRY ********//
|
|
36
|
-
async process(): Promise<string> {
|
|
37
|
-
this.logger.debug('signal-process', { jid: this.context.metadata.jid, gid: this.context.metadata.gid, aid: this.metadata.aid });
|
|
38
|
-
let telemetry: TelemetryService;
|
|
39
|
-
try {
|
|
40
|
-
await this.verifyEntry();
|
|
41
|
-
|
|
42
|
-
telemetry = new TelemetryService(this.engine.appId, this.config, this.metadata, this.context);
|
|
43
|
-
telemetry.startActivitySpan(this.leg);
|
|
44
|
-
|
|
45
|
-
//save state and notarize early completion (signals only run leg1)
|
|
46
|
-
const multi = this.store.getMulti();
|
|
47
|
-
this.adjacencyList = await this.filterAdjacent();
|
|
48
|
-
this.mapOutputData();
|
|
49
|
-
this.mapJobData();
|
|
50
|
-
await this.setState(multi);
|
|
51
|
-
await CollatorService.notarizeEarlyCompletion(this, multi);
|
|
52
|
-
await this.setStatus(this.adjacencyList.length - 1, multi);
|
|
53
|
-
const multiResponse = await multi.exec() as MultiResponseFlags;
|
|
54
|
-
|
|
55
|
-
//todo: this should execute BEFORE the status is decremented
|
|
56
|
-
if (this.config.subtype === 'all') {
|
|
57
|
-
await this.hookAll();
|
|
58
|
-
} else {
|
|
59
|
-
await this.hookOne();
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
//transition to adjacent activities
|
|
63
|
-
const jobStatus = this.resolveStatus(multiResponse);
|
|
64
|
-
const attrs: StringScalarType = { 'app.job.jss': jobStatus };
|
|
65
|
-
const messageIds = await this.transition(this.adjacencyList, jobStatus);
|
|
66
|
-
if (messageIds.length) {
|
|
67
|
-
attrs['app.activity.mids'] = messageIds.join(',')
|
|
68
|
-
}
|
|
69
|
-
telemetry.mapActivityAttributes();
|
|
70
|
-
telemetry.setActivityAttributes(attrs);
|
|
71
|
-
|
|
72
|
-
return this.context.metadata.aid;
|
|
73
|
-
} catch (error) {
|
|
74
|
-
if (error instanceof InactiveJobError) {
|
|
75
|
-
this.logger.error('signal-inactive-job-error', { ...error });
|
|
76
|
-
return;
|
|
77
|
-
} else if (error instanceof GenerationalError) {
|
|
78
|
-
this.logger.info('process-event-generational-job-error', { ...error });
|
|
79
|
-
return;
|
|
80
|
-
} else if (error instanceof GetStateError) {
|
|
81
|
-
this.logger.error('signal-get-state-error', { ...error });
|
|
82
|
-
return;
|
|
83
|
-
} else {
|
|
84
|
-
this.logger.error('signal-process-error', { ...error });
|
|
85
|
-
}
|
|
86
|
-
telemetry.setActivityError(error.message);
|
|
87
|
-
throw error;
|
|
88
|
-
} finally {
|
|
89
|
-
telemetry?.endActivitySpan();
|
|
90
|
-
this.logger.debug('signal-process-end', { jid: this.context.metadata.jid, gid: this.context.metadata.gid, aid: this.metadata.aid });
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
mapSignalData(): Record<string, any> {
|
|
95
|
-
if(this.config.signal?.maps) {
|
|
96
|
-
const mapper = new MapperService(this.config.signal.maps, this.context);
|
|
97
|
-
return mapper.mapRules();
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
mapResolverData(): Record<string, any> {
|
|
102
|
-
if(this.config.resolver?.maps) {
|
|
103
|
-
const mapper = new MapperService(this.config.resolver.maps, this.context);
|
|
104
|
-
return mapper.mapRules();
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* The signal activity will hook one
|
|
110
|
-
*/
|
|
111
|
-
async hookOne(): Promise<string> {
|
|
112
|
-
const topic = Pipe.resolve(this.config.topic, this.context);
|
|
113
|
-
const signalInputData = this.mapSignalData();
|
|
114
|
-
const status = Pipe.resolve(this.config.status, this.context);
|
|
115
|
-
const code = Pipe.resolve(this.config.code, this.context);
|
|
116
|
-
return await this.engine.hook(topic, signalInputData, status, code);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* The signal activity will hook all paused jobs that share the same job key.
|
|
121
|
-
*/
|
|
122
|
-
async hookAll(): Promise<string[]> {
|
|
123
|
-
//prep 1) generate `input signal data` (essentially the webhook payload)
|
|
124
|
-
const signalInputData = this.mapSignalData();
|
|
125
|
-
|
|
126
|
-
//prep 2) generate data that resolves the job key (per the YAML config)
|
|
127
|
-
const keyResolverData = this.mapResolverData() as JobStatsInput;
|
|
128
|
-
if (this.config.scrub) {
|
|
129
|
-
//self-clean the indexes upon use if configured
|
|
130
|
-
keyResolverData.scrub = true;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
//prep 3) jobKeys can contain multiple indexes (per the YAML config)
|
|
134
|
-
const key_name = Pipe.resolve(this.config.key_name, this.context);
|
|
135
|
-
const key_value = Pipe.resolve(this.config.key_value, this.context);
|
|
136
|
-
const indexQueryFacets = [`${key_name}:${key_value}`];
|
|
137
|
-
|
|
138
|
-
//execute: `hookAll` will now resume all paused jobs that share the same job key
|
|
139
|
-
return await this.engine.hookAll(
|
|
140
|
-
this.config.topic,
|
|
141
|
-
signalInputData,
|
|
142
|
-
keyResolverData,
|
|
143
|
-
indexQueryFacets
|
|
144
|
-
);
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
export { Signal };
|