@hotmeshio/hotmesh 0.6.1 → 0.7.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 (55) hide show
  1. package/README.md +179 -142
  2. package/build/modules/enums.d.ts +7 -0
  3. package/build/modules/enums.js +16 -1
  4. package/build/modules/utils.d.ts +27 -0
  5. package/build/modules/utils.js +52 -1
  6. package/build/package.json +10 -8
  7. package/build/services/connector/providers/postgres.js +3 -0
  8. package/build/services/hotmesh/index.d.ts +66 -15
  9. package/build/services/hotmesh/index.js +84 -15
  10. package/build/services/memflow/index.d.ts +100 -14
  11. package/build/services/memflow/index.js +100 -14
  12. package/build/services/memflow/worker.d.ts +97 -0
  13. package/build/services/memflow/worker.js +217 -0
  14. package/build/services/memflow/workflow/proxyActivities.d.ts +74 -3
  15. package/build/services/memflow/workflow/proxyActivities.js +81 -4
  16. package/build/services/router/consumption/index.d.ts +2 -1
  17. package/build/services/router/consumption/index.js +38 -2
  18. package/build/services/router/error-handling/index.d.ts +3 -3
  19. package/build/services/router/error-handling/index.js +48 -13
  20. package/build/services/router/index.d.ts +1 -0
  21. package/build/services/router/index.js +2 -1
  22. package/build/services/store/index.d.ts +3 -2
  23. package/build/services/store/providers/postgres/kvtypes/hash/basic.js +36 -6
  24. package/build/services/store/providers/postgres/kvtypes/hash/expire.js +12 -2
  25. package/build/services/store/providers/postgres/kvtypes/hash/scan.js +30 -10
  26. package/build/services/store/providers/postgres/kvtypes/list.js +68 -10
  27. package/build/services/store/providers/postgres/kvtypes/string.js +60 -10
  28. package/build/services/store/providers/postgres/kvtypes/zset.js +92 -22
  29. package/build/services/store/providers/postgres/postgres.d.ts +3 -3
  30. package/build/services/store/providers/redis/_base.d.ts +3 -3
  31. package/build/services/store/providers/redis/ioredis.js +17 -7
  32. package/build/services/stream/providers/postgres/kvtables.js +76 -23
  33. package/build/services/stream/providers/postgres/lifecycle.d.ts +19 -0
  34. package/build/services/stream/providers/postgres/lifecycle.js +54 -0
  35. package/build/services/stream/providers/postgres/messages.d.ts +56 -0
  36. package/build/services/stream/providers/postgres/messages.js +253 -0
  37. package/build/services/stream/providers/postgres/notifications.d.ts +59 -0
  38. package/build/services/stream/providers/postgres/notifications.js +357 -0
  39. package/build/services/stream/providers/postgres/postgres.d.ts +110 -11
  40. package/build/services/stream/providers/postgres/postgres.js +196 -488
  41. package/build/services/stream/providers/postgres/scout.d.ts +68 -0
  42. package/build/services/stream/providers/postgres/scout.js +233 -0
  43. package/build/services/stream/providers/postgres/stats.d.ts +49 -0
  44. package/build/services/stream/providers/postgres/stats.js +113 -0
  45. package/build/services/sub/providers/postgres/postgres.js +37 -5
  46. package/build/services/sub/providers/redis/ioredis.js +13 -2
  47. package/build/services/sub/providers/redis/redis.js +13 -2
  48. package/build/services/worker/index.d.ts +1 -0
  49. package/build/services/worker/index.js +2 -0
  50. package/build/types/hotmesh.d.ts +42 -2
  51. package/build/types/index.d.ts +3 -3
  52. package/build/types/memflow.d.ts +32 -0
  53. package/build/types/provider.d.ts +16 -0
  54. package/build/types/stream.d.ts +92 -1
  55. package/package.json +10 -8
@@ -3,11 +3,11 @@ export { App, AppVID, AppTransitions, AppSubscriptions } from './app';
3
3
  export { AsyncSignal } from './async';
4
4
  export { CacheMode } from './cache';
