@hotmeshio/hotmesh 0.21.1 → 0.22.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 (30) hide show
  1. package/README.md +12 -129
  2. package/build/modules/utils.js +3 -0
  3. package/build/package.json +2 -1
  4. package/build/services/activities/hook.d.ts +178 -58
  5. package/build/services/activities/hook.js +244 -58
  6. package/build/services/activities/trigger.js +5 -1
  7. package/build/services/durable/client.d.ts +238 -67
  8. package/build/services/durable/client.js +307 -131
  9. package/build/services/durable/index.d.ts +0 -2
  10. package/build/services/durable/schemas/factory.js +40 -0
  11. package/build/services/durable/worker.js +5 -28
  12. package/build/services/durable/workflow/condition.d.ts +69 -37
  13. package/build/services/durable/workflow/condition.js +70 -39
  14. package/build/services/hotmesh/index.d.ts +31 -4
  15. package/build/services/hotmesh/index.js +31 -4
  16. package/build/services/store/index.d.ts +1 -1
  17. package/build/services/store/providers/postgres/kvsql.d.ts +1 -1
  18. package/build/services/store/providers/postgres/kvtables.js +83 -122
  19. package/build/services/store/providers/postgres/kvtypes/hash/basic.d.ts +1 -1
  20. package/build/services/store/providers/postgres/kvtypes/hash/basic.js +8 -8
  21. package/build/services/store/providers/postgres/kvtypes/hash/index.d.ts +1 -1
  22. package/build/services/store/providers/postgres/postgres.d.ts +44 -188
  23. package/build/services/store/providers/postgres/postgres.js +480 -285
  24. package/build/types/activity.d.ts +2 -0
  25. package/build/types/hmsh_escalations.d.ts +212 -0
  26. package/build/types/index.d.ts +1 -1
  27. package/build/types/provider.d.ts +2 -0
  28. package/package.json +2 -1
  29. package/build/types/signal.d.ts +0 -147
  30. /package/build/types/{signal.js → hmsh_escalations.js} +0 -0
@@ -4,8 +4,8 @@ exports._setStatusAndCollateGuid = exports._collateLeg2Entry = exports._hincrbyf
4
4
  const utils_1 = require("./utils");
