@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.
Files changed (69) hide show
  1. package/README.md +12 -12
  2. package/build/modules/enums.d.ts +1 -0
  3. package/build/modules/enums.js +3 -1
  4. package/build/modules/errors.d.ts +9 -1
  5. package/build/modules/errors.js +12 -1
  6. package/build/modules/key.d.ts +20 -19
  7. package/build/modules/key.js +20 -20
  8. package/build/package.json +1 -1
  9. package/build/services/activities/activity.d.ts +10 -0
  10. package/build/services/activities/activity.js +28 -3
  11. package/build/services/activities/await.js +10 -9
  12. package/build/services/activities/cycle.js +10 -9
  13. package/build/services/activities/hook.d.ts +7 -1
  14. package/build/services/activities/hook.js +61 -44
  15. package/build/services/activities/interrupt.js +10 -9
  16. package/build/services/activities/signal.js +7 -7
  17. package/build/services/activities/trigger.js +4 -2
  18. package/build/services/activities/worker.js +9 -8
  19. package/build/services/durable/meshos.js +2 -2
  20. package/build/services/durable/worker.js +2 -2
  21. package/build/services/durable/workflow.js +17 -17
  22. package/build/services/engine/index.d.ts +5 -7
  23. package/build/services/engine/index.js +53 -47
  24. package/build/services/hotmesh/index.js +3 -3
  25. package/build/services/{signaler/stream.d.ts → router/index.d.ts} +3 -3
  26. package/build/services/{signaler/stream.js → router/index.js} +6 -6
  27. package/build/services/serializer/index.js +1 -1
  28. package/build/services/store/clients/ioredis.js +1 -0
  29. package/build/services/store/index.d.ts +9 -4
  30. package/build/services/store/index.js +21 -10
  31. package/build/services/task/index.d.ts +13 -4
  32. package/build/services/task/index.js +115 -17
  33. package/build/services/telemetry/index.js +6 -6
  34. package/build/services/worker/index.d.ts +3 -3
  35. package/build/services/worker/index.js +8 -8
  36. package/build/types/job.d.ts +2 -0
  37. package/build/types/stream.d.ts +1 -0
  38. package/modules/enums.ts +4 -1
  39. package/modules/errors.ts +18 -0
  40. package/modules/key.ts +21 -20
  41. package/package.json +1 -1
  42. package/services/activities/activity.ts +44 -4
  43. package/services/activities/await.ts +14 -10
  44. package/services/activities/cycle.ts +14 -10
  45. package/services/activities/hook.ts +70 -47
  46. package/services/activities/interrupt.ts +13 -10
  47. package/services/activities/signal.ts +11 -8
  48. package/services/activities/trigger.ts +5 -1
  49. package/services/activities/worker.ts +13 -9
  50. package/services/durable/meshos.ts +1 -1
  51. package/services/durable/worker.ts +1 -1
  52. package/services/durable/workflow.ts +1 -1
  53. package/services/engine/index.ts +82 -44
  54. package/services/hotmesh/index.ts +3 -3
  55. package/services/{signaler/stream.ts → router/index.ts} +5 -5
  56. package/services/serializer/index.ts +1 -1
  57. package/services/store/clients/ioredis.ts +1 -0
  58. package/services/store/index.ts +23 -12
  59. package/services/task/index.ts +120 -21
  60. package/services/telemetry/index.ts +6 -6
  61. package/services/worker/index.ts +7 -7
  62. package/types/job.ts +2 -0
  63. package/types/stream.ts +6 -5
  64. package/build/services/signaler/store.d.ts +0 -15
  65. package/build/services/signaler/store.js +0 -68
  66. package/services/signaler/store.ts +0 -76
  67. /package/build/{services/durable/asyncLocalStorage.d.ts → modules/storage.d.ts} +0 -0
  68. /package/build/{services/durable/asyncLocalStorage.js → modules/storage.js} +0 -0
  69. /package/{services/durable/asyncLocalStorage.ts → modules/storage.ts} +0 -0
package/README.md CHANGED
@@ -15,12 +15,12 @@ npm install @hotmeshio/hotmesh
15
15
  ## Understanding HotMesh
16
16
  HotMesh inverts the relationship to Redis: those functions that once used Redis as a cache, are instead *cached and governed* by Redis. Consider the following. It's a typical microservices network, with a tangled mess of services and functions. There's important business logic in there (functions *A*, *B* and *C* are critical!), but they're hard to find and access.
17
17
 
18
- <img src="https://github.com/hotmeshio/sdk-typescript/blob/main/docs/img/operational_data_layer.png" alt="A Tangled Microservices Network with 3 functions buried within" style="max-width:100%;width:600px;">
18
+ <img src="https://github.com/hotmeshio/sdk-typescript/tree/main/docs/img/operational_data_layer.png" alt="A Tangled Microservices Network with 3 functions buried within" style="max-width:100%;width:600px;">
19
19
 
