@hotmeshio/hotmesh 0.1.14 → 0.1.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.
Files changed (134) hide show
  1. package/README.md +623 -209
  2. package/build/index.d.ts +14 -3
  3. package/build/index.js +17 -4
  4. package/build/modules/enums.d.ts +12 -12
  5. package/build/modules/enums.js +15 -25
  6. package/build/modules/errors.d.ts +16 -16
  7. package/build/modules/errors.js +28 -28
  8. package/build/modules/key.d.ts +0 -37
  9. package/build/modules/key.js +4 -45
  10. package/build/modules/utils.d.ts +7 -15
  11. package/build/modules/utils.js +21 -44
  12. package/build/package.json +18 -15
  13. package/build/services/activities/activity.d.ts +0 -31
  14. package/build/services/activities/activity.js +1 -50
  15. package/build/services/activities/await.js +0 -4
  16. package/build/services/activities/cycle.d.ts +0 -7
  17. package/build/services/activities/cycle.js +1 -16
  18. package/build/services/activities/hook.d.ts +0 -6
  19. package/build/services/activities/hook.js +2 -12
  20. package/build/services/activities/interrupt.js +0 -8
  21. package/build/services/activities/signal.d.ts +0 -6
  22. package/build/services/activities/signal.js +0 -15
  23. package/build/services/activities/trigger.d.ts +4 -5
  24. package/build/services/activities/trigger.js +22 -16
  25. package/build/services/activities/worker.js +0 -4
  26. package/build/services/collator/index.d.ts +0 -70
  27. package/build/services/collator/index.js +1 -91
  28. package/build/services/compiler/deployer.js +6 -38
  29. package/build/services/compiler/index.d.ts +0 -15
  30. package/build/services/compiler/index.js +0 -20
  31. package/build/services/compiler/validator.d.ts +0 -3
  32. package/build/services/compiler/validator.js +0 -25
  33. package/build/services/connector/clients/ioredis.js +0 -2
  34. package/build/services/connector/clients/redis.js +0 -2
  35. package/build/services/connector/index.js +0 -2
  36. package/build/services/engine/index.d.ts +1 -10
  37. package/build/services/engine/index.js +1 -48
  38. package/build/services/exporter/index.d.ts +0 -27
  39. package/build/services/exporter/index.js +0 -33
  40. package/build/services/hotmesh/index.d.ts +8 -4
  41. package/build/services/hotmesh/index.js +20 -19
  42. package/build/services/logger/index.js +0 -2
  43. package/build/services/mapper/index.d.ts +0 -14
  44. package/build/services/mapper/index.js +0 -14
  45. package/build/services/meshcall/index.d.ts +21 -0
  46. package/build/services/meshcall/index.js +202 -0
  47. package/build/services/meshcall/schemas/factory.d.ts +2 -0
  48. package/build/services/meshcall/schemas/factory.js +179 -0
  49. package/build/services/meshdata/index.d.ts +75 -0
  50. package/build/services/meshdata/index.js +541 -0
  51. package/build/services/meshflow/client.d.ts +18 -0
  52. package/build/services/{durable → meshflow}/client.js +9 -40
  53. package/build/services/{durable → meshflow}/connection.d.ts +2 -1
  54. package/build/services/{durable → meshflow}/connection.js +1 -0
  55. package/build/services/meshflow/exporter.d.ts +29 -0
  56. package/build/services/{durable → meshflow}/exporter.js +0 -29
  57. package/build/services/meshflow/handle.d.ts +22 -0
  58. package/build/services/{durable → meshflow}/handle.js +0 -46
  59. package/build/services/meshflow/index.d.ts +17 -0
  60. package/build/services/meshflow/index.js +23 -0
  61. package/build/services/meshflow/schemas/factory.d.ts +4 -0
  62. package/build/services/{durable → meshflow}/schemas/factory.js +3 -31
  63. package/build/services/meshflow/search.d.ts +23 -0
  64. package/build/services/{durable → meshflow}/search.js +0 -99
  65. package/build/services/{durable → meshflow}/worker.d.ts +3 -2
  66. package/build/services/{durable → meshflow}/worker.js +23 -39
  67. package/build/services/meshflow/workflow.d.ts +27 -0
  68. package/build/services/{durable → meshflow}/workflow.js +27 -169
  69. package/build/services/pipe/functions/date.d.ts +0 -7
  70. package/build/services/pipe/functions/date.js +0 -7
  71. package/build/services/pipe/functions/math.js +0 -2
  72. package/build/services/pipe/index.d.ts +0 -15
  73. package/build/services/pipe/index.js +2 -23
  74. package/build/services/quorum/index.d.ts +1 -7
  75. package/build/services/quorum/index.js +0 -21
  76. package/build/services/reporter/index.d.ts +0 -5
  77. package/build/services/reporter/index.js +0 -9
  78. package/build/services/router/index.d.ts +0 -9
  79. package/build/services/router/index.js +2 -30
  80. package/build/services/serializer/index.js +6 -23
  81. package/build/services/store/cache.d.ts +0 -19
  82. package/build/services/store/cache.js +0 -19
  83. package/build/services/store/clients/ioredis.d.ts +0 -6
  84. package/build/services/store/clients/ioredis.js +0 -7
  85. package/build/services/store/clients/redis.d.ts +0 -6
  86. package/build/services/store/clients/redis.js +0 -6
  87. package/build/services/store/index.d.ts +0 -55
  88. package/build/services/store/index.js +14 -87
  89. package/build/services/stream/clients/ioredis.js +1 -4
  90. package/build/services/task/index.d.ts +0 -9
  91. package/build/services/task/index.js +0 -31
  92. package/build/services/telemetry/index.d.ts +0 -7
  93. package/build/services/telemetry/index.js +1 -13
  94. package/build/services/worker/index.d.ts +1 -4
  95. package/build/services/worker/index.js +0 -6
  96. package/build/types/activity.d.ts +0 -81
  97. package/build/types/error.d.ts +5 -5
  98. package/build/types/exporter.d.ts +1 -14
  99. package/build/types/hotmesh.d.ts +4 -12
  100. package/build/types/hotmesh.js +0 -3
  101. package/build/types/index.d.ts +5 -3
  102. package/build/types/index.js +1 -1
  103. package/build/types/job.d.ts +1 -95
  104. package/build/types/meshcall.d.ts +54 -0
  105. package/build/types/meshdata.d.ts +59 -0
  106. package/build/types/meshdata.js +2 -0
  107. package/build/types/meshflow.d.ts +202 -0
  108. package/build/types/meshflow.js +2 -0
  109. package/build/types/pipe.d.ts +0 -65
  110. package/build/types/quorum.d.ts +0 -12
  111. package/build/types/redis.d.ts +0 -6
  112. package/build/types/stream.d.ts +0 -59
  113. package/build/types/stream.js +0 -4
  114. package/index.ts +22 -3
  115. package/package.json +18 -15
  116. package/typedoc.json +38 -0
  117. package/types/error.ts +5 -5
  118. package/types/exporter.ts +1 -1
  119. package/types/hotmesh.ts +3 -2
  120. package/types/index.ts +25 -7
  121. package/types/job.ts +19 -1
  122. package/types/meshcall.ts +123 -0
  123. package/types/meshdata.ts +273 -0
  124. package/types/{durable.ts → meshflow.ts} +33 -9
  125. package/build/services/durable/client.d.ts +0 -49
  126. package/build/services/durable/exporter.d.ts +0 -51
  127. package/build/services/durable/handle.d.ts +0 -58
  128. package/build/services/durable/index.d.ts +0 -19
  129. package/build/services/durable/index.js +0 -25
  130. package/build/services/durable/schemas/factory.d.ts +0 -33
  131. package/build/services/durable/search.d.ts +0 -120
  132. package/build/services/durable/workflow.d.ts +0 -143
  133. package/build/types/durable.d.ts +0 -467
  134. /package/build/types/{durable.js → meshcall.js} +0 -0