5
5
  function createBasicOperations(context) {
6
6
  return {
7
- async hsetnx(key, field, value, multi, entity) {
8
- const { sql, params } = _hset(context, key, { [field]: value }, { nx: true, entity });
7
+ async hsetnx(key, field, value, multi, entity, originId, parentId) {
8
+ const { sql, params } = _hset(context, key, { [field]: value }, { nx: true, entity, originId, parentId });
9
9
  if (multi) {
10
10
  multi.addCommand(sql, params, 'number');
11
11
  return Promise.resolve(0);
@@ -281,25 +281,25 @@ function _hset(context, key, fields, options) {
281
281
  if (options?.nx) {
282
282
  // Use WHERE NOT EXISTS to enforce nx
283
283
  sql = `
284
- INSERT INTO ${targetTable} (id, key, status, entity)
285
- SELECT gen_random_uuid(), $1, $2, $3
284
+ INSERT INTO ${targetTable} (id, key, status, entity, origin_id, parent_id)
285
+ SELECT gen_random_uuid(), $1, $2, $3, $4, $5
286
286
  WHERE NOT EXISTS (
287
287
  SELECT 1 FROM ${targetTable}
288
288
  WHERE key = $1 AND is_live
289
289
  )
290
290
  RETURNING 1 as count
291
291
  `;
292
- params.push(key, fields[':'], options?.entity ?? null);
292
+ params.push(key, fields[':'], options?.entity ?? null, options?.originId ?? null, options?.parentId ?? null);
293
293
  }
294
294
  else {
295
295
  // Update existing job or insert new one
296
296
  sql = `
297
- INSERT INTO ${targetTable} (id, key, status, entity)
298
- VALUES (gen_random_uuid(), $1, $2, $3)
297
+ INSERT INTO ${targetTable} (id, key, status, entity, origin_id, parent_id)
298
+ VALUES (gen_random_uuid(), $1, $2, $3, $4, $5)
299
299
  ON CONFLICT (key) WHERE is_live DO UPDATE SET status = EXCLUDED.status
300
300
  RETURNING 1 as count
301
301
  `;
302
- params.push(key, fields[':'], options?.entity ?? null);
302
+ params.push(key, fields[':'], options?.entity ?? null, options?.originId ?? null, options?.parentId ?? null);
303
303
  }
304
304
  }
305
305
  else if (isJobsTableResult) {
@@ -20,7 +20,7 @@ export declare const hashModule: (context: KVSQL) => {
20
20
  cursor: number;
21
21
  keys: string[];
22
22
  }>;
23
- hsetnx(key: string, field: string, value: string, multi?: import("./types").ProviderTransaction, entity?: string): Promise<number>;
23
+ hsetnx(key: string, field: string, value: string, multi?: import("./types").ProviderTransaction, entity?: string, originId?: string, parentId?: string): Promise<number>;
24
24
  hget(key: string, field: string, multi?: import("./types").ProviderTransaction): Promise<string>;
25
25
  hdel(key: string, fields: string[], multi?: unknown): Promise<number>;
26
26
  hmget(key: string, fields: string[], multi?: import("./types").ProviderTransaction): Promise<string[]>;
@@ -11,7 +11,6 @@ import { Transitions } from '../../../../types/transition';
11
11
  import { JobInterruptOptions } from '../../../../types/job';
12
12
  import { WorkListTaskType } from '../../../../types/task';
13
13
  import { ThrottleOptions } from '../../../../types/quorum';
14
- import { SignalQueueEntry } from '../../../../types/signal';
15
14
  import { StoreService } from '../..';
16
15
  import { PostgresClientType } from '../../../../types';
17
16
  import { KVSQL } from './kvsql';
@@ -105,7 +104,7 @@ declare class PostgresStoreService extends StoreService<ProviderClient, Provider
105
104
  * `purposeful re-entry`.
106
105
  */
107
106
  collateSynthetic(jobId: string, guid: string, amount: number, transaction?: ProviderTransaction): Promise<number>;
108
- setStateNX(jobId: string, appId: string, status?: number, entity?: string, transaction?: ProviderTransaction): Promise<boolean>;
107
+ setStateNX(jobId: string, appId: string, status?: number, entity?: string, transaction?: ProviderTransaction, originId?: string, parentId?: string): Promise<boolean>;
109
108
  getSchema(activityId: string, appVersion: AppVID): Promise<ActivityType>;
110
109
  getSchemas(appVersion: AppVID): Promise<Record<string, ActivityType>>;
111
110
  setSchemas(schemas: Record<string, ActivityType>, appVersion: AppVID): Promise<any>;
@@ -223,198 +222,55 @@ declare class PostgresStoreService extends StoreService<ProviderClient, Provider
223
222
  activity?: string;
224
223
  types?: string[];
225
224
  }): Promise<import('../../../../types/exporter').StreamHistoryEntry[]>;
226
- private signalQueueTable;
227
- private rowToSignalEntry;
228
- enqueueSignal(params: {
229
- namespace: string;
230
- appId: string;
231
- signalKey: string;
232
- workflowId: string;
233
- jobId?: string;
225
+ /**
226
+ * Parse a HotMesh-encoded value string.
227
+ * Values may be prefixed with `/s` (JSON), `/d` (number), `/t` or `/f` (boolean), `/n` (null).
228
+ */
229
+ private parseHmshValue;
230
+ private _escalationInsertSql;
231
+ private _escalationInsertParams;
232
+ createEscalation(params: import('../../../../types/hmsh_escalations').CreateEscalationParams): Promise<import('../../../../types/hmsh_escalations').EscalationEntry>;
233
+ /**
234
+ * Enqueues the escalation INSERT into an existing Leg1 transaction so the row
235
+ * is written atomically with the job state checkpoint. On conflict
236
+ * (ON CONFLICT DO NOTHING) the command is a no-op, making it safe for
237
+ * idempotent re-runs after a crash.
238
+ */
239
+ addEscalationToTransaction(params: import('../../../../types/hmsh_escalations').CreateEscalationParams, transaction: import('../../../../types/provider').ProviderTransaction): void;
240
+ getEscalation(id: string, namespace?: string): Promise<import('../../../../types/hmsh_escalations').EscalationEntry | null>;
241
+ getEscalationBySignalKey(signalKey: string, namespace?: string): Promise<import('../../../../types/hmsh_escalations').EscalationEntry | null>;
242
+ listEscalations(params?: import('../../../../types/hmsh_escalations').ListEscalationsParams): Promise<import('../../../../types/hmsh_escalations').EscalationEntry[]>;
243
+ claimEscalation(params: import('../../../../types/hmsh_escalations').ClaimEscalationParams): Promise<import('../../../../types/hmsh_escalations').ClaimEscalationResult>;
244
+ claimEscalationByMetadata(params: import('../../../../types/hmsh_escalations').ClaimByMetadataParams): Promise<import('../../../../types/hmsh_escalations').ClaimByMetadataResult>;
245
+ releaseEscalation(params: import('../../../../types/hmsh_escalations').ReleaseEscalationParams): Promise<import('../../../../types/hmsh_escalations').ReleaseEscalationResult>;
246
+ resolveEscalation(params: import('../../../../types/hmsh_escalations').ResolveEscalationParams): Promise<import('../../../../types/hmsh_escalations').ResolveEscalationResult & {
247
+ signalKey?: string;
234
248
  topic?: string;
235
- role?: string;
236
- type?: string;
237
- subtype?: string;
238
- priority?: number;
239
- description?: string;
240
- taskQueue?: string;
241
- workflowType?: string;
242
- assignedTo?: string;
243
- metadata?: Record<string, unknown>;
244
- envelope?: Record<string, unknown>;
245
- expiresAt?: Date;
246
- }): Promise<{
247
- id: string;
248
- } | null>;
249
- claimSignal(params: {
250
- namespace: string;
251
- appId: string;
252
- id: string;
253
- assignee?: string;
254
- durationMinutes?: number;
255
- }): Promise<{
256
- ok: true;
257
- entry: SignalQueueEntry;
258
- } | {
259
- ok: false;
260
- reason: 'not-found' | 'conflict';
261
- }>;
262
- claimSignalByMetadata(params: {
263
- namespace: string;
264
- appId: string;
265
- key: string;
266
- value: unknown;
267
- assignee?: string;
268
- durationMinutes?: number;
269
- }): Promise<{
270
- ok: true;
271
- entry: SignalQueueEntry;
272
- } | {
273
- ok: false;
274
- reason: 'not-found' | 'conflict';
275
249
  }>;
276
- releaseSignal(params: {
277
- namespace: string;
278
- appId: string;
279
- id: string;
280
- }): Promise<{
281
- ok: true;
282
- } | {
283
- ok: false;
284
- reason: 'not-found' | 'wrong-status';
250
+ resolveEscalationByMetadata(params: import('../../../../types/hmsh_escalations').ResolveByMetadataParams): Promise<import('../../../../types/hmsh_escalations').ResolveEscalationResult & {
251
+ signalKey?: string;
252
+ topic?: string;
285
253
  }>;
286
- resolveSignal(params: {
287
- namespace: string;
288
- appId: string;
254
+ /**
255
+ * Queues the escalation UPDATE into an existing transaction without executing it.
256
+ * Used by client.ts resolve() to commit the status change atomically with signal delivery.
257
+ */
258
+ queueResolveEscalation(params: {
289
259
  id: string;
260
+ namespace?: string;
290
261
  resolverPayload?: Record<string, unknown>;
291
- }): Promise<{
292
- ok: true;
293
- signalKey: string;
294
- topic: string;
295
- } | {
296
- ok: false;
297
- reason: 'not-found' | 'already-resolved';
298
- }>;
299
- resolveSignalByMetadata(params: {
300
- namespace: string;
301
- appId: string;
302
- key: string;
303
- value: unknown;
304
- resolverPayload?: Record<string, unknown>;
305
- }): Promise<{
306
- ok: true;
307
- signalKey: string;
308
- topic: string;
309
- } | {
310
- ok: false;
311
- reason: 'not-found';
312
- }>;
313
- releaseExpiredSignals(params: {
314
- namespace: string;
315
- appId: string;
316
- }): Promise<number>;
317
- listSignals(params: {
318
- namespace: string;
319
- appId: string;
320
- status?: string;
321
- role?: string;
322
- taskQueue?: string;
323
- limit?: number;
324
- offset?: number;
325
- }): Promise<{
326
- id: string;
327
- namespace: string;
328
- appId: string;
329
- signalKey: string;
330
- workflowId: string;
331
- jobId: string;
332
- topic: string;
333
- status: "pending" | "claimed" | "resolved" | "expired" | "released";
334
- role: string;
335
- type: string;
336
- subtype: string;
337
- priority: number;
338
- description: string;
339
- taskQueue: string;
340
- workflowType: string;
341
- assignedTo: string;
342
- claimedAt: Date;
343
- claimExpiresAt: Date;
344
- resolvedAt: Date;
345
- resolverPayload: Record<string, unknown>;
346
- envelope: Record<string, unknown>;
347
- metadata: Record<string, unknown>;
348
- expiresAt: Date;
349
- createdAt: Date;
350
- updatedAt: Date;
351
- }[]>;
352
- getSignal(params: {
353
- namespace: string;
354
- appId: string;
355
- id: string;
356
- }): Promise<{
357
- id: string;
358
- namespace: string;
359
- appId: string;
360
- signalKey: string;
361
- workflowId: string;
362
- jobId: string;
363
- topic: string;
364
- status: "pending" | "claimed" | "resolved" | "expired" | "released";
365
- role: string;
366
- type: string;
367
- subtype: string;
368
- priority: number;
369
- description: string;
370
- taskQueue: string;
371
- workflowType: string;
372
- assignedTo: string;
373
- claimedAt: Date;
374
- claimExpiresAt: Date;
375
- resolvedAt: Date;
376
- resolverPayload: Record<string, unknown>;
377
- envelope: Record<string, unknown>;
378
- metadata: Record<string, unknown>;
379
- expiresAt: Date;
380
- createdAt: Date;
381
- updatedAt: Date;
382
- }>;
383
- getSignalBySignalKey(params: {
384
- namespace: string;
385
- appId: string;
386
- signalKey: string;
387
- }): Promise<{
388
- id: string;
389
- namespace: string;
390
- appId: string;
391
- signalKey: string;
392
- workflowId: string;
393
- jobId: string;
394
- topic: string;
395
- status: "pending" | "claimed" | "resolved" | "expired" | "released";
396
- role: string;
397
- type: string;
398
- subtype: string;
399
- priority: number;
400
- description: string;
401
- taskQueue: string;
402
- workflowType: string;
403
- assignedTo: string;
404
- claimedAt: Date;
405
- claimExpiresAt: Date;
406
- resolvedAt: Date;
407
- resolverPayload: Record<string, unknown>;
408
- envelope: Record<string, unknown>;
409
- metadata: Record<string, unknown>;
410
- expiresAt: Date;
411
- createdAt: Date;
412
- updatedAt: Date;
413
- }>;
262
+ }, transaction: {
263
+ addCommand: (sql: string, params: any[], returnType: string) => any;
264
+ }): void;
414
265
  /**
415
- * Parse a HotMesh-encoded value string.
416
- * Values may be prefixed with `/s` (JSON), `/d` (number), `/t` or `/f` (boolean), `/n` (null).
266
+ * Finds the highest-priority pending or claimed escalation matching the given metadata filter.
267
+ * Used by client.ts resolveByMetadata() to get routing info before building the atomic transaction.
417
268
  */
418
- private parseHmshValue;
269
+ findEscalationByMetadata(key: string, value: string, roles: string[] | null, namespace?: string): Promise<import('../../../../types/hmsh_escalations').EscalationEntry | null>;
270
+ cancelEscalation(id: string, namespace?: string): Promise<import('../../../../types/hmsh_escalations').CancelEscalationResult>;
271
+ escalateEscalationToRole(params: import('../../../../types/hmsh_escalations').EscalateToRoleParams): Promise<import('../../../../types/hmsh_escalations').EscalationEntry | null>;
272
+ updateEscalation(params: import('../../../../types/hmsh_escalations').UpdateEscalationParams): Promise<import('../../../../types/hmsh_escalations').EscalationEntry | null>;
273
+ appendEscalationMilestones(params: import('../../../../types/hmsh_escalations').AppendMilestonesParams): Promise<import('../../../../types/hmsh_escalations').EscalationEntry | null>;
274
+ releaseExpiredEscalations(namespace?: string): Promise<number>;
419
275
  }
420
276
  export { PostgresStoreService };