20
20
  HotMesh creates an *ad hoc*, Redis-backed network of functions and organizes them into a unified service mesh. *Any service with access to Redis can join in the network, bypassing the legacy clutter.*
21
21
 
22
22
  ## Design
23
- The simplest way to get started is to use the `Durable` module. It's organized using principles similar to Temporal. If you're familiar with their SDK, the setup is similar.
23
+ The simplest way to get started is to use the `Durable` module. It's organized using principles similar to temporal.io. If you're familiar with their SDK, the setup is similar.
24
24
 
25
25
  1. Start by defining **activities**. Activities can be written in any style, using any framework, and can even be legacy functions you've already written. The only requirement is that they return a Promise. *Note how the `saludar` example throws an error 50% of the time. It doesn't matter how unpredictable your functions are, HotMesh will retry as necessary until they succeed.*
26
26
  ```javascript
@@ -285,31 +285,31 @@ const hotMesh = await HotMesh.init({
285
285
  ```
286
286
 
287
287
  ### Observability
288
- Workflows and activities are run according to the rules you define, offering [Graph-Oriented](https://github.com/hotmeshio/sdk-typescript/blob/main/docs/system_lifecycle.md#telemetry) telemetry insights into your legacy function executions.
288
+ Workflows and activities are run according to the rules you define, offering [Graph-Oriented](https://github.com/hotmeshio/sdk-typescript/tree/main/docs/system_lifecycle.md#telemetry) telemetry insights into your legacy function executions.
289
289
 
290
290
  ## FAQ
291
- Refer to the [FAQ](https://github.com/hotmeshio/sdk-typescript/blob/main/docs/faq.md) for terminology, definitions, and an exploration of how HotMesh facilitates orchestration use cases.
291
+ Refer to the [FAQ](https://github.com/hotmeshio/sdk-typescript/tree/main/docs/faq.md) for terminology, definitions, and an exploration of how HotMesh facilitates orchestration use cases.
292
292
 
293
293
  ## Quick Start
294
- Refer to the [Quick Start](https://github.com/hotmeshio/sdk-typescript/blob/main/docs/quickstart.md) for sample flows you can easily copy, paste, and modify to get started.
294
+ Refer to the [Quick Start](https://github.com/hotmeshio/sdk-typescript/tree/main/docs/quickstart.md) for sample flows you can easily copy, paste, and modify to get started.
295
295
 
296
296
  ## Developer Guide
297
- For more details on the complete development process, including information about schemas, APIs, and deployment, consult the [Developer Guide](https://github.com/hotmeshio/sdk-typescript/blob/main/docs/developer_guide.md).
297
+ For more details on the complete development process, including information about schemas, APIs, and deployment, consult the [Developer Guide](https://github.com/hotmeshio/sdk-typescript/tree/main/docs/developer_guide.md).
298
298
 
299
299
  ## Model Driven Development
300
- [Model Driven Development](https://github.com/hotmeshio/sdk-typescript/blob/main/docs/model_driven_development.md) is an established strategy for managing process-oriented tasks. Check out this guide to understand its foundational principles.
300
+ [Model Driven Development](https://github.com/hotmeshio/sdk-typescript/tree/main/docs/model_driven_development.md) is an established strategy for managing process-oriented tasks. Check out this guide to understand its foundational principles.
301
301
 
302
302
  ## Data Mapping
303
- Exchanging data between activities is central to HotMesh. For detailed information on supported functions and the functional mapping syntax (@pipes), see the [Data Mapping Overview](https://github.com/hotmeshio/sdk-typescript/blob/main/docs/data_mapping.md).
303
+ Exchanging data between activities is central to HotMesh. For detailed information on supported functions and the functional mapping syntax (@pipes), see the [Data Mapping Overview](https://github.com/hotmeshio/sdk-typescript/tree/main/docs/data_mapping.md).
304
304
 
305
305
  ## Composition
306
- While the simplest graphs are linear, detailing a consistent sequence of non-cyclical activities, graphs can be layered to represent intricate business scenarios. Some can even be designed to accommodate long-lasting workflows that span months. For more details, check out the [Composable Workflow Guide](https://github.com/hotmeshio/sdk-typescript/blob/main/docs/composable_workflow.md).
306
+ While the simplest graphs are linear, detailing a consistent sequence of non-cyclical activities, graphs can be layered to represent intricate business scenarios. Some can even be designed to accommodate long-lasting workflows that span months. For more details, check out the [Composable Workflow Guide](https://github.com/hotmeshio/sdk-typescript/tree/main/docs/composable_workflow.md).
307
307
 
308
308
  ## Distributed Orchestration
309
- HotMesh is a distributed orchestration engine. Refer to the [Distributed Orchestration Guide](https://github.com/hotmeshio/sdk-typescript/blob/main/docs/distributed_orchestration.md) for a detailed breakdown of the approach.
309
+ HotMesh is a distributed orchestration engine. Refer to the [Distributed Orchestration Guide](https://github.com/hotmeshio/sdk-typescript/tree/main/docs/distributed_orchestration.md) for a detailed breakdown of the approach.
310
310
 
311
311
  ## System Lifecycle
312
- Gain insight into HotMesh's monitoring, exception handling, and alarm configurations via the [System Lifecycle Guide](https://github.com/hotmeshio/sdk-typescript/blob/main/docs/system_lifecycle.md).
312
+ Gain insight into HotMesh's monitoring, exception handling, and alarm configurations via the [System Lifecycle Guide](https://github.com/hotmeshio/sdk-typescript/tree/main/docs/system_lifecycle.md).
313
313
 
314
314
  ## Alpha Release
315
- So what exacty is an [alpha release](https://github.com/hotmeshio/sdk-typescript/blob/main/docs/alpha.md)?
315
+ So what exacty is an [alpha release](https://github.com/hotmeshio/sdk-typescript/tree/main/docs/alpha.md)?
@@ -20,3 +20,4 @@ export declare const BASE_FIDELITY_SECONDS = 15;
20
20
  export declare const TEST_FIDELITY_SECONDS = 5;
21
21
  export declare const FIDELITY_SECONDS: number;
22
22
  export declare const DURABLE_EXPIRE_SECONDS = 1;
23
+ export declare const SCOUT_INTERVAL_SECONDS = 60;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DURABLE_EXPIRE_SECONDS = exports.FIDELITY_SECONDS = exports.TEST_FIDELITY_SECONDS = exports.BASE_FIDELITY_SECONDS = exports.EXPIRE_DURATION = exports.STATUS_MESSAGE_UNKNOWN = exports.STATUS_CODE_UNKNOWN = exports.STATUS_CODE_UNACKED = exports.XPENDING_COUNT = exports.XCLAIM_COUNT = exports.XCLAIM_DELAY_MS = exports.BLOCK_TIME_MS = exports.TEST_BLOCK_DURATION = exports.BLOCK_DURATION = exports.GRADUATED_INTERVAL_MS = exports.MAX_TIMEOUT_MS = exports.MAX_RETRIES = exports.OTT_WAIT_TIME = exports.STATUS_CODE_INTERRUPT = exports.STATUS_CODE_TIMEOUT = exports.STATUS_CODE_PENDING = exports.STATUS_CODE_SUCCESS = void 0;
3
+ exports.SCOUT_INTERVAL_SECONDS = exports.DURABLE_EXPIRE_SECONDS = exports.FIDELITY_SECONDS = exports.TEST_FIDELITY_SECONDS = exports.BASE_FIDELITY_SECONDS = exports.EXPIRE_DURATION = exports.STATUS_MESSAGE_UNKNOWN = exports.STATUS_CODE_UNKNOWN = exports.STATUS_CODE_UNACKED = exports.XPENDING_COUNT = exports.XCLAIM_COUNT = exports.XCLAIM_DELAY_MS = exports.BLOCK_TIME_MS = exports.TEST_BLOCK_DURATION = exports.BLOCK_DURATION = exports.GRADUATED_INTERVAL_MS = exports.MAX_TIMEOUT_MS = exports.MAX_RETRIES = exports.OTT_WAIT_TIME = exports.STATUS_CODE_INTERRUPT = exports.STATUS_CODE_TIMEOUT = exports.STATUS_CODE_PENDING = exports.STATUS_CODE_SUCCESS = void 0;
4
4
  // Engine Constants
5
5
  exports.STATUS_CODE_SUCCESS = 200;
6
6
  exports.STATUS_CODE_PENDING = 202;
@@ -27,3 +27,5 @@ exports.TEST_FIDELITY_SECONDS = 5;
27
27
  exports.FIDELITY_SECONDS = process.env.NODE_ENV === 'test' ? exports.TEST_FIDELITY_SECONDS : exports.BASE_FIDELITY_SECONDS;
28
28
  // DURABLE CONSTANTS
29
29
  exports.DURABLE_EXPIRE_SECONDS = 1;
30
+ // TASK CONSTANTS
31
+ exports.SCOUT_INTERVAL_SECONDS = 60;
@@ -68,6 +68,14 @@ declare class InactiveJobError extends Error {
68
68
  status: number;
69
69
  constructor(jobId: string, status: number, activityId: string);
70
70
  }
71
+ declare class GenerationalError extends Error {
72
+ expected: string;
73
+ actual: string;
74
+ jobId: string;
75
+ activityId: string;
76
+ dimensionalAddress: string;
77
+ constructor(expected: string, actual: string, jobId: string, activityId: string, dimensionalAddress: string);
78
+ }
71
79
  declare class ExecActivityError extends Error {
72
80
  constructor();
73
81
  }
@@ -78,4 +86,4 @@ declare class CollationError extends Error {
78
86
  fault: CollationFaultType;
79
87
  constructor(status: number, leg: ActivityDuplex, stage: CollationStage, fault?: CollationFaultType);
80
88
  }
81
- export { CollationError, DurableFatalError, DurableIncompleteSignalError, DurableMaxedError, DurableRetryError, DurableSleepError, DurableSleepForError, DurableTimeoutError, DurableWaitForSignalError, DuplicateJobError, ExecActivityError, GetStateError, InactiveJobError, MapDataError, RegisterTimeoutError, SetStateError, };
89
+ export { CollationError, DurableFatalError, DurableIncompleteSignalError, DurableMaxedError, DurableRetryError, DurableSleepError, DurableSleepForError, DurableTimeoutError, DurableWaitForSignalError, DuplicateJobError, ExecActivityError, GenerationalError, GetStateError, InactiveJobError, MapDataError, RegisterTimeoutError, SetStateError, };
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SetStateError = exports.RegisterTimeoutError = exports.MapDataError = exports.InactiveJobError = exports.GetStateError = exports.ExecActivityError = exports.DuplicateJobError = exports.DurableWaitForSignalError = exports.DurableTimeoutError = exports.DurableSleepForError = exports.DurableSleepError = exports.DurableRetryError = exports.DurableMaxedError = exports.DurableIncompleteSignalError = exports.DurableFatalError = exports.CollationError = void 0;
3
+ exports.SetStateError = exports.RegisterTimeoutError = exports.MapDataError = exports.InactiveJobError = exports.GetStateError = exports.GenerationalError = exports.ExecActivityError = exports.DuplicateJobError = exports.DurableWaitForSignalError = exports.DurableTimeoutError = exports.DurableSleepForError = exports.DurableSleepError = exports.DurableRetryError = exports.DurableMaxedError = exports.DurableIncompleteSignalError = exports.DurableFatalError = exports.CollationError = void 0;
4
4
  class GetStateError extends Error {
5
5
  constructor(jobId) {
6
6
  super(`${jobId} Not Found`);
@@ -110,6 +110,17 @@ class InactiveJobError extends Error {
110
110
  }
111
111
  }
112
112
  exports.InactiveJobError = InactiveJobError;
113
+ class GenerationalError extends Error {
114
+ constructor(expected, actual, jobId, activityId, dimensionalAddress) {
115
+ super("Generational Error");
116
+ this.expected = expected;
117
+ this.actual = actual;
118
+ this.jobId = jobId;
119
+ this.activityId = activityId;
120
+ this.dimensionalAddress = dimensionalAddress;
121
+ }
122
+ }
123
+ exports.GenerationalError = GenerationalError;
113
124
  class ExecActivityError extends Error {
114
125
  constructor() {
115
126
  super("Error occurred while executing activity");
@@ -27,25 +27,25 @@
27
27
  */
28
28
  declare const HMNS = "hmsh";
29
29
  declare enum KeyType {
30
- APP = 0,
31
- ENGINE_ID = 1,
32
- HOOKS = 2,
33
- JOB_DEPENDENTS = 3,
34
- JOB_STATE = 4,
35
- JOB_STATS_GENERAL = 5,
36
- JOB_STATS_MEDIAN = 6,
37
- JOB_STATS_INDEX = 7,
38
- HOTMESH = 8,
39
- QUORUM = 9,
40
- SCHEMAS = 10,
41
- SIGNALS = 11,
42
- STREAMS = 12,
43
- SUBSCRIPTIONS = 13,
44
- SUBSCRIPTION_PATTERNS = 14,
45
- SYMKEYS = 15,
46
- SYMVALS = 16,
47
- TIME_RANGE = 17,
48
- WORK_ITEMS = 18
30
+ APP = "APP",
31
+ ENGINE_ID = "ENGINE",
32
+ HOOKS = "HOOKS",
33
+ JOB_DEPENDENTS = "JOB_DEPENDENTS",
34
+ JOB_STATE = "JOB_STATE",
35
+ JOB_STATS_GENERAL = "JOB_STATS_GENERAL",
36
+ JOB_STATS_MEDIAN = "JOB_STATS_MEDIAN",
37
+ JOB_STATS_INDEX = "JOB_STATS_INDEX",
38
+ HOTMESH = "HOTMESH",
39
+ QUORUM = "QUORUM",
40
+ SCHEMAS = "SCHEMAS",
41
+ SIGNALS = "SIGNALS",
42
+ STREAMS = "STREAMS",
43
+ SUBSCRIPTIONS = "SUBSCRIPTIONS",
44
+ SUBSCRIPTION_PATTERNS = "SUBSCRIPTION_PATTERNS",
45
+ SYMKEYS = "SYMKEYS",
46
+ SYMVALS = "SYMVALS",
47
+ TIME_RANGE = "TIME_RANGE",
48
+ WORK_ITEMS = "WORK_ITEMS"
49
49
  }
50
50
  type KeyStoreParams = {
51
51
  appId?: string;
@@ -58,6 +58,7 @@ type KeyStoreParams = {
58
58
  facet?: string;
59
59
  topic?: string;
60
60
  timeValue?: number;
61
+ scoutType?: 'signal' | 'time';
61
62
  };
62
63
  declare class KeyService {
63
64
  /**
@@ -34,25 +34,25 @@ exports.HMNS = HMNS;
34
34
  //these are the entity types that are stored in the key/value store
35
35
  var KeyType;
36
36
  (function (KeyType) {
37
- KeyType[KeyType["APP"] = 0] = "APP";
38
- KeyType[KeyType["ENGINE_ID"] = 1] = "ENGINE_ID";
39
- KeyType[KeyType["HOOKS"] = 2] = "HOOKS";
40
- KeyType[KeyType["JOB_DEPENDENTS"] = 3] = "JOB_DEPENDENTS";
41
- KeyType[KeyType["JOB_STATE"] = 4] = "JOB_STATE";
42
- KeyType[KeyType["JOB_STATS_GENERAL"] = 5] = "JOB_STATS_GENERAL";
43
- KeyType[KeyType["JOB_STATS_MEDIAN"] = 6] = "JOB_STATS_MEDIAN";
44
- KeyType[KeyType["JOB_STATS_INDEX"] = 7] = "JOB_STATS_INDEX";
45
- KeyType[KeyType["HOTMESH"] = 8] = "HOTMESH";
46
- KeyType[KeyType["QUORUM"] = 9] = "QUORUM";
47
- KeyType[KeyType["SCHEMAS"] = 10] = "SCHEMAS";
48
- KeyType[KeyType["SIGNALS"] = 11] = "SIGNALS";
49
- KeyType[KeyType["STREAMS"] = 12] = "STREAMS";
50
- KeyType[KeyType["SUBSCRIPTIONS"] = 13] = "SUBSCRIPTIONS";
51
- KeyType[KeyType["SUBSCRIPTION_PATTERNS"] = 14] = "SUBSCRIPTION_PATTERNS";
52
- KeyType[KeyType["SYMKEYS"] = 15] = "SYMKEYS";
53
- KeyType[KeyType["SYMVALS"] = 16] = "SYMVALS";
54
- KeyType[KeyType["TIME_RANGE"] = 17] = "TIME_RANGE";
55
- KeyType[KeyType["WORK_ITEMS"] = 18] = "WORK_ITEMS";
37
+ KeyType["APP"] = "APP";
38
+ KeyType["ENGINE_ID"] = "ENGINE";
39
+ KeyType["HOOKS"] = "HOOKS";
40
+ KeyType["JOB_DEPENDENTS"] = "JOB_DEPENDENTS";
41
+ KeyType["JOB_STATE"] = "JOB_STATE";
42
+ KeyType["JOB_STATS_GENERAL"] = "JOB_STATS_GENERAL";
43
+ KeyType["JOB_STATS_MEDIAN"] = "JOB_STATS_MEDIAN";
44
+ KeyType["JOB_STATS_INDEX"] = "JOB_STATS_INDEX";
45
+ KeyType["HOTMESH"] = "HOTMESH";
46
+ KeyType["QUORUM"] = "QUORUM";
47
+ KeyType["SCHEMAS"] = "SCHEMAS";
48
+ KeyType["SIGNALS"] = "SIGNALS";
49
+ KeyType["STREAMS"] = "STREAMS";
50
+ KeyType["SUBSCRIPTIONS"] = "SUBSCRIPTIONS";
51
+ KeyType["SUBSCRIPTION_PATTERNS"] = "SUBSCRIPTION_PATTERNS";
52
+ KeyType["SYMKEYS"] = "SYMKEYS";
53
+ KeyType["SYMVALS"] = "SYMVALS";
54
+ KeyType["TIME_RANGE"] = "TIME_RANGE";
55
+ KeyType["WORK_ITEMS"] = "WORK_ITEMS";
56
56
  })(KeyType || (KeyType = {}));
57
57
  exports.KeyType = KeyType;
58
58
  class KeyService {
@@ -74,7 +74,7 @@ class KeyService {
74
74
  case KeyType.ENGINE_ID:
75
75
  return `${namespace}:${params.appId}:e:${params.engineId}`;
76
76
  case KeyType.WORK_ITEMS:
77
- return `${namespace}:${params.appId}:w:`;
77
+ return `${namespace}:${params.appId}:w:${params.scoutType || ''}`;
78
78
  case KeyType.TIME_RANGE:
79
79
  return `${namespace}:${params.appId}:t:${params.timeValue || ''}`;
80
80
  case KeyType.APP:
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hotmeshio/hotmesh",
3
- "version": "0.0.35",
3
+ "version": "0.0.37",
4
4
  "description": "Unbreakable Workflows",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -26,6 +26,11 @@ declare class Activity {
26
26
  adjacentIndex: number;
27
27
  constructor(config: ActivityType, data: ActivityData, metadata: ActivityMetadata, hook: ActivityData | null, engine: EngineService, context?: JobState);
28
28
  setLeg(leg: ActivityLeg): void;
29
+ /**
30
+ * Upon entering leg 1 of a duplexed activty, verify
31
+ * all aspects of the entry including job and activty state
32
+ */
33
+ verifyEntry(): Promise<void>;
29
34
  processEvent(status?: StreamStatus, code?: StreamCode, type?: 'hook' | 'output'): Promise<void>;
30
35
  processPending(telemetry: TelemetryService, type: 'hook' | 'output'): Promise<MultiResponseFlags>;
31
36
  processSuccess(telemetry: TelemetryService, type: 'hook' | 'output'): Promise<MultiResponseFlags>;
@@ -50,6 +55,11 @@ declare class Activity {
50
55
  bindJobMetadataPaths(): string[];
51
56
  bindActivityMetadataPaths(): string[];
52
57
  getState(): Promise<void>;
58
+ /**
59
+ * if the job is created/deleted/created with the same key,
60
+ * the 'gid' ensures no stale messages enter the stream
61
+ */
62
+ assertGenerationalId(jobGID: string, msgGID?: string): void;
53
63
  initDimensionalAddress(dad: string): void;
54
64
  initSelf(context: StringAnyType): JobState;
55
65
  initPolicies(context: JobState): void;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Activity = void 0;
4
+ const enums_1 = require("../../modules/enums");
4
5
  const errors_1 = require("../../modules/errors");
5
6
  const utils_1 = require("../../modules/utils");
6
7
  const collator_1 = require("../collator");
@@ -9,7 +10,6 @@ const pipe_1 = require("../pipe");
9
10
  const serializer_1 = require("../serializer");
10
11
  const telemetry_1 = require("../telemetry");
11
12
  const stream_1 = require("../../types/stream");
12
- const enums_1 = require("../../modules/enums");
13
13
  /**
14
14
  * The base class for all activities
15
15
  */
@@ -30,6 +30,16 @@ class Activity {
30
30
  setLeg(leg) {
31
31
  this.leg = leg;
32
32
  }
33
+ /**
34
+ * Upon entering leg 1 of a duplexed activty, verify
35
+ * all aspects of the entry including job and activty state
36
+ */
37
+ async verifyEntry() {
38
+ this.setLeg(1);
39
+ await this.getState();
40
+ collator_1.CollatorService.assertJobActive(this.context.metadata.js, this.context.metadata.jid, this.metadata.aid);
41
+ await collator_1.CollatorService.notarizeEntry(this);
42
+ }
33
43
  //******** DUPLEX RE-ENTRY POINT ********//
34
44
  async processEvent(status = stream_1.StreamStatus.SUCCESS, code = 200, type = 'output') {
35
45
  this.setLeg(2);
@@ -77,6 +87,10 @@ class Activity {
77
87
  this.logger.info('process-event-inactive-job-error', { error });
78
88
  return;
79
89
  }
90
+ else if (error instanceof errors_1.GenerationalError) {
91
+ this.logger.info('process-event-generational-job-error', { error });
92
+ return;
93
+ }
80
94
  else if (error instanceof errors_1.GetStateError) {
81
95
  this.logger.info('process-event-get-job-error', { error });
82
96
  return;
@@ -266,7 +280,7 @@ class Activity {
266
280
  return serializer_1.MDATA_SYMBOLS[keys_to_save].KEYS.map((key) => `output/metadata/${key}`);
267
281
  }
268
282
  async getState() {
269
- //assemble list of paths necessary to create 'job state' from the 'symbol hash'
283
+ const gid = this.context.metadata.gid;
270
284
  const jobSymbolHashName = `$${this.config.subscribes}`;
271
285
  const consumes = {
272
286
  [jobSymbolHashName]: serializer_1.MDATA_SYMBOLS.JOB.KEYS.map((key) => `metadata/${key}`)
@@ -295,10 +309,20 @@ class Activity {
295
309
  //`state` is a flat hash; context is a tree
296
310
  const [state, status] = await this.store.getState(jid, consumes, dIds);
297
311
  this.context = (0, utils_1.restoreHierarchy)(state);
312
+ this.assertGenerationalId(this.context.metadata.gid, gid);
298
313
  this.initDimensionalAddress(dad);
299
314
  this.initSelf(this.context);
300
315
  this.initPolicies(this.context);
301
316
  }
317
+ /**
318
+ * if the job is created/deleted/created with the same key,
319
+ * the 'gid' ensures no stale messages enter the stream
320
+ */
321
+ assertGenerationalId(jobGID, msgGID) {
322
+ if (msgGID !== jobGID) {
323
+ throw new errors_1.GenerationalError(jobGID, msgGID, this.context.metadata.jid, this.context.metadata.aid, this.context.metadata.dad);
324
+ }
325
+ }
302
326
  initDimensionalAddress(dad) {
303
327
  this.metadata.dad = dad;
304
328
  }
@@ -355,6 +379,7 @@ class Activity {
355
379
  metadata: {
356
380
  guid: (0, utils_1.guid)(),
357
381
  jid: this.context.metadata.jid,
382
+ gid: this.context.metadata.gid,
358
383
  dad: adjacentDad,
359
384
  aid: toActivityId,
360
385
  spn: this.context['$self'].output.metadata?.l2s,
@@ -383,7 +408,7 @@ class Activity {
383
408
  if (adjacencyList.length && jobStatus > 0) {
384
409
  const multi = this.store.getMulti();
385
410
  for (const execSignal of adjacencyList) {
386
- await this.engine.streamSignaler?.publishMessage(null, execSignal, multi);
411
+ await this.engine.router?.publishMessage(null, execSignal, multi);
387
412
  }
388
413
  mIds = (await multi.exec());
389
414
  }
@@ -4,8 +4,8 @@ exports.Await = void 0;
4
4
  const errors_1 = require("../../modules/errors");
5
5
  const activity_1 = require("./activity");
6
6
  const collator_1 = require("../collator");
7
- const stream_1 = require("../../types/stream");
8
7
  const telemetry_1 = require("../telemetry");
8
+ const stream_1 = require("../../types/stream");
9
9
  const pipe_1 = require("../pipe");
10
10
  const utils_1 = require("../../modules/utils");
11
11
  class Await extends activity_1.Activity {
@@ -14,14 +14,10 @@ class Await extends activity_1.Activity {
14
14
  }
15
15
  //******** INITIAL ENTRY POINT (A) ********//
16
16
  async process() {
17
- this.logger.debug('await-process', { jid: this.context.metadata.jid, aid: this.metadata.aid });
17
+ this.logger.debug('await-process', { jid: this.context.metadata.jid, gid: this.context.metadata.gid, aid: this.metadata.aid });
18
18
  let telemetry;
19
19
  try {
20
- //confirm entry is allowed and restore state
21
- this.setLeg(1);
22
- await collator_1.CollatorService.notarizeEntry(this);
23
- await this.getState();
24
- collator_1.CollatorService.assertJobActive(this.context.metadata.js, this.context.metadata.jid, this.metadata.aid);
20
+ await this.verifyEntry();
25
21
  telemetry = new telemetry_1.TelemetryService(this.engine.appId, this.config, this.metadata, this.context);
26
22
  telemetry.startActivitySpan(this.leg);
27
23
  this.mapInputData();
@@ -47,6 +43,10 @@ class Await extends activity_1.Activity {
47
43
  this.logger.error('await-inactive-job-error', { error });
48
44
  return;
49
45
  }
46
+ else if (error instanceof errors_1.GenerationalError) {
47
+ this.logger.info('process-event-generational-job-error', { error });
48
+ return;
49
+ }
50
50
  else if (error instanceof errors_1.GetStateError) {
51
51
  this.logger.error('await-get-state-error', { error });
52
52
  return;
@@ -59,7 +59,7 @@ class Await extends activity_1.Activity {
59
59
  }
60
60
  finally {
61
61
  telemetry?.endActivitySpan();
62
- this.logger.debug('await-process-end', { jid: this.context.metadata.jid, aid: this.metadata.aid });
62
+ this.logger.debug('await-process-end', { jid: this.context.metadata.jid, gid: this.context.metadata.gid, aid: this.metadata.aid });
63
63
  }
64
64
  }
65
65
  async execActivity(multi) {
@@ -68,6 +68,7 @@ class Await extends activity_1.Activity {
68
68
  metadata: {
69
69
  guid: (0, utils_1.guid)(),
70
70
  jid: this.context.metadata.jid,
71
+ gid: this.context.metadata.gid,
71
72
  dad: this.metadata.dad,
72
73
  aid: this.metadata.aid,
73
74
  topic,
@@ -82,7 +83,7 @@ class Await extends activity_1.Activity {
82
83
  retry: this.config.retry
83
84
  };
84
85
  }
85
- return (await this.engine.streamSignaler?.publishMessage(null, streamData, multi));
86
+ return (await this.engine.router?.publishMessage(null, streamData, multi));
86
87
  }
87
88
  }
88
89
  exports.Await = Await;
@@ -12,14 +12,10 @@ class Cycle extends activity_1.Activity {
12
12
  }
13
13
  //******** LEG 1 ENTRY ********//
14
14
  async process() {
15
- this.logger.debug('cycle-process', { jid: this.context.metadata.jid, aid: this.metadata.aid });
15
+ this.logger.debug('cycle-process', { jid: this.context.metadata.jid, gid: this.context.metadata.gid, aid: this.metadata.aid });
16
16
  let telemetry;
17
17
  try {
18
- //verify entry is allowed
19
- this.setLeg(1);
20
- await collator_1.CollatorService.notarizeEntry(this);
21
- await this.getState();
22
- collator_1.CollatorService.assertJobActive(this.context.metadata.js, this.context.metadata.jid, this.metadata.aid);
18
+ await this.verifyEntry();
23
19
  telemetry = new telemetry_1.TelemetryService(this.engine.appId, this.config, this.metadata, this.context);
24
20
  telemetry.startActivitySpan(this.leg);
25
21
  this.mapInputData();
@@ -47,6 +43,10 @@ class Cycle extends activity_1.Activity {
47
43
  this.logger.error('cycle-inactive-job-error', { error });
48
44
  return;
49
45
  }
46
+ else if (error instanceof errors_1.GenerationalError) {
47
+ this.logger.info('process-event-generational-job-error', { error });
48
+ return;
49
+ }
50
50
  else if (error instanceof errors_1.GetStateError) {
51
51
  this.logger.error('cycle-get-state-error', { error });
52
52
  return;
@@ -59,7 +59,7 @@ class Cycle extends activity_1.Activity {
59
59
  }
60
60
  finally {
61
61
  telemetry?.endActivitySpan();
62
- this.logger.debug('cycle-process-end', { jid: this.context.metadata.jid, aid: this.metadata.aid });
62
+ this.logger.debug('cycle-process-end', { jid: this.context.metadata.jid, gid: this.context.metadata.gid, aid: this.metadata.aid });
63
63
  }
64
64
  }
65
65
  /**
@@ -78,15 +78,16 @@ class Cycle extends activity_1.Activity {
78
78
  const streamData = {
79
79
  metadata: {
80
80
  guid: (0, utils_1.guid)(),
81
- dad: collator_1.CollatorService.resolveReentryDimension(this),
82
81
  jid: this.context.metadata.jid,
82
+ gid: this.context.metadata.gid,
83
+ dad: collator_1.CollatorService.resolveReentryDimension(this),
83
84
  aid: this.config.ancestor,
84
85
  spn: this.context['$self'].output.metadata?.l1s,
85
86
  trc: this.context.metadata.trc,
86
87
  },
87
88
  data: this.context.data
88
89
  };
89
- return (await this.engine.streamSignaler?.publishMessage(null, streamData, multi));
90
+ return (await this.engine.router?.publishMessage(null, streamData, multi));
90
91
  }
91
92
  }
92
93
  exports.Cycle = Cycle;
@@ -1,18 +1,24 @@
1
1
  import { Activity } from './activity';
2
2
  import { EngineService } from '../engine';
3
+ import { TelemetryService } from '../telemetry';
3
4
  import { ActivityData, ActivityMetadata, ActivityType, HookActivity } from '../../types/activity';
4
5
  import { HookRule } from '../../types/hook';
5
6
  import { JobState, JobStatus } from '../../types/job';
6
7
  import { RedisMulti } from '../../types/redis';
7
8
  import { StreamCode, StreamStatus } from '../../types/stream';
8
9
  /**
9
- * Listens for `webhook`, `timehook`, and `cycle` (repeat) signals
10
+ * Supports `signal hook`, `time hook`, and `cycle hook` patterns
10
11
  */
11
12
  declare class Hook extends Activity {
12
13
  config: HookActivity;
13
14
  constructor(config: ActivityType, data: ActivityData, metadata: ActivityMetadata, hook: ActivityData | null, engine: EngineService, context?: JobState);
14
15
  process(): Promise<string>;
16
+ /**
17
+ * does this activity use a time-hook or web-hook
18
+ */
15
19
  doesHook(): boolean;
20
+ doHook(telemetry: TelemetryService): Promise<void>;
21
+ doPassThrough(telemetry: TelemetryService): Promise<void>;
16
22
  getHookRule(topic: string): Promise<HookRule | undefined>;
17
23
  registerHook(multi?: RedisMulti): Promise<string | void>;
18
24
  processWebHookEvent(status?: StreamStatus, code?: StreamCode): Promise<JobStatus | void>;