@@ -3,42 +3,15 @@ import { StoreService } from '../store';
3
3
  import { DependencyExport, ExportOptions, JobActionExport, JobExport } from '../../types/exporter';
4
4
  import { RedisClient, RedisMulti } from '../../types/redis';
5
5
  import { StringStringType, Symbols } from '../../types/serializer';
6
- /**
7
- * Downloads job data from Redis (hscan, hmget, hgetall)
8
- * Expands process data and includes dependency list
9
- */
10
6
  declare class ExporterService {
11
7
  appId: string;
12
8
  logger: ILogger;
13
9
  store: StoreService<RedisClient, RedisMulti>;
14
10
  symbols: Promise<Symbols> | Symbols;
15
11
  constructor(appId: string, store: StoreService<RedisClient, RedisMulti>, logger: ILogger);
16
- /**
17
- * Convert the job hash and dependency list into a JobExport object.
18
- * This object contains various facets that describe the interaction
19
- * in terms relevant to narrative storytelling.
20
- */
21
12
  export(jobId: string, options?: ExportOptions): Promise<JobExport>;
22
- /**
23
- * Inflates the key from Redis, 3-character symbol
24
- * into a human-readable JSON path, reflecting the
25
- * tree-like structure of the unidimensional Hash
26
- */
27
13
  inflateKey(key: string): string;
28
- /**
29
- * Inflates the job data from Redis into a JobExport object
30
- * @param jobHash - the job data from Redis
31
- * @param dependencyList - the list of dependencies for the job
32
- * @returns - the inflated job data
33
- */
34
14
  inflate(jobHash: StringStringType, dependencyList: string[]): JobExport;
35
- /**
36
- * Inflates the dependency data from Redis into a JobExport object by
37
- * organizing the dimensional isolate in sch a way asto interleave
38
- * into a story
39
- * @param data - the dependency data from Redis
40
- * @returns - the organized dependency data
41
- */
42
15
  inflateDependencyData(data: string[], actions: JobActionExport): DependencyExport[];
43
16
  }
