@hotmeshio/hotmesh 0.7.0 → 0.9.0

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 (138) hide show
  1. package/.claude/settings.local.json +8 -0
  2. package/README.md +158 -38
  3. package/build/index.d.ts +1 -3
  4. package/build/index.js +1 -5
  5. package/build/modules/utils.js +3 -31
  6. package/build/package.json +63 -79
  7. package/build/services/activities/activity.d.ts +97 -9
  8. package/build/services/activities/activity.js +323 -86
  9. package/build/services/activities/await.d.ts +101 -0
  10. package/build/services/activities/await.js +103 -2
  11. package/build/services/activities/cycle.d.ts +82 -0
  12. package/build/services/activities/cycle.js +86 -8
  13. package/build/services/activities/hook.d.ts +144 -1
  14. package/build/services/activities/hook.js +162 -21
  15. package/build/services/activities/interrupt.d.ts +112 -0
  16. package/build/services/activities/interrupt.js +134 -29
  17. package/build/services/activities/signal.d.ts +111 -4
  18. package/build/services/activities/signal.js +136 -28
  19. package/build/services/activities/trigger.d.ts +56 -4
  20. package/build/services/activities/trigger.js +119 -35
  21. package/build/services/activities/worker.d.ts +107 -0
  22. package/build/services/activities/worker.js +109 -2
  23. package/build/services/collator/index.d.ts +116 -30
  24. package/build/services/collator/index.js +211 -115
  25. package/build/services/connector/factory.d.ts +1 -1
  26. package/build/services/connector/factory.js +1 -11
  27. package/build/services/engine/index.d.ts +22 -6
  28. package/build/services/engine/index.js +49 -18
  29. package/build/services/exporter/index.d.ts +2 -0
  30. package/build/services/exporter/index.js +1 -0
  31. package/build/services/hotmesh/index.d.ts +471 -236
  32. package/build/services/hotmesh/index.js +473 -238
  33. package/build/services/memflow/client.js +2 -2
  34. package/build/services/memflow/handle.js +1 -1
  35. package/build/services/memflow/index.d.ts +1 -1
  36. package/build/services/memflow/index.js +1 -1
  37. package/build/services/memflow/workflow/all.d.ts +28 -3
  38. package/build/services/memflow/workflow/all.js +28 -3
  39. package/build/services/memflow/workflow/context.d.ts +44 -1
  40. package/build/services/memflow/workflow/context.js +44 -1
  41. package/build/services/memflow/workflow/didRun.d.ts +23 -3
  42. package/build/services/memflow/workflow/didRun.js +23 -3
  43. package/build/services/memflow/workflow/emit.d.ts +43 -4
  44. package/build/services/memflow/workflow/emit.js +43 -4
  45. package/build/services/memflow/workflow/enrich.d.ts +32 -4
  46. package/build/services/memflow/workflow/enrich.js +32 -4
  47. package/build/services/memflow/workflow/entityMethods.d.ts +54 -7
  48. package/build/services/memflow/workflow/entityMethods.js +54 -7
  49. package/build/services/memflow/workflow/execChild.d.ts +96 -8
  50. package/build/services/memflow/workflow/execChild.js +96 -8
  51. package/build/services/memflow/workflow/execHook.d.ts +54 -39
  52. package/build/services/memflow/workflow/execHook.js +52 -38
  53. package/build/services/memflow/workflow/execHookBatch.d.ts +82 -29
  54. package/build/services/memflow/workflow/execHookBatch.js +80 -28
  55. package/build/services/memflow/workflow/hook.d.ts +68 -3
  56. package/build/services/memflow/workflow/hook.js +69 -4
  57. package/build/services/memflow/workflow/index.d.ts +65 -10
  58. package/build/services/memflow/workflow/index.js +65 -10
  59. package/build/services/memflow/workflow/interrupt.d.ts +50 -4
  60. package/build/services/memflow/workflow/interrupt.js +50 -4
  61. package/build/services/memflow/workflow/interruption.d.ts +49 -16
  62. package/build/services/memflow/workflow/interruption.js +49 -16
  63. package/build/services/memflow/workflow/isSideEffectAllowed.d.ts +21 -4
  64. package/build/services/memflow/workflow/isSideEffectAllowed.js +21 -4
  65. package/build/services/memflow/workflow/proxyActivities.d.ts +70 -42
  66. package/build/services/memflow/workflow/proxyActivities.js +70 -42
  67. package/build/services/memflow/workflow/random.d.ts +33 -3
  68. package/build/services/memflow/workflow/random.js +33 -3
  69. package/build/services/memflow/workflow/searchMethods.d.ts +49 -2
  70. package/build/services/memflow/workflow/searchMethods.js +49 -2
  71. package/build/services/memflow/workflow/signal.d.ts +51 -22
  72. package/build/services/memflow/workflow/signal.js +52 -23
  73. package/build/services/memflow/workflow/sleepFor.d.ts +57 -18
  74. package/build/services/memflow/workflow/sleepFor.js +57 -18
  75. package/build/services/memflow/workflow/trace.d.ts +39 -6
  76. package/build/services/memflow/workflow/trace.js +39 -6
  77. package/build/services/memflow/workflow/waitFor.d.ts +55 -18
  78. package/build/services/memflow/workflow/waitFor.js +55 -18
  79. package/build/services/router/consumption/index.js +1 -1
  80. package/build/services/search/factory.js +1 -9
  81. package/build/services/store/factory.js +1 -9
  82. package/build/services/store/index.d.ts +6 -1
  83. package/build/services/store/providers/postgres/kvsql.d.ts +4 -0
  84. package/build/services/store/providers/postgres/kvsql.js +4 -0
  85. package/build/services/store/providers/postgres/kvtransaction.d.ts +2 -0
  86. package/build/services/store/providers/postgres/kvtransaction.js +23 -0
  87. package/build/services/store/providers/postgres/kvtypes/hash/basic.d.ts +51 -0
  88. package/build/services/store/providers/postgres/kvtypes/hash/basic.js +193 -1
  89. package/build/services/store/providers/postgres/kvtypes/hash/index.d.ts +4 -0
  90. package/build/services/store/providers/postgres/kvtypes/hash/index.js +6 -0
  91. package/build/services/store/providers/postgres/postgres.d.ts +21 -1
  92. package/build/services/store/providers/postgres/postgres.js +42 -4
  93. package/build/services/stream/factory.js +1 -17
  94. package/build/services/stream/providers/postgres/scout.js +2 -2
  95. package/build/services/sub/factory.js +1 -9
  96. package/build/services/sub/index.d.ts +1 -1
  97. package/build/services/sub/providers/postgres/postgres.d.ts +1 -1
  98. package/build/services/sub/providers/postgres/postgres.js +25 -10
  99. package/build/services/task/index.d.ts +1 -1
  100. package/build/services/task/index.js +2 -6
  101. package/build/services/telemetry/index.js +6 -0
  102. package/build/types/activity.d.ts +1 -1
  103. package/build/types/hotmesh.d.ts +1 -1
  104. package/build/types/index.d.ts +0 -1
  105. package/build/types/index.js +1 -4
  106. package/build/types/job.d.ts +1 -1
  107. package/build/types/memflow.d.ts +1 -1
  108. package/build/types/provider.d.ts +1 -1
  109. package/build/types/quorum.d.ts +2 -2
  110. package/build/vitest.config.d.ts +2 -0
  111. package/build/vitest.config.js +18 -0
  112. package/index.ts +0 -4
  113. package/package.json +63 -79
  114. package/vitest.config.ts +17 -0
  115. package/build/services/connector/providers/ioredis.d.ts +0 -9
  116. package/build/services/connector/providers/ioredis.js +0 -26
  117. package/build/services/connector/providers/redis.d.ts +0 -9
  118. package/build/services/connector/providers/redis.js +0 -38
  119. package/build/services/search/providers/redis/ioredis.d.ts +0 -23
  120. package/build/services/search/providers/redis/ioredis.js +0 -189
  121. package/build/services/search/providers/redis/redis.d.ts +0 -23
  122. package/build/services/search/providers/redis/redis.js +0 -202
  123. package/build/services/store/providers/redis/_base.d.ts +0 -137
  124. package/build/services/store/providers/redis/_base.js +0 -980
  125. package/build/services/store/providers/redis/ioredis.d.ts +0 -20
  126. package/build/services/store/providers/redis/ioredis.js +0 -190
  127. package/build/services/store/providers/redis/redis.d.ts +0 -18
  128. package/build/services/store/providers/redis/redis.js +0 -199
  129. package/build/services/stream/providers/redis/ioredis.d.ts +0 -61
  130. package/build/services/stream/providers/redis/ioredis.js +0 -272
  131. package/build/services/stream/providers/redis/redis.d.ts +0 -61
  132. package/build/services/stream/providers/redis/redis.js +0 -305
  133. package/build/services/sub/providers/redis/ioredis.d.ts +0 -20
  134. package/build/services/sub/providers/redis/ioredis.js +0 -161
  135. package/build/services/sub/providers/redis/redis.d.ts +0 -18
  136. package/build/services/sub/providers/redis/redis.js +0 -148
  137. package/build/types/redis.d.ts +0 -258
  138. package/build/types/redis.js +0 -11