5
5
  export { CollationFaultType, CollationStage } from './collator';
6
- export { ActivityConfig, ActivityWorkflowDataType, ChildResponseType, ClientConfig, ClientWorkflow, ContextType, Connection, ProxyResponseType, ProxyType, Registry, SignalOptions, FindJobsOptions, FindOptions, FindWhereOptions, FindWhereQuery, HookOptions, SearchResults, WorkflowConfig, WorkerConfig, WorkerOptions, WorkflowContext, WorkflowSearchOptions, WorkflowSearchSchema, WorkflowDataType, WorkflowOptions, } from './memflow';
6
+ export { ActivityConfig, ActivityWorkflowDataType, ChildResponseType, ClientConfig, ClientWorkflow, ContextType, Connection, ProxyResponseType, ProxyType, Registry, SignalOptions, FindJobsOptions, FindOptions, FindWhereOptions, FindWhereQuery, HookOptions, SearchResults, WorkflowConfig, WorkerConfig, WorkerOptions, WorkflowContext, WorkflowSearchOptions, WorkflowSearchSchema, WorkflowDataType, WorkflowOptions, WorkflowInterceptor, InterceptorRegistry, } from './memflow';
7
7
  export { MemFlowChildErrorType, MemFlowProxyErrorType, MemFlowSleepErrorType, MemFlowWaitForAllErrorType, MemFlowWaitForErrorType, } from './error';
8
8
  export { ActivityAction, DependencyExport, MemFlowJobExport, ExportCycles, ExportItem, ExportOptions, ExportTransitions, JobAction, JobExport, JobActionExport, JobTimeline, } from './exporter';
9
9
  export { HookCondition, HookConditions, HookGate, HookInterface, HookRule, HookRules, HookSignal, } from './hook';
10
- export { HotMesh, HotMeshEngine, HotMeshWorker, HotMeshSettings, HotMeshApp, HotMeshApps, HotMeshConfig, HotMeshManifest, HotMeshGraph, KeyType, KeyStoreParams, } from './hotmesh';
10
+ export { HotMesh, HotMeshEngine, HotMeshWorker, HotMeshSettings, HotMeshApp, HotMeshApps, HotMeshConfig, HotMeshManifest, HotMeshGraph, KeyType, KeyStoreParams, ScoutType, } from './hotmesh';
11
11
  export { ILogger, LogLevel } from './logger';
12
12
  export { ExtensionType, JobCompletionOptions, JobData, JobsData, JobInterruptOptions, JobMetadata, JobOutput, JobState, JobStatus, PartialJobState, } from './job';
13
13
  export { MappingStatements } from './map';