44
17
  export { ExporterService };
@@ -4,21 +4,12 @@ exports.ExporterService = void 0;
4
4
  const key_1 = require("../../modules/key");
5
5
  const utils_1 = require("../../modules/utils");
6
6
  const serializer_1 = require("../serializer");
7
- /**
8
- * Downloads job data from Redis (hscan, hmget, hgetall)
9
- * Expands process data and includes dependency list
10
- */
11
7
  class ExporterService {
12
8
  constructor(appId, store, logger) {
13
9
  this.appId = appId;
14
10
  this.logger = logger;
15
11
  this.store = store;
16
12
  }
17
- /**
18
- * Convert the job hash and dependency list into a JobExport object.
19
- * This object contains various facets that describe the interaction
20
- * in terms relevant to narrative storytelling.
21
- */
22
13
  async export(jobId, options = {}) {
23
14
  if (!this.symbols) {
24
15
  this.symbols = this.store.getAllSymbols();
@@ -29,22 +20,10 @@ class ExporterService {
29
20
  const jobExport = this.inflate(jobData, depData);
30
21
  return jobExport;
31
22
  }
32
- /**
33
- * Inflates the key from Redis, 3-character symbol
34
- * into a human-readable JSON path, reflecting the
35
- * tree-like structure of the unidimensional Hash
36
- */
37
23
  inflateKey(key) {
38
24
  return key in this.symbols ? this.symbols[key] : key;
39
25
  }
40
- /**
41
- * Inflates the job data from Redis into a JobExport object
42
- * @param jobHash - the job data from Redis
43
- * @param dependencyList - the list of dependencies for the job
44
- * @returns - the inflated job data
45
- */
46
26
  inflate(jobHash, dependencyList) {
47
- //the list of actions taken in the workflow and hook functions
48
27
  const actions = {
49
28
  hooks: {},
50
29
  main: {
@@ -58,7 +37,6 @@ class ExporterService {
58
37
  Object.entries(jobHash).forEach(([key, value]) => {
59
38
  const match = key.match(regex);
60
39
  if (match) {
61
- //activity process state
62
40
  const [_, letters, numbers] = match;
63
41
  const path = this.inflateKey(letters);
64
42
  const dimensions = `${numbers.replace(/,/g, '/')}`;
@@ -66,7 +44,6 @@ class ExporterService {
66
44
  process[`${dimensions}/${path}`] = resolved;
67
45
  }
68
46
  else if (key.length === 3) {
69
- //job state
70
47
  process[this.inflateKey(key)] = serializer_1.SerializerService.fromString(value);
71
48
  }
72
49
  });
@@ -76,13 +53,6 @@ class ExporterService {
76
53
  status: jobHash[':'],
77
54
  };
78
55
  }
79
- /**
80
- * Inflates the dependency data from Redis into a JobExport object by
81
- * organizing the dimensional isolate in sch a way asto interleave
82
- * into a story
83
- * @param data - the dependency data from Redis
84
- * @returns - the organized dependency data
85
- */
86
56
  inflateDependencyData(data, actions) {
87
57
  const hookReg = /([0-9,]+)-(\d+)$/;
88
58
  const flowReg = /-(\d+)$/;
@@ -94,7 +64,6 @@ class ExporterService {
94
64
  let type;
95
65
  let dimensionKey = '';
96
66
  if (match) {
97
- //hook-originating dependency
98
67
  const [_, dimension, counter] = match;
99
68
  dimensionKey = dimension.split(',').join('/');
100
69
  prefix = `${dimensionKey}[${counter}]`;
@@ -103,13 +72,11 @@ class ExporterService {
103
72
  else {
104
73
  const match = jobId.match(flowReg);
105
74
  if (match) {
106
- //main workflow-originating dependency
107
75
  const [_, counter] = match;
108
76
  prefix = `[${counter}]`;
109
77
  type = 'flow';
110
78
  }
111
79
  else {
112
- //'other' types like signal cleanup
113
80
  prefix = '/';
114
81
  type = 'other';
115
82
  }
@@ -5,11 +5,11 @@ import { WorkerService } from '../worker';
5
5
  import { JobState, JobData, JobOutput, JobStatus, JobInterruptOptions, ExtensionType } from '../../types/job';
6
6
  import { HotMeshConfig, HotMeshManifest } from '../../types/hotmesh';
7
7
  import { JobExport } from '../../types/exporter';
8
- import { JobMessageCallback, QuorumProfile, ThrottleOptions } from '../../types/quorum';
8
+ import { JobMessageCallback, QuorumMessage, QuorumMessageCallback, QuorumProfile, ThrottleOptions } from '../../types/quorum';
9
9
  import { StringAnyType, StringStringType } from '../../types/serializer';
10
10
  import { JobStatsInput, GetStatsOptions, IdsResponse, StatsResponse } from '../../types/stats';
11
11
  import { StreamCode, StreamData, StreamDataResponse, StreamStatus } from '../../types/stream';
12
- declare class HotMeshService {
12
+ declare class HotMesh {
13
13
  namespace: string;
14
14
  appId: string;
15
15
  guid: string;
@@ -20,10 +20,11 @@ declare class HotMeshService {
20
20
  static disconnecting: boolean;
21
21
  verifyAndSetNamespace(namespace?: string): void;
22
22
  verifyAndSetAppId(appId: string): void;
23
- static init(config: HotMeshConfig): Promise<HotMeshService>;
23
+ static init(config: HotMeshConfig): Promise<HotMesh>;
24
24
  static guid(): string;
25
25
  initEngine(config: HotMeshConfig, logger: ILogger): Promise<void>;
26
26
  initQuorum(config: HotMeshConfig, engine: EngineService, logger: ILogger): Promise<void>;
27
+ constructor();
27
28
  doWork(config: HotMeshConfig, logger: ILogger): Promise<void>;
28
29
  pub(topic: string, data?: JobData, context?: JobState, extended?: ExtensionType): Promise<string>;
29
30
  sub(topic: string, callback: JobMessageCallback): Promise<void>;
@@ -34,6 +35,9 @@ declare class HotMeshService {
34
35
  add(streamData: StreamData | StreamDataResponse): Promise<string>;
35
36
  rollCall(delay?: number): Promise<QuorumProfile[]>;
36
37
  throttle(options: ThrottleOptions): Promise<boolean>;
38
+ pubQuorum(quorumMessage: QuorumMessage): Promise<boolean>;
39
+ subQuorum(callback: QuorumMessageCallback): Promise<void>;
40
+ unsubQuorum(callback: QuorumMessageCallback): Promise<void>;
37
41
  plan(path: string): Promise<HotMeshManifest>;
38
42
  deploy(pathOrYAML: string): Promise<HotMeshManifest>;
39
43
  activate(version: string, delay?: number): Promise<boolean>;
@@ -53,4 +57,4 @@ declare class HotMeshService {
53
57
  stop(): void;
54
58
  compress(terms: string[]): Promise<boolean>;
55
59
  }
56
- export { HotMeshService };
60
+ export { HotMesh };
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.HotMeshService = void 0;
3
+ exports.HotMesh = void 0;
4
4
  const key_1 = require("../../modules/key");
5
5
  const utils_1 = require("../../modules/utils");
6
6
  const redis_1 = require("../connector/clients/redis");
@@ -12,12 +12,7 @@ const quorum_1 = require("../quorum");
12
12
  const router_1 = require("../router");
13
13
  const worker_1 = require("../worker");
14
14
  const enums_1 = require("../../modules/enums");
15
- class HotMeshService {
16
- constructor() {
17
- this.engine = null;
18
- this.quorum = null;
19
- this.workers = [];
20
- }
15
+ class HotMesh {
21
16
  verifyAndSetNamespace(namespace) {
22
17
  if (!namespace) {
23
18
  this.namespace = key_1.HMNS;
@@ -41,8 +36,8 @@ class HotMeshService {
41
36
  }
42
37
  }
43
38
  static async init(config) {
44
- const instance = new HotMeshService();
45
- instance.guid = (0, utils_1.guid)();
39
+ const instance = new HotMesh();
40
+ instance.guid = config.guid ?? (0, utils_1.guid)();
46
41
  instance.verifyAndSetNamespace(config.namespace);
47
42
  instance.verifyAndSetAppId(config.appId);
48
43
  instance.logger = new logger_1.LoggerService(config.appId, instance.guid, config.name || '', config.logLevel);
@@ -65,10 +60,14 @@ class HotMeshService {
65
60
  this.quorum = await quorum_1.QuorumService.init(this.namespace, this.appId, this.guid, config, engine, logger);
66
61
  }
67
62
  }
63
+ constructor() {
64
+ this.engine = null;
65
+ this.quorum = null;
66
+ this.workers = [];
67
+ }
68
68
  async doWork(config, logger) {
69
69
  this.workers = await worker_1.WorkerService.init(this.namespace, this.appId, this.guid, config, logger);
70
70
  }
71
- // ************* PUB/SUB METHODS *************
72
71
  async pub(topic, data = {}, context, extended) {
73
72
  return await this.engine?.pub(topic, data, context, extended);
74
73
  }
@@ -90,7 +89,6 @@ class HotMeshService {
90
89
  async add(streamData) {
91
90
  return (await this.engine.add(streamData));
92
91
  }
93
- // ************* QUORUM METHODS *************
94
92
  async rollCall(delay) {
95
93
  return await this.quorum?.rollCall(delay);
96
94
  }
@@ -118,7 +116,15 @@ class HotMeshService {
118
116
  await this.engine.store.setThrottleRate(throttleMessage);
119
117
  return await this.quorum?.pub(throttleMessage);
120
118
  }
121
- // ************* COMPILER METHODS *************
119
+ async pubQuorum(quorumMessage) {
120
+ return await this.quorum?.pub(quorumMessage);
121
+ }
122
+ async subQuorum(callback) {
123
+ return await this.quorum?.sub(callback);
124
+ }
125
+ async unsubQuorum(callback) {
126
+ return await this.quorum?.unsub(callback);
127
+ }
122
128
  async plan(path) {
123
129
  return await this.engine?.plan(path);
124
130
  }
@@ -126,10 +132,8 @@ class HotMeshService {
126
132
  return await this.engine?.deploy(pathOrYAML);
127
133
  }
128
134
  async activate(version, delay) {
129
- //activation is a quorum operation
130
135
  return await this.quorum?.activate(version, delay);
131
136
  }
132
- // ************* REPORTER METHODS *************
133
137
  async export(jobId) {
134
138
  return await this.engine?.export(jobId);
135
139
  }
@@ -154,15 +158,12 @@ class HotMeshService {
154
158
  async resolveQuery(topic, query) {
155
159
  return await this.engine?.resolveQuery(topic, query);
156
160
  }
157
- // ****************** `INTERRUPT` ACTIVE JOBS *****************
158
161
  async interrupt(topic, jobId, options = {}) {
159
162
  return await this.engine?.interrupt(topic, jobId, options);
160
163
  }
161
- // ****************** `SCRUB` CLEAN COMPLETED JOBS *****************
162
164
  async scrub(jobId) {
163
165
  await this.engine?.scrub(jobId);
164
166
  }
165
- // ****** `HOOK` ACTIVITY RE-ENTRY POINT ******
166
167
  async hook(topic, data, status, code) {
167
168
  return await this.engine?.hook(topic, data, status, code);
168
169
  }
@@ -188,5 +189,5 @@ class HotMeshService {
188
189
  return await this.engine?.compress(terms);
189
190
  }
190
191
  }
191
- exports.HotMeshService = HotMeshService;
192
- HotMeshService.disconnecting = false;
192
+ exports.HotMesh = HotMesh;
193
+ HotMesh.disconnecting = false;
@@ -15,14 +15,12 @@ class LoggerService {
15
15
  level: this.logLevel,
16
16
  format: winston_1.format.combine(winston_1.format.colorize(), winston_1.format.timestamp(), winston_1.format.printf((info) => {
17
17
  const { timestamp, level, message } = info;
18
- // Extract the object from the `info` object's `Symbol(splat)` field
19
18
  const symbols = Object.getOwnPropertySymbols(info);
20
19
  const splatSymbol = symbols.find((symbol) => symbol.toString() === 'Symbol(splat)');
21
20
  let splatData = {};
22
21
  if (splatSymbol) {
23
22
  splatData = info[splatSymbol][0] || {};
24
23
  }
25
- // Pass it to the `tagify` method
26
24
  const tags = this.tagify(splatData);
27
25
  return `${timestamp} [${level}] [${this.name || this.appId}:${this.instanceId}] ${message} ${tags}`;
28
26
  })),
@@ -7,22 +7,8 @@ declare class MapperService {
7
7
  constructor(rules: Record<string, unknown>, data: JobState);
8
8
  mapRules(): Record<string, unknown>;
9
9
  private traverseRules;
10
- /**
11
- * resolves a pipe expression of the form: { @pipe: [["{data.foo.bar}", 2, false, "hello world"]] }
12
- * @param value
13
- * @returns
14
- */
15
10
  private pipe;
16
- /**
17
- * resolves a mapping expression in the form: "{data.foo.bar}" or 2 or false or "hello world"
18
- * @param value
19
- * @returns
20
- */
21
11
  private resolve;
22
- /**
23
- * Evaluates a transition rule against the current job state and incoming Stream message
24
- * to determine which (if any) transition should be taken.
25
- */
26
12
  static evaluate(transitionRule: TransitionRule | boolean, context: JobState, code: StreamCode): boolean;
27
13
  }
28
14
  export { MapperService };
@@ -27,28 +27,14 @@ class MapperService {
27
27
  return this.resolve(rules);
28
28
  }
29
29
  }
30
- /**
31
- * resolves a pipe expression of the form: { @pipe: [["{data.foo.bar}", 2, false, "hello world"]] }
32
- * @param value
33
- * @returns
34
- */
35
30
  pipe(value) {
36
31
  const pipe = new pipe_1.Pipe(value, this.data);
37
32
  return pipe.process();
38
33
  }
39
- /**
40
- * resolves a mapping expression in the form: "{data.foo.bar}" or 2 or false or "hello world"
41
- * @param value
42
- * @returns
43
- */
44
34
  resolve(value) {
45
35
  const pipe = new pipe_1.Pipe([[value]], this.data);
46
36
  return pipe.process();
47
37
  }
48
- /**
49
- * Evaluates a transition rule against the current job state and incoming Stream message
50
- * to determine which (if any) transition should be taken.
51
- */
52
38
  static evaluate(transitionRule, context, code) {
53
39
  if (typeof transitionRule === 'boolean') {
54
40
  return transitionRule;
@@ -0,0 +1,21 @@
1
+ import { HotMesh } from "../hotmesh";
2
+ import { MeshCallConnectParams, MeshCallCronParams, MeshCallExecParams, MeshCallFlushParams, MeshCallInterruptParams } from "../../types/meshcall";
3
+ import { RedisConfig } from "../../types";
4
+ declare class MeshCall {
5
+ static workers: Map<string, HotMesh | Promise<HotMesh>>;
6
+ static engines: Map<string, HotMesh | Promise<HotMesh>>;
7
+ static connections: Map<string, any>;
8
+ constructor();
9
+ static findFirstMatching(workers: Map<string, (HotMesh | Promise<HotMesh>)>, namespace: string, config: RedisConfig): Promise<HotMesh | void>;
10
+ static getHotMeshClient: (namespace: string, connection: RedisConfig) => Promise<HotMesh>;
11
+ static verifyWorkflowActive(hotMesh: HotMesh, appId?: string, count?: number): Promise<boolean>;
12
+ static activateWorkflow(hotMesh: HotMesh, appId?: string, version?: string): Promise<void>;
13
+ static getInstance(namespace: string, redis: RedisConfig): Promise<HotMesh>;
14
+ static connect(params: MeshCallConnectParams): Promise<HotMesh>;
15
+ static exec<U>(params: MeshCallExecParams): Promise<U>;
16
+ static flush(params: MeshCallFlushParams): Promise<void>;
17
+ static cron(params: MeshCallCronParams): Promise<boolean>;
18
+ static interrupt(params: MeshCallInterruptParams): Promise<void>;
19
+ static shutdown(): Promise<void>;
20
+ }
21
+ export { MeshCall };
@@ -0,0 +1,202 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ var _a;
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.MeshCall = void 0;
8
+ const ms_1 = __importDefault(require("ms"));
9
+ const hotmesh_1 = require("../hotmesh");
10
+ const enums_1 = require("../../modules/enums");
11
+ const utils_1 = require("../../modules/utils");
12
+ const key_1 = require("../../modules/key");
13
+ const factory_1 = require("./schemas/factory");
14
+ class MeshCall {
15
+ constructor() { }
16
+ static async findFirstMatching(workers, namespace = key_1.HMNS, config) {
17
+ for (const [id, hotMeshInstance] of workers) {
18
+ if ((await hotMeshInstance).namespace === namespace) {
19
+ if (id.startsWith((0, utils_1.hashOptions)(config.options))) {
20
+ return hotMeshInstance;
21
+ }
22
+ }
23
+ }
24
+ }
25
+ static async verifyWorkflowActive(hotMesh, appId = key_1.HMNS, count = 0) {
26
+ const app = await hotMesh.engine.store.getApp(appId);
27
+ const appVersion = app?.version;
28
+ if (isNaN(appVersion)) {
29
+ if (count > 10) {
30
+ throw new Error('Workflow failed to activate');
31
+ }
32
+ await (0, utils_1.sleepFor)(enums_1.HMSH_QUORUM_DELAY_MS * 2);
33
+ return await MeshCall.verifyWorkflowActive(hotMesh, appId, count + 1);
34
+ }
35
+ return true;
36
+ }
37
+ static async activateWorkflow(hotMesh, appId = key_1.HMNS, version = '1') {
38
+ const app = await hotMesh.engine.store.getApp(appId);
39
+ const appVersion = app?.version;
40
+ if (appVersion === version && !app.active) {
41
+ try {
42
+ await hotMesh.activate(version);
43
+ }
44
+ catch (error) {
45
+ hotMesh.engine.logger.error('durable-client-activate-err', { error });
46
+ throw error;
47
+ }
48
+ }
49
+ else if (isNaN(Number(appVersion)) || appVersion < version) {
50
+ try {
51
+ await hotMesh.deploy((0, factory_1.getWorkflowYAML)(appId));
52
+ await hotMesh.activate(version);
53
+ }
54
+ catch (error) {
55
+ hotMesh.engine.logger.error('durable-client-deploy-activate-err', {
56
+ ...error,
57
+ });
58
+ throw error;
59
+ }
60
+ }
61
+ }
62
+ static async getInstance(namespace, redis) {
63
+ let hotMeshInstance = await MeshCall.findFirstMatching(MeshCall.workers, namespace, redis);
64
+ if (!hotMeshInstance) {
65
+ hotMeshInstance = await MeshCall.findFirstMatching(MeshCall.engines, namespace, redis);
66
+ if (!hotMeshInstance) {
67
+ hotMeshInstance = await MeshCall.getHotMeshClient(namespace, redis);
68
+ }
69
+ }
70
+ return hotMeshInstance;
71
+ }
72
+ static async connect(params) {
73
+ const targetNamespace = params.namespace ?? key_1.HMNS;
74
+ const optionsHash = (0, utils_1.hashOptions)(params.redis?.options);
75
+ const targetTopic = `${optionsHash}.${targetNamespace}.${params.topic}`;
76
+ const hotMeshWorker = await hotmesh_1.HotMesh.init({
77
+ guid: params.guid,
78
+ logLevel: params.logLevel ?? enums_1.HMSH_LOGLEVEL,
79
+ appId: params.namespace ?? key_1.HMNS,
80
+ engine: { redis: params.redis },
81
+ workers: [
82
+ {
83
+ topic: params.topic,
84
+ redis: params.redis,
85
+ callback: async function (input) {
86
+ const response = await params.callback.apply(this, input.data.args);
87
+ return {
88
+ metadata: { ...input.metadata },
89
+ data: { response },
90
+ };
91
+ },
92
+ }
93
+ ],
94
+ });
95
+ MeshCall.workers.set(targetTopic, hotMeshWorker);
96
+ await MeshCall.activateWorkflow(hotMeshWorker, targetNamespace);
97
+ return hotMeshWorker;
98
+ }
99
+ static async exec(params) {
100
+ const TOPIC = `${params.namespace ?? key_1.HMNS}.call`;
101
+ const hotMeshInstance = await MeshCall.getInstance(params.namespace, params.redis);
102
+ let id = params.options?.id;
103
+ if (id) {
104
+ if (params.options?.flush) {
105
+ await hotMeshInstance.scrub(id);
106
+ }
107
+ else if (params.options?.ttl) {
108
+ try {
109
+ const cached = await hotMeshInstance.getState(TOPIC, id);
110
+ if (cached) {
111
+ return cached.data.response;
112
+ }
113
+ }
114
+ catch (error) {
115
+ }
116
+ }
117
+ }
118
+ else {
119
+ id = hotmesh_1.HotMesh.guid();
120
+ }
121
+ let expire = 1;
122
+ if (params.options?.ttl) {
123
+ expire = (0, ms_1.default)(params.options.ttl) / 1000;
124
+ }
125
+ const jobOutput = await hotMeshInstance.pubsub(TOPIC, { id, expire, topic: params.topic, args: params.args }, null, 30000);
126
+ return jobOutput?.data?.response;
127
+ }
128
+ static async flush(params) {
129
+ const hotMeshInstance = await MeshCall.getInstance(params.namespace, params.redis);
130
+ await hotMeshInstance.scrub(params.id);
131
+ }
132
+ static async cron(params) {
133
+ try {
134
+ await MeshCall.connect({
135
+ logLevel: params.logLevel,
136
+ guid: params.guid,
137
+ topic: params.topic,
138
+ redis: params.redis,
139
+ callback: params.callback,
140
+ namespace: params.namespace,
141
+ });
142
+ const TOPIC = `${params.namespace ?? key_1.HMNS}.cron`;
143
+ const hotMeshInstance = await MeshCall.getInstance(params.namespace, params.redis);
144
+ await hotMeshInstance.pub(TOPIC, {
145
+ id: params.options.id,
146
+ topic: params.topic,
147
+ args: params.args,
148
+ interval: params.options.interval,
149
+ maxCycles: params.options.maxCycles ?? 1000000000,
150
+ maxDuration: params.options.maxDuration,
151
+ });
152
+ return true;
153
+ }
154
+ catch (error) {
155
+ if (error.message.includes(`Duplicate job: ${params.options.id}`)) {
156
+ return false;
157
+ }
158
+ throw error;
159
+ }
160
+ }
161
+ static async interrupt(params) {
162
+ const hotMeshInstance = await MeshCall.getInstance(params.namespace, params.redis);
163
+ await hotMeshInstance.interrupt(`${params.namespace ?? key_1.HMNS}.cron`, params.options.id, { 'throw': false, expire: 60 });
164
+ }
165
+ static async shutdown() {
166
+ for (const [_, hotMeshInstance] of MeshCall.workers) {
167
+ (await hotMeshInstance).stop();
168
+ }
169
+ for (const [_, hotMeshInstance] of MeshCall.engines) {
170
+ (await hotMeshInstance).stop();
171
+ }
172
+ await hotmesh_1.HotMesh.stop();
173
+ }
174
+ }
175
+ exports.MeshCall = MeshCall;
176
+ _a = MeshCall;
177
+ MeshCall.workers = new Map();
178
+ MeshCall.engines = new Map();
179
+ MeshCall.connections = new Map();
180
+ MeshCall.getHotMeshClient = async (namespace, connection) => {
181
+ const optionsHash = (0, utils_1.hashOptions)(connection.options);
182
+ const targetNS = namespace ?? key_1.HMNS;
183
+ const connectionNS = `${optionsHash}.${targetNS}`;
184
+ if (MeshCall.engines.has(connectionNS)) {
185
+ const hotMeshClient = await MeshCall.engines.get(connectionNS);
186
+ await _a.verifyWorkflowActive(hotMeshClient, targetNS);
187
+ return hotMeshClient;
188
+ }
189
+ const hotMeshClient = hotmesh_1.HotMesh.init({
190
+ appId: targetNS,
191
+ logLevel: enums_1.HMSH_LOGLEVEL,
192
+ engine: {
193
+ redis: {
194
+ class: connection.class,
195
+ options: connection.options,
196
+ },
197
+ },
198
+ });
199
+ MeshCall.engines.set(connectionNS, hotMeshClient);
200
+ await _a.activateWorkflow(await hotMeshClient, targetNS);
201
+ return hotMeshClient;
202
+ };
@@ -0,0 +1,2 @@
1
+ export declare const VERSION = "1";
2
+ export declare const getWorkflowYAML: (appId?: string, version?: string) => string;