@@ -7,6 +7,113 @@ const collator_1 = require("../collator");
7
7
  const pipe_1 = require("../pipe");
8
8
  const telemetry_1 = require("../telemetry");
9
9
  const activity_1 = require("./activity");
10
+ /**
11
+ * Dispatches work to a registered callback function. The `worker` activity
12
+ * publishes a message to its configured `topic` stream, where a worker
13
+ * process picks it up, executes the callback, and returns a response
14
+ * that the engine captures as the activity's output.
15
+ *
16
+ * ## YAML Configuration
17
+ *
18
+ * ```yaml
19
+ * app:
20
+ * id: myapp
21
+ * version: '1'
22
+ * graphs:
23
+ * - subscribes: order.placed
24
+ * expire: 120
25
+ *
26
+ * activities:
27
+ * t1:
28
+ * type: trigger
29
+ *
30
+ * a1:
31
+ * type: worker
32
+ * topic: work.do # matches the registered worker topic
33
+ * input:
34
+ * schema:
35
+ * type: object
36
+ * properties:
37
+ * x: { type: string }
38
+ * maps:
39
+ * x: '{t1.output.data.inputField}'
40
+ * output:
41
+ * schema:
42
+ * type: object
43
+ * properties:
44
+ * y: { type: string }
45
+ * job:
46
+ * maps:
47
+ * result: '{$self.output.data.y}'
48
+ *
49
+ * transitions:
50
+ * t1:
51
+ * - to: a1
52
+ * ```
53
+ *
54
+ * ## Worker Registration (JavaScript)
55
+ *
56
+ * Workers are registered at initialization time via the `workers` array
57
+ * in `HotMesh.init`. Each worker binds a `topic` to a `callback` function.
58
+ *
59
+ * ```typescript
60
+ * const hotMesh = await HotMesh.init({
61
+ * appId: 'myapp',
62
+ * engine: { connection },
63
+ * workers: [{
64
+ * topic: 'work.do',
65
+ * connection,
66
+ * callback: async (data: StreamData) => ({
67
+ * metadata: { ...data.metadata },
68
+ * data: { y: `${data.data.x} transformed` }
69
+ * })
70
+ * }]
71
+ * });
72
+ * ```
73
+ *
74
+ * ## Retry Policy
75
+ *
76
+ * Retry behavior is configured at the **worker level** (not in YAML) via
77
+ * the `retryPolicy` option. Failed callbacks are retried with exponential
78
+ * backoff until `maximumAttempts` is exhausted. The `maximumInterval` caps
79
+ * the delay between retries.
80
+ *
81
+ * ```typescript
82
+ * const hotMesh = await HotMesh.init({
83
+ * appId: 'myapp',
84
+ * engine: { connection },
85
+ * workers: [{
86
+ * topic: 'work.backoff',
87
+ * connection,
88
+ * retryPolicy: {
89
+ * maximumAttempts: 5, // retry up to 5 times
90
+ * backoffCoefficient: 2, // exponential: 2^0, 2^1, 2^2, ... seconds
91
+ * maximumInterval: '30s', // cap delay at 30 seconds
92
+ * },
93
+ * callback: async (data: StreamData) => {
94
+ * const result = await doWork(data.data);
95
+ * return {
96
+ * code: 200,
97
+ * status: StreamStatus.SUCCESS,
98
+ * metadata: { ...data.metadata },
99
+ * data: { result },
100
+ * } as StreamDataResponse;
101
+ * },
102
+ * }]
103
+ * });
104
+ * ```
105
+ *
106
+ * ## Execution Model
107
+ *
108
+ * Worker is a **Category A (duplex)** activity:
109
+ * - **Leg 1** (`process`): Maps input data and publishes a message to the
110
+ * worker's topic stream.
111
+ * - **Leg 2** (`processEvent`, inherited): Receives the worker's response,
112
+ * maps output data, and executes the step protocol to transition to
113
+ * adjacent activities.
114
+ *
115
+ * @see {@link WorkerActivity} for the TypeScript interface
116
+ */
10
117
  class Worker extends activity_1.Activity {
11
118
  constructor(config, data, metadata, hook, engine, context) {
12
119
  super(config, data, metadata, hook, engine, context);
@@ -24,11 +131,11 @@ class Worker extends activity_1.Activity {
24
131
  telemetry = new telemetry_1.TelemetryService(this.engine.appId, this.config, this.metadata, this.context);
25
132
  telemetry.startActivitySpan(this.leg);
26
133
  this.mapInputData();
27
- //save state and authorize reentry
134
+ //save state and mark Leg1 complete
28
135
  const transaction = this.store.transact();
29
136
  //todo: await this.registerTimeout();
30
137
  const messageId = await this.execActivity(transaction);
31
- await collator_1.CollatorService.authorizeReentry(this, transaction);
138
+ await collator_1.CollatorService.notarizeLeg1Completion(this, transaction);
32
139
  await this.setState(transaction);
33
140
  await this.setStatus(0, transaction);
34
141
  const txResponse = (await transaction.exec());
@@ -6,6 +6,23 @@ import { Activity } from '../activities/activity';
6
6
  import { Cycle } from '../activities/cycle';
7
7
  declare class CollatorService {
8
8
  static targetLength: number;
9
+ /**
10
+ * Positional weights for the 15-digit activity/GUID ledger.
11
+ *
12
+ * Position: 1 2 3 4 5 6 7 8-15
13
+ * Weight: 100T 10T 1T 100B 10B 1B 100M 10M..1
14
+ */
15
+ static WEIGHTS: {
16
+ AUTH: number;
17
+ FINALIZE: number;
18
+ LEG1_ENTRY: number;
19
+ LEG1_COMPLETE: number;
20
+ STEP1_WORK: number;
21
+ STEP2_SPAWN: number;
22
+ STEP3_CLEANUP: number;
23
+ LEG2_ENTRY: number;
24
+ GUID_SNAPSHOT: number;
25
+ };
9
26
  /**
10
27
  * Upon re/entry, verify that the job status is active
11
28
  */
@@ -26,53 +43,122 @@ declare class CollatorService {
26
43
  * the origin node can be queried for approval/entry.
27
44
  */
28
45
  static resolveReentryDimension(activity: Cycle): string;
46
+ /**
47
+ * Leg1 entry: increment attempt counter (+1T).
48
+ * NOT bundled with Leg1 work — exists only to mark entry.
49
+ */
29
50
  static notarizeEntry(activity: Activity, transaction?: ProviderTransaction): Promise<number>;
30
- static authorizeReentry(activity: Activity, transaction?: ProviderTransaction): Promise<number>;
51
+ /**
52
+ * Leg1 completion: increment +100B to mark Leg1 complete.
53
+ * For cycle=true activities, also pre-seeds the Leg2 entry counter (+1)
54
+ * so the first real Leg2 gets adjacentIndex=1 (new dimension).
55
+ * MUST be bundled in the same transaction as Leg1 durable work.
56
+ */
57
+ static notarizeLeg1Completion(activity: Activity, transaction?: ProviderTransaction): Promise<number>;
58
+ /**
59
+ * Leg1 early exit: marks Leg1 complete for activities that
60
+ * only run Leg1 and fully close (e.g., Cycle).
61
+ * Increment +100B (Leg1 completion marker).
62
+ */
31
63
  static notarizeEarlyExit(activity: Activity, transaction?: ProviderTransaction): Promise<number>;
64
+ /**
65
+ * Leg1 early completion: marks Leg1 complete for Leg1-only
66
+ * activities that spawn children (e.g., Signal, Hook passthrough,
67
+ * Interrupt-another). Increment +100B.
68
+ */
32
69
  static notarizeEarlyCompletion(activity: Activity, transaction?: ProviderTransaction): Promise<number>;
33
70
  /**
34
- * sets the synthetic inception key (in case of an overage occurs).
71
+ * Leg2 entry: atomically increments the activity ledger (+1) and
72
+ * seeds the GUID ledger with the ordinal IF NOT EXISTS.
73
+ * Returns [activityLedger, guidLedger] after the compound operation.
74
+ */
75
+ static notarizeLeg2Entry(activity: Activity, guid: string, transaction?: ProviderTransaction): Promise<[number, number]>;
76
+ /**
77
+ * Step 1: Mark Leg2 work done (+10B on GUID ledger only).
78
+ * MUST be bundled with Leg2 durable work writes.
79
+ */
80
+ static notarizeStep1(activity: Activity, guid: string, transaction: ProviderTransaction): Promise<void>;
81
+ /**
82
+ * Step 2: Mark children spawned (+1B on GUID ledger only).
83
+ * The job semaphore update and GUID job-closed snapshot are handled
84
+ * by the compound `setStatusAndCollateGuid` primitive, which MUST
85
+ * be called in the same transaction.
86
+ */
87
+ static notarizeStep2(activity: Activity, guid: string, transaction: ProviderTransaction): Promise<void>;
88
+ /**
89
+ * Step 3: Mark job completion tasks done (+100M on GUID ledger only).
90
+ * MUST be bundled with job completion durable writes.
91
+ */
92
+ static notarizeStep3(activity: Activity, guid: string, transaction: ProviderTransaction): Promise<void>;
93
+ /**
94
+ * Finalize: close the activity to new Leg2 GUIDs (+200T).
95
+ * Sets pos 1 to 2 (finalized).
96
+ * Only for non-cycle activities after final SUCCESS/ERROR.
35
97
  */
36
- static notarizeInception(activity: Activity, guid: string, transaction: ProviderTransaction): Promise<void>;
98
+ static notarizeFinalize(activity: Activity, transaction: ProviderTransaction): Promise<void>;
37
99
  /**
38
- * ignore those ID collisions that are due to re-entry overages
100
+ * Check if Step 1 (work done) is complete on the GUID ledger.
101
+ * Position 5 (10B digit) > 0.
39
102
  */
40
- static isInceptionOverage(activity: Activity, guid: string): Promise<boolean>;
103
+ static isGuidStep1Done(guidLedger: number): boolean;
41
104
  /**
42
- * verifies both the concrete and synthetic keys for the activity; concrete keys
43
- * exist in the original model and are effectively the 'real' keys. In reality,
44
- * hook activities are atomized during compilation to create a synthetic DAG that
45
- * is used to track the status of the graph in a distributed environment. The
46
- * synthetic key represents different dimensional realities and is used to
47
- * track re-entry overages (it distinguishes between the original and re-entry).
48
- * The essential challenge is: is this a re-entry that is purposeful in
49
- * order to induce cycles, or is the re-entry due to a failure in the system?
105
+ * Check if Step 2 (children spawned) is complete on the GUID ledger.
106
+ * Position 6 (1B digit) > 0.
107
+ */
108
+ static isGuidStep2Done(guidLedger: number): boolean;
109
+ /**
110
+ * Check if Step 3 (job completion tasks) is complete on the GUID ledger.
111
+ * Position 7 (100M digit) > 0.
112
+ */
113
+ static isGuidStep3Done(guidLedger: number): boolean;
114
+ /**
115
+ * Check if this GUID was responsible for closing the job.
116
+ * Position 4 (100B digit) > 0 (job closed snapshot).
117
+ */
118
+ static isGuidJobClosed(guidLedger: number): boolean;
119
+ /**
120
+ * Get the attempt count from the GUID ledger (last 8 digits).
121
+ */
122
+ static getGuidAttemptCount(guidLedger: number): number;
123
+ /**
124
+ * Gets the digit at a 1-indexed position from a 15-digit ledger value.
125
+ * The value is left-padded to 15 digits before extraction.
126
+ */
127
+ static getDigitAtPosition(num: number, position: number): number;
128
+ /**
129
+ * @deprecated Use getDigitAtPosition (1-indexed) instead
50
130
  */
51
- static notarizeReentry(activity: Activity, guid: string, transaction?: ProviderTransaction): Promise<number>;
52
- static notarizeContinuation(activity: Activity, transaction?: ProviderTransaction): Promise<number>;
53
- static notarizeCompletion(activity: Activity, transaction?: ProviderTransaction): Promise<number>;
54
131
  static getDigitAtIndex(num: number, targetDigitIndex: number): number | null;
132
+ /**
133
+ * Extracts the dimensional index from the Leg2 entry counter.
134
+ * Non-cycle activities: first Leg2 → leg2Count=1 → 1-1=0 (same dimension as Leg1).
135
+ * Cycle activities: first Leg2 → leg2Count=2 (pre-seeded +1) → 2-1=1 (new dimension).
136
+ */
55
137
  static getDimensionalIndex(num: number): number | null;
56
- static isDuplicate(num: number, targetDigitIndex: number): boolean;
57
- static isInactive(num: number): boolean;
58
- static isPrimed(amount: number, leg: ActivityDuplex): boolean;
59
138
  /**
60
- * During compilation, the graphs are compiled into structures necessary
61
- * for distributed processing; these are referred to as 'synthetic DAGs',
62
- * because they are not part of the original graph, but are used to track
63
- * the status of the graph in a distributed environment. This check ensures
64
- * that the 'synthetic key' is not a duplicate. (which is different than
65
- * saying the 'key' is not a duplicate)
139
+ * Verifies the GUID ledger value for step-level resume decisions.
140
+ * The GUID ledger is seeded with an ordinal position (last 8 digits)
141
+ * on first entry; step markers drive all resume/reject logic.
142
+ *
143
+ * Fully processed: Step 3 done, or Steps 1+2 done without job closure.
144
+ * Crash recovery: Any incomplete step combination is allowed for resume.
66
145
  */
67
146
  static verifySyntheticInteger(amount: number): void;
68
- static verifyInteger(amount: number, leg: ActivityDuplex, stage: CollationStage): void;
69
- static getDimensionsById(ancestors: string[], dad: string): Record<string, string>;
70
147
  /**
71
- * All non-trigger activities are assigned a status seed by their parent
148
+ * Verifies the activity ledger value at entry boundaries.
149
+ *
150
+ * Leg1 enter: pos 3 (1T digit) must be > 0 after +1T (proves seed exists).
151
+ * pos 4 (100B) must be 0 (Leg1 not yet complete).
152
+ * If pos 3 > 1 and pos 4 == 1, it's a stale/replayed message.
153
+ *
154
+ * Leg2 enter: pos 4 (100B) must be > 0 (Leg1 complete, reentry authorized).
155
+ * pos 1 (100T) must be < 2 (not finalized) — cycle activities exempt.
72
156
  */
73
- static getSeed(): string;
157
+ static verifyInteger(amount: number, leg: ActivityDuplex, stage: CollationStage): void;
158
+ static getDimensionsById(ancestors: string[], dad: string): Record<string, string>;
74
159
  /**
75
- * All trigger activities are assigned a status seed in a completed state
160
+ * All trigger activities are assigned a status seed in a completed state.
161
+ * Seed: 101100000000001 (authorized, 1 Leg1 entry, Leg1 complete, 1 Leg2 entry)
76
162
  */
77
163
  static getTriggerSeed(): string;
78
164
  /**