@hotmeshio/hotmesh 0.0.35 → 0.0.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -12
- package/build/modules/enums.d.ts +1 -0
- package/build/modules/enums.js +3 -1
- package/build/modules/errors.d.ts +9 -1
- package/build/modules/errors.js +12 -1
- package/build/modules/key.d.ts +20 -19
- package/build/modules/key.js +20 -20
- package/build/package.json +1 -1
- package/build/services/activities/activity.d.ts +10 -0
- package/build/services/activities/activity.js +28 -3
- package/build/services/activities/await.js +10 -9
- package/build/services/activities/cycle.js +10 -9
- package/build/services/activities/hook.d.ts +7 -1
- package/build/services/activities/hook.js +61 -44
- package/build/services/activities/interrupt.js +10 -9
- package/build/services/activities/signal.js +7 -7
- package/build/services/activities/trigger.js +4 -2
- package/build/services/activities/worker.js +9 -8
- package/build/services/durable/meshos.js +2 -2
- package/build/services/durable/worker.js +2 -2
- package/build/services/durable/workflow.js +17 -17
- package/build/services/engine/index.d.ts +5 -7
- package/build/services/engine/index.js +53 -47
- package/build/services/hotmesh/index.js +3 -3
- package/build/services/{signaler/stream.d.ts → router/index.d.ts} +3 -3
- package/build/services/{signaler/stream.js → router/index.js} +6 -6
- package/build/services/serializer/index.js +1 -1
- package/build/services/store/clients/ioredis.js +1 -0
- package/build/services/store/index.d.ts +9 -4
- package/build/services/store/index.js +21 -10
- package/build/services/task/index.d.ts +13 -4
- package/build/services/task/index.js +115 -17
- package/build/services/telemetry/index.js +6 -6
- package/build/services/worker/index.d.ts +3 -3
- package/build/services/worker/index.js +8 -8
- package/build/types/job.d.ts +2 -0
- package/build/types/stream.d.ts +1 -0
- package/modules/enums.ts +4 -1
- package/modules/errors.ts +18 -0
- package/modules/key.ts +21 -20
- package/package.json +1 -1
- package/services/activities/activity.ts +44 -4
- package/services/activities/await.ts +14 -10
- package/services/activities/cycle.ts +14 -10
- package/services/activities/hook.ts +70 -47
- package/services/activities/interrupt.ts +13 -10
- package/services/activities/signal.ts +11 -8
- package/services/activities/trigger.ts +5 -1
- package/services/activities/worker.ts +13 -9
- package/services/durable/meshos.ts +1 -1
- package/services/durable/worker.ts +1 -1
- package/services/durable/workflow.ts +1 -1
- package/services/engine/index.ts +82 -44
- package/services/hotmesh/index.ts +3 -3
- package/services/{signaler/stream.ts → router/index.ts} +5 -5
- package/services/serializer/index.ts +1 -1
- package/services/store/clients/ioredis.ts +1 -0
- package/services/store/index.ts +23 -12
- package/services/task/index.ts +120 -21
- package/services/telemetry/index.ts +6 -6
- package/services/worker/index.ts +7 -7
- package/types/job.ts +2 -0
- package/types/stream.ts +6 -5
- package/build/services/signaler/store.d.ts +0 -15
- package/build/services/signaler/store.js +0 -68
- package/services/signaler/store.ts +0 -76
- /package/build/{services/durable/asyncLocalStorage.d.ts → modules/storage.d.ts} +0 -0
- /package/build/{services/durable/asyncLocalStorage.js → modules/storage.js} +0 -0
- /package/{services/durable/asyncLocalStorage.ts → modules/storage.ts} +0 -0
package/services/worker/index.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { KeyType } from "../../modules/key";
|
|
2
2
|
import { ILogger } from "../logger";
|
|
3
|
-
import {
|
|
3
|
+
import { Router } from "../router";
|
|
4
4
|
import { StoreService } from '../store';
|
|
5
5
|
import { RedisStoreService as RedisStore } from '../store/clients/redis';
|
|
6
6
|
import { IORedisStoreService as IORedisStore } from '../store/clients/ioredis';
|
|
@@ -30,7 +30,7 @@ class WorkerService {
|
|
|
30
30
|
store: StoreService<RedisClient, RedisMulti> | null;
|
|
31
31
|
stream: StreamService<RedisClient, RedisMulti> | null;
|
|
32
32
|
subscribe: SubService<RedisClient, RedisMulti> | null;
|
|
33
|
-
|
|
33
|
+
router: Router | null;
|
|
34
34
|
logger: ILogger;
|
|
35
35
|
reporting = false;
|
|
36
36
|
|
|
@@ -66,10 +66,10 @@ class WorkerService {
|
|
|
66
66
|
await service.subscribe.subscribe(KeyType.QUORUM, service.subscriptionHandler(), appId, service.topic);
|
|
67
67
|
await service.subscribe.subscribe(KeyType.QUORUM, service.subscriptionHandler(), appId, service.guid);
|
|
68
68
|
await service.initStreamChannel(service, worker.stream);
|
|
69
|
-
service.
|
|
69
|
+
service.router = service.initRouter(worker, logger);
|
|
70
70
|
|
|
71
71
|
const key = service.stream.mintKey(KeyType.STREAMS, { appId: service.appId, topic: worker.topic });
|
|
72
|
-
await service.
|
|
72
|
+
await service.router.consumeMessages(
|
|
73
73
|
key,
|
|
74
74
|
'WORKER',
|
|
75
75
|
service.guid,
|
|
@@ -130,8 +130,8 @@ class WorkerService {
|
|
|
130
130
|
);
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
-
|
|
134
|
-
return new
|
|
133
|
+
initRouter(worker: HotMeshWorker, logger: ILogger): Router {
|
|
134
|
+
return new Router(
|
|
135
135
|
{
|
|
136
136
|
namespace: this.namespace,
|
|
137
137
|
appId: this.appId,
|
|
@@ -158,7 +158,7 @@ class WorkerService {
|
|
|
158
158
|
}
|
|
159
159
|
|
|
160
160
|
async throttle(delayInMillis: number) {
|
|
161
|
-
this.
|
|
161
|
+
this.router.setThrottle(delayInMillis);
|
|
162
162
|
}
|
|
163
163
|
}
|
|
164
164
|
|
package/types/job.ts
CHANGED
|
@@ -8,10 +8,12 @@ type ActivityData = {
|
|
|
8
8
|
|
|
9
9
|
type JobMetadata = {
|
|
10
10
|
key?: string; //job_key
|
|
11
|
+
gid: string; //system assigned guid; ensured created/deleted/created jobs are unique
|
|
11
12
|
jid: string; //job_id (jid+dad+aid) is composite key for activity
|
|
12
13
|
dad: string; //dimensional address for the activity (,0,0,1)
|
|
13
14
|
aid: string; //activity_id as in the YAML file
|
|
14
15
|
pj?: string; //parent_job_id (pj+pd+pa) is composite key for parent activity
|
|
16
|
+
pg?: string; //parent_generational_id (system assigned at trigger inception); pg is the parent job's gid (just in case user created/deleted/created a job with same jid)
|
|
15
17
|
pd?: string; //parent_dimensional_address
|
|
16
18
|
pa?: string; //parent_activity_id
|
|
17
19
|
ngn?: string; //engine guid (one time subscriptions)
|
package/types/stream.ts
CHANGED
|
@@ -35,12 +35,13 @@ export interface StreamData {
|
|
|
35
35
|
metadata: {
|
|
36
36
|
guid: string; //every message is minted with a guid to distinguish retries from new messages
|
|
37
37
|
topic?: string;
|
|
38
|
-
jid?: string;
|
|
39
|
-
|
|
38
|
+
jid?: string; //is optional if type is WEBHOOK (system assigned or user assigned)
|
|
39
|
+
gid?: string; //is optional if type is WEBHOOK (system assigned job guid)
|
|
40
|
+
dad?: string; //dimensional address
|
|
40
41
|
aid: string;
|
|
41
|
-
trc?: string;
|
|
42
|
-
spn?: string;
|
|
43
|
-
try?: number;
|
|
42
|
+
trc?: string; //trace id
|
|
43
|
+
spn?: string; //span id
|
|
44
|
+
try?: number; //current try count
|
|
44
45
|
};
|
|
45
46
|
type?: StreamDataType;
|
|
46
47
|
data: Record<string, unknown>;
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { ILogger } from '../logger';
|
|
2
|
-
import { StoreService } from '../store';
|
|
3
|
-
import { HookRule } from '../../types/hook';
|
|
4
|
-
import { JobState } from '../../types/job';
|
|
5
|
-
import { RedisClient, RedisMulti } from '../../types/redis';
|
|
6
|
-
declare class StoreSignaler {
|
|
7
|
-
store: StoreService<RedisClient, RedisMulti>;
|
|
8
|
-
logger: ILogger;
|
|
9
|
-
constructor(store: StoreService<RedisClient, RedisMulti>, logger: ILogger);
|
|
10
|
-
getHookRule(topic: string): Promise<HookRule | undefined>;
|
|
11
|
-
registerWebHook(topic: string, context: JobState, dad: string, multi?: RedisMulti): Promise<string>;
|
|
12
|
-
processWebHookSignal(topic: string, data: Record<string, unknown>): Promise<[string, string, string] | undefined>;
|
|
13
|
-
deleteWebHookSignal(topic: string, data: Record<string, unknown>): Promise<number>;
|
|
14
|
-
}
|
|
15
|
-
export { StoreSignaler };
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.StoreSignaler = void 0;
|
|
4
|
-
const pipe_1 = require("../pipe");
|
|
5
|
-
class StoreSignaler {
|
|
6
|
-
constructor(store, logger) {
|
|
7
|
-
this.store = store;
|
|
8
|
-
this.logger = logger;
|
|
9
|
-
}
|
|
10
|
-
async getHookRule(topic) {
|
|
11
|
-
const rules = await this.store.getHookRules();
|
|
12
|
-
return rules?.[topic]?.[0];
|
|
13
|
-
}
|
|
14
|
-
async registerWebHook(topic, context, dad, multi) {
|
|
15
|
-
const hookRule = await this.getHookRule(topic);
|
|
16
|
-
if (hookRule) {
|
|
17
|
-
const mapExpression = hookRule.conditions.match[0].expected;
|
|
18
|
-
const resolved = pipe_1.Pipe.resolve(mapExpression, context);
|
|
19
|
-
const jobId = context.metadata.jid;
|
|
20
|
-
const hook = {
|
|
21
|
-
topic,
|
|
22
|
-
resolved,
|
|
23
|
-
//hookSignalId is composed of `<dad>::<jid>`
|
|
24
|
-
jobId: `${dad}::${jobId}`,
|
|
25
|
-
};
|
|
26
|
-
await this.store.setHookSignal(hook, multi);
|
|
27
|
-
return jobId;
|
|
28
|
-
}
|
|
29
|
-
else {
|
|
30
|
-
throw new Error('signaler.registerWebHook:error: hook rule not found');
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
async processWebHookSignal(topic, data) {
|
|
34
|
-
const hookRule = await this.getHookRule(topic);
|
|
35
|
-
if (hookRule) {
|
|
36
|
-
//NOTE: both formats are supported: $self.hook.data OR $hook.data
|
|
37
|
-
const context = { $self: { hook: { data } }, $hook: { data } };
|
|
38
|
-
const mapExpression = hookRule.conditions.match[0].actual;
|
|
39
|
-
const resolved = pipe_1.Pipe.resolve(mapExpression, context);
|
|
40
|
-
const hookSignalId = await this.store.getHookSignal(topic, resolved);
|
|
41
|
-
if (!hookSignalId) {
|
|
42
|
-
//messages can be double-processed; not an issue; return undefined
|
|
43
|
-
//users can also provide a bogus topic; not an issue; return undefined
|
|
44
|
-
return undefined;
|
|
45
|
-
}
|
|
46
|
-
const [dad, jid] = hookSignalId.split('::');
|
|
47
|
-
//return [jid, aid, dad]
|
|
48
|
-
return [jid, hookRule.to, dad];
|
|
49
|
-
}
|
|
50
|
-
else {
|
|
51
|
-
throw new Error('signal-not-found');
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
async deleteWebHookSignal(topic, data) {
|
|
55
|
-
const hookRule = await this.getHookRule(topic);
|
|
56
|
-
if (hookRule) {
|
|
57
|
-
//NOTE: both formats are supported: $self.hook.data OR $hook.data
|
|
58
|
-
const context = { $self: { hook: { data } }, $hook: { data } };
|
|
59
|
-
const mapExpression = hookRule.conditions.match[0].actual;
|
|
60
|
-
const resolved = pipe_1.Pipe.resolve(mapExpression, context);
|
|
61
|
-
return await this.store.deleteHookSignal(topic, resolved);
|
|
62
|
-
}
|
|
63
|
-
else {
|
|
64
|
-
throw new Error('signaler.process:error: hook rule not found');
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
exports.StoreSignaler = StoreSignaler;
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import { ILogger } from '../logger';
|
|
2
|
-
import { StoreService } from '../store';
|
|
3
|
-
import { HookRule, HookSignal } from '../../types/hook';
|
|
4
|
-
import { JobState } from '../../types/job';
|
|
5
|
-
import { RedisClient, RedisMulti } from '../../types/redis';
|
|
6
|
-
import { Pipe } from '../pipe';
|
|
7
|
-
|
|
8
|
-
class StoreSignaler {
|
|
9
|
-
store: StoreService<RedisClient, RedisMulti>;
|
|
10
|
-
logger: ILogger
|
|
11
|
-
|
|
12
|
-
constructor(store: StoreService<RedisClient, RedisMulti>, logger: ILogger) {
|
|
13
|
-
this.store = store;
|
|
14
|
-
this.logger = logger;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
async getHookRule(topic: string): Promise<HookRule | undefined> {
|
|
18
|
-
const rules = await this.store.getHookRules();
|
|
19
|
-
return rules?.[topic]?.[0] as HookRule;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
async registerWebHook(topic: string, context: JobState, dad: string, multi?: RedisMulti): Promise<string> {
|
|
23
|
-
const hookRule = await this.getHookRule(topic);
|
|
24
|
-
if (hookRule) {
|
|
25
|
-
const mapExpression = hookRule.conditions.match[0].expected;
|
|
26
|
-
const resolved = Pipe.resolve(mapExpression, context);
|
|
27
|
-
const jobId = context.metadata.jid;
|
|
28
|
-
const hook: HookSignal = {
|
|
29
|
-
topic,
|
|
30
|
-
resolved,
|
|
31
|
-
//hookSignalId is composed of `<dad>::<jid>`
|
|
32
|
-
jobId: `${dad}::${jobId}`,
|
|
33
|
-
}
|
|
34
|
-
await this.store.setHookSignal(hook, multi);
|
|
35
|
-
return jobId;
|
|
36
|
-
} else {
|
|
37
|
-
throw new Error('signaler.registerWebHook:error: hook rule not found');
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
async processWebHookSignal(topic: string, data: Record<string, unknown>): Promise<[string, string, string] | undefined> {
|
|
42
|
-
const hookRule = await this.getHookRule(topic);
|
|
43
|
-
if (hookRule) {
|
|
44
|
-
//NOTE: both formats are supported: $self.hook.data OR $hook.data
|
|
45
|
-
const context = { $self: { hook: { data }}, $hook: { data }};
|
|
46
|
-
const mapExpression = hookRule.conditions.match[0].actual;
|
|
47
|
-
const resolved = Pipe.resolve(mapExpression, context);
|
|
48
|
-
const hookSignalId = await this.store.getHookSignal(topic, resolved);
|
|
49
|
-
if (!hookSignalId) {
|
|
50
|
-
//messages can be double-processed; not an issue; return undefined
|
|
51
|
-
//users can also provide a bogus topic; not an issue; return undefined
|
|
52
|
-
return undefined;
|
|
53
|
-
}
|
|
54
|
-
const [dad, jid] = hookSignalId.split('::');
|
|
55
|
-
//return [jid, aid, dad]
|
|
56
|
-
return [jid, hookRule.to, dad];
|
|
57
|
-
} else {
|
|
58
|
-
throw new Error('signal-not-found');
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
async deleteWebHookSignal(topic: string, data: Record<string, unknown>): Promise<number> {
|
|
63
|
-
const hookRule = await this.getHookRule(topic);
|
|
64
|
-
if (hookRule) {
|
|
65
|
-
//NOTE: both formats are supported: $self.hook.data OR $hook.data
|
|
66
|
-
const context = { $self: { hook: { data }}, $hook: { data }};
|
|
67
|
-
const mapExpression = hookRule.conditions.match[0].actual;
|
|
68
|
-
const resolved = Pipe.resolve(mapExpression, context);
|
|
69
|
-
return await this.store.deleteHookSignal(topic, resolved);
|
|
70
|
-
} else {
|
|
71
|
-
throw new Error('signaler.process:error: hook rule not found');
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export { StoreSignaler };
|
|
File without changes
|
|
File without changes
|
|
File without changes
|