@@ -20,7 +20,7 @@ export { NatsAckPolicy, NatsAckPolicyExplicitType, NatsClassType, NatsClientType
20
20
  export { RedisClass, RedisRedisClientType, RedisRedisClientOptions, RedisRedisClassType, IORedisClientType, RedisClient, RedisMulti, RedisRedisMultiType, IORedisClientOptions, IORedisClassType, IORedisMultiType, RedisOptions, isRedisClient, isIORedisClient, } from './redis';
21
21
  export { JSONSchema, StringAnyType, StringScalarType, StringStringType, SymbolMap, SymbolMaps, SymbolRanges, Symbols, SymbolSets, } from './serializer';
22
22
  export { AggregatedData, CountByFacet, GetStatsOptions, IdsData, Measure, MeasureIds, MetricTypes, StatType, StatsType, IdsResponse, JobStats, JobStatsInput, JobStatsRange, StatsResponse, Segment, TimeSegment, } from './stats';
23
- export { ReclaimedMessageType, RouterConfig, StreamCode, StreamConfig, StreamData, StreamDataType, StreamError, StreamDataResponse, StreamMessage, StreamMessageMetadata, StreamProviderType, StreamRetryPolicy, StreamRole, StreamStats, StreamStatus, } from './stream';
23
+ export { ReclaimedMessageType, RetryPolicy, RouterConfig, StreamCode, StreamConfig, StreamData, StreamDataType, StreamError, StreamDataResponse, StreamMessage, StreamMessageMetadata, StreamProviderType, StreamRetryPolicy, StreamRole, StreamStats, StreamStatus, PublishMessageConfig, } from './stream';
24
24
  export { context, Context, Counter, Meter, metrics, propagation, SpanContext, Span, SpanStatus, SpanStatusCode, SpanKind, trace, Tracer, ValueType, } from './telemetry';
25
25
  export { WorkListTaskType } from './task';
26
26
  export { TransitionMatch, TransitionRule, Transitions } from './transition';
@@ -457,6 +457,38 @@ type ActivityConfig = {
457
457
  startToCloseTimeout?: string;
458
458
  /** Configuration for specific activities, type not yet specified */
459
459
  activities?: any;
460
+ /**
461
+ * Optional explicit task queue for activities.
462
+ *
463
+ * **Default Behavior (no taskQueue specified):**
464
+ * Activities use the workflow's task queue + "-activity" suffix.
465
+ * Example: workflow "my-workflow" → activity queue "my-workflow-activity"
466
+ *
467
+ * **Explicit Task Queue (when specified):**
468
+ * Activities use the specified task queue + "-activity" suffix.
469
+ * Useful for:
470
+ * - Shared activity pools across multiple workflows
471
+ * - Interceptors (prevents per-workflow queue creation)
472
+ * - Isolated activity worker pools
473
+ *
474
+ * @example
475
+ * ```typescript
476
+ * // Default: uses workflow's task queue (backward compatible)
477
+ * const activities = MemFlow.workflow.proxyActivities<typeof activities>({
478
+ * activities,
479
+ * retryPolicy: { maximumAttempts: 3 }
480
+ * });
481
+ * // If workflow taskQueue is "orders", uses "orders-activity"
482
+ *
483
+ * // Explicit: shared queue for interceptors (prevents explosion)
484
+ * const { auditLog } = MemFlow.workflow.proxyActivities<typeof activities>({
485
+ * activities: { auditLog },
486
+ * taskQueue: 'shared-activities', // Uses "shared-activities-activity"
487
+ * retryPolicy: { maximumAttempts: 3 }
488
+ * });
489
+ * ```
490
+ */
491
+ taskQueue?: string;
460
492
  /** Retry policy configuration for activities */
461
493
  retryPolicy?: {
462
494
  /** Maximum number of retry attempts, default is 5 (HMSH_MEMFLOW_MAX_ATTEMPTS) */
@@ -62,6 +62,22 @@ export type ProviderConfig = {
62
62
  * can still read/write to the store and can still pub/sub events.
63
63
  */
64
64
  readonly?: boolean;
65
+ /**
66
+ * Retry policy for stream messages. Configures automatic retry
67
+ * behavior with exponential backoff for failed operations.
68
+ *
69
+ * @example
70
+ * ```typescript
71
+ * {
72
+ * retryPolicy: {
73
+ * maximumAttempts: 5,
74
+ * backoffCoefficient: 2,
75
+ * maximumInterval: '300s'
76
+ * }
77
+ * }
78
+ * ```
79
+ */
80
+ retryPolicy?: import('./stream').RetryPolicy;
65
81
  };
66
82
  export type ProvidersConfig = {
67
83
  sub: ProviderConfig;
@@ -1,4 +1,40 @@
1
1
  import { ProviderTransaction } from './provider';
2
+ /**
3
+ * Structured retry policy configuration for stream messages.
4
+ * Controls retry behavior with exponential backoff.
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * const retryPolicy: RetryPolicy = {
9
+ * maximumAttempts: 5,
10
+ * backoffCoefficient: 2,
11
+ * maximumInterval: '300s',
12
+ * };
13
+ * // Results in delays: 2s, 4s, 8s, 16s, 32s, 64s, 128s, 256s, 300s (capped)
14
+ * ```
15
+ */
16
+ export interface RetryPolicy {
17
+ /**
18
+ * Maximum number of retry attempts before the message fails.
19
+ * @default 3
20
+ * @example 5
21
+ */
22
+ maximumAttempts?: number;
23
+ /**
24
+ * Base coefficient for exponential backoff calculation.
25
+ * Retry delay = min(backoffCoefficient ^ attemptNumber, maximumInterval)
26
+ * @default 10
27
+ * @example 2
28
+ */
29
+ backoffCoefficient?: number;
30
+ /**
31
+ * Maximum interval between retries in seconds or as a duration string.
32
+ * Caps the exponential backoff to prevent excessive delays.
33
+ * @default "120s"
34
+ * @example "60s" or 60
35
+ */
36
+ maximumInterval?: string | number;
37
+ }
2
38
  /** Represents a policy for retrying stream operations based on error codes */
3
39
  export interface StreamRetryPolicy {
4
40
  /**
@@ -133,6 +169,8 @@ export type RouterConfig = {
133
169
  reclaimCount?: number;
134
170
  /** if true, will not process stream messages; default true */
135
171
  readonly?: boolean;
172
+ /** Retry policy for worker messages. Applied when worker callback throws an error */
173
+ retryPolicy?: RetryPolicy;
136
174
  };
137
175
  export type StreamProviderType = 'postgres' | 'nats' | 'sqs';
138
176
  export interface StreamConfig {
@@ -142,6 +180,20 @@ export interface StreamConfig {
142
180
  maxRetries?: number;
143
181
  batchSize?: number;
144
182
  timeout?: number;
183
+ /**
184
+ * Default retry policy for all streams in this app.
185
+ * Can be overridden per message using PublishMessageConfig.
186
+ *
187
+ * @example
188
+ * ```typescript
189
+ * {
190
+ * maximumAttempts: 5,
191
+ * backoffCoefficient: 2,
192
+ * maximumInterval: '300s',
193
+ * }
194
+ * ```
195
+ */
196
+ retryPolicy?: RetryPolicy;
145
197
  postgres?: {
146
198
  pollInterval?: number;
147
199
  vacuumInterval?: number;
@@ -169,6 +221,11 @@ export interface StreamMessage {
169
221
  id: string;
170
222
  data: StreamData;
171
223
  metadata?: StreamMessageMetadata;
224
+ /**
225
+ * Retry policy configuration for this message.
226
+ * Populated from database columns when available.
227
+ */
228
+ retryPolicy?: RetryPolicy;
172
229
  }
173
230
  export interface StreamMessageMetadata {
174
231
  timestamp?: number;
@@ -195,8 +252,42 @@ export interface StreamStats {
195
252
  /**
196
253
  * When publishing a message to the stream, the configuration
197
254
  * can include a transaction object to execute the operation
198
- * atomically.
255
+ * atomically and/or a retry policy to control retry behavior.
199
256
  */
200
257
  export interface PublishMessageConfig {
201
258
  transaction?: ProviderTransaction;
259
+ /**
260
+ * Retry policy for this specific message.
261
+ * Overrides stream-level and app-level defaults.
262
+ *
263
+ * @example
264
+ * ```typescript
265
+ * await streamService.publishMessages('my-topic', [msg], {
266
+ * retryPolicy: {
267
+ * maximumAttempts: 10,
268
+ * backoffCoefficient: 2,
269
+ * maximumInterval: '600s',
270
+ * }
271
+ * });
272
+ * ```
273
+ */
274
+ retryPolicy?: RetryPolicy;
275
+ }
276
+ /**
277
+ * Notification consumer configuration for PostgreSQL stream provider.
278
+ * Manages notification-based message consumption with fallback polling.
279
+ */
280
+ export interface NotificationConsumer {
281
+ /** Name of the stream being consumed */
282
+ streamName: string;
283
+ /** Name of the consumer group */
284
+ groupName: string;
285
+ /** Unique name identifying this consumer */
286
+ consumerName: string;
287
+ /** Callback function invoked when messages are available */
288
+ callback: (messages: StreamMessage[]) => void;
289
+ /** Whether this consumer is actively listening for notifications */
290
+ isListening: boolean;
291
+ /** Timestamp of the last fallback check (used for periodic polling) */
292
+ lastFallbackCheck: number;
202
293
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hotmeshio/hotmesh",
3
- "version": "0.6.1",
3
+ "version": "0.7.0",
4
4
  "description": "Permanent-Memory Workflows & AI Agents",
5
5
  "main": "./build/index.js",
6
6
  "types": "./build/index.d.ts",
@@ -29,7 +29,7 @@
29
29
  "test:connect:nats": "NODE_ENV=test jest ./tests/unit/services/connector/providers/nats.test.ts --detectOpenHandles --forceExit --verbose",
30
30
  "test:memflow": "NODE_ENV=test jest ./tests/memflow/*/*.test.ts --detectOpenHandles --forceExit --verbose",
31
31
  "test:memflow:basic": "HMSH_LOGLEVEL=info NODE_ENV=test jest ./tests/memflow/basic/postgres.test.ts --detectOpenHandles --forceExit --verbose",
32
- "test:memflow:collision": "NODE_ENV=test jest ./tests/memflow/collision/*.test.ts --detectOpenHandles --forceExit --verbose",
32
+ "test:memflow:collision": "NODE_ENV=test jest ./tests/memflow/collision/postgres.test.ts --detectOpenHandles --forceExit --verbose",
33
33
  "test:memflow:fatal": "NODE_ENV=test jest ./tests/memflow/fatal/*.test.ts --detectOpenHandles --forceExit --verbose",
34
34
  "test:memflow:goodbye": "NODE_ENV=test HMSH_LOGLEVEL=debug jest ./tests/memflow/goodbye/postgres.test.ts --detectOpenHandles --forceExit --verbose",
35
35
  "test:memflow:interceptor": "NODE_ENV=test HMSH_LOGLEVEL=debug jest ./tests/memflow/interceptor/postgres.test.ts --detectOpenHandles --forceExit --verbose",
@@ -37,30 +37,32 @@
37
37
  "test:memflow:agent": "NODE_ENV=test HMSH_LOGLEVEL=debug jest ./tests/memflow/agent/postgres.test.ts --detectOpenHandles --forceExit --verbose",
38
38
  "test:memflow:hello": "HMSH_TELEMETRY=debug HMSH_LOGLEVEL=debug NODE_ENV=test jest ./tests/memflow/helloworld/postgres.test.ts --detectOpenHandles --forceExit --verbose",
39
39
  "test:memflow:hook": "NODE_ENV=test jest ./tests/memflow/hook/postgres.test.ts --detectOpenHandles --forceExit --verbose",
40
- "test:memflow:interrupt": "NODE_ENV=test jest ./tests/memflow/interrupt/postgres.test.ts --detectOpenHandles --forceExit --verbose",
41
- "test:memflow:loopactivity": "NODE_ENV=test jest ./tests/memflow/loopactivity/postgres.test.ts --detectOpenHandles --forceExit --verbose",
40
+ "test:memflow:interrupt": "NODE_ENV=test jest ./tests/memflow/interrupt/*.test.ts --detectOpenHandles --forceExit --verbose",
41
+ "test:memflow:loopactivity": "NODE_ENV=test jest ./tests/memflow/loopactivity/*.test.ts --detectOpenHandles --forceExit --verbose",
42
42
  "test:memflow:nested": "NODE_ENV=test jest ./tests/memflow/nested/postgres.test.ts --detectOpenHandles --forceExit --verbose",
43
43
  "test:memflow:pipeline": "NODE_ENV=test jest ./tests/memflow/pipeline/postgres.test.ts --detectOpenHandles --forceExit --verbose",
44
44
  "test:memflow:retry": "NODE_ENV=test jest ./tests/memflow/retry/postgres.test.ts --detectOpenHandles --forceExit --verbose",
45
+ "test:memflow:retrypolicy": "NODE_ENV=test jest ./tests/memflow/retry-policy/*.test.ts --detectOpenHandles --forceExit --verbose",
45
46
  "test:memflow:sleep": "NODE_ENV=test jest ./tests/memflow/sleep/postgres.test.ts --detectOpenHandles --forceExit --verbose",
46
47
  "test:memflow:signal": "NODE_ENV=test jest ./tests/memflow/signal/postgres.test.ts --detectOpenHandles --forceExit --verbose",
47
- "test:memflow:unknown": "NODE_ENV=test jest ./tests/memflow/unknown/postgres.test.ts --detectOpenHandles --forceExit --verbose",
48
+ "test:memflow:unknown": "NODE_ENV=test jest ./tests/memflow/unknown/*.test.ts --detectOpenHandles --forceExit --verbose",
48
49
  "test:cycle": "NODE_ENV=test jest ./tests/functional/cycle/*.test.ts --detectOpenHandles --forceExit --verbose",
49
50
  "test:functional": "NODE_ENV=test jest ./tests/functional/* --detectOpenHandles --forceExit --verbose",
50
51
  "test:emit": "NODE_ENV=test jest ./tests/functional/emit/*.test.ts --detectOpenHandles --forceExit --verbose",
51
52
  "test:pending": "NODE_ENV=test jest ./tests/functional/pending/index.test.ts --detectOpenHandles --forceExit --verbose",
52
53
  "test:hmsh": "NODE_ENV=test jest ./tests/functional/*.test.ts --detectOpenHandles --verbose --forceExit",
53
- "test:hook": "NODE_ENV=test jest ./tests/functional/hook/index.test.ts --detectOpenHandles --forceExit --verbose",
54
+ "test:hook": "NODE_ENV=test jest ./tests/functional/hook/postgres.test.ts --detectOpenHandles --forceExit --verbose",
54
55
  "test:interrupt": "NODE_ENV=test jest ./tests/functional/interrupt/*.test.ts --detectOpenHandles --forceExit --verbose",
55
56
  "test:parallel": "NODE_ENV=test jest ./tests/functional/parallel/index.test.ts --detectOpenHandles --forceExit --verbose",
56
57
  "test:pipe": "NODE_ENV=test jest ./tests/unit/services/pipe/index.test.ts --detectOpenHandles --forceExit --verbose",
57
- "test:quorum": "NODE_ENV=test jest ./tests/functional/quorum/*.test.ts --detectOpenHandles --forceExit --verbose",
58
+ "test:quorum": "NODE_ENV=test jest ./tests/functional/quorum/postgres.test.ts --detectOpenHandles --forceExit --verbose",
58
59
  "test:reclaim": "NODE_ENV=test jest ./tests/functional/reclaim/*.test.ts --detectOpenHandles --forceExit --verbose",
59
60
  "test:redeploy": "NODE_ENV=test jest ./tests/functional/redeploy/*.test.ts --detectOpenHandles --forceExit --verbose",
60
61
  "test:reporter": "NODE_ENV=test jest ./tests/unit/services/reporter/index.test.ts --detectOpenHandles --forceExit --verbose",
61
62
  "test:reentrant": "NODE_ENV=test jest ./tests/functional/reentrant/*.test.ts --detectOpenHandles --forceExit --verbose",
62
63
  "test:retry": "NODE_ENV=test jest ./tests/functional/retry/*.test.ts --detectOpenHandles --forceExit --verbose",
63
- "test:sequence": "NODE_ENV=test HMSH_LOGLEVEL=debug jest ./tests/functional/sequence/postgres.test.ts --detectOpenHandles --forceExit --verbose",
64
+ "test:retrypolicy": "NODE_ENV=test jest ./tests/functional/retry-policy/*.test.ts --detectOpenHandles --forceExit --verbose",
65
+ "test:sequence": "NODE_ENV=test HMSH_LOGLEVEL=debug jest ./tests/functional/sequence/*.test.ts --detectOpenHandles --forceExit --verbose",
64
66
  "test:signal": "NODE_ENV=test jest ./tests/functional/signal/*.test.ts --detectOpenHandles --forceExit --verbose",
65
67
  "test:status": "NODE_ENV=test jest ./tests/functional/status/index.test.ts --detectOpenHandles --forceExit --verbose",
66
68
  "test:providers": "NODE_ENV=test jest ./tests/functional/*/providers/*/*.test.ts --detectOpenHandles --forceExit --verbose",