@hotmeshio/hotmesh 0.6.1 → 0.8.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 (112) hide show
  1. package/.claude/settings.local.json +7 -0
  2. package/README.md +179 -142
  3. package/build/index.d.ts +1 -3
  4. package/build/index.js +1 -5
  5. package/build/modules/enums.d.ts +7 -0
  6. package/build/modules/enums.js +16 -1
  7. package/build/modules/utils.d.ts +27 -0
  8. package/build/modules/utils.js +55 -32
  9. package/build/package.json +18 -27
  10. package/build/services/activities/activity.d.ts +43 -6
  11. package/build/services/activities/activity.js +262 -54
  12. package/build/services/activities/await.js +2 -2
  13. package/build/services/activities/cycle.js +1 -1
  14. package/build/services/activities/hook.d.ts +5 -0
  15. package/build/services/activities/hook.js +22 -19
  16. package/build/services/activities/interrupt.js +17 -25
  17. package/build/services/activities/signal.d.ts +4 -2
  18. package/build/services/activities/signal.js +27 -24
  19. package/build/services/activities/worker.js +2 -2
  20. package/build/services/collator/index.d.ts +123 -25
  21. package/build/services/collator/index.js +224 -101
  22. package/build/services/connector/factory.d.ts +1 -1
  23. package/build/services/connector/factory.js +1 -11
  24. package/build/services/connector/providers/postgres.js +3 -0
  25. package/build/services/engine/index.d.ts +5 -5
  26. package/build/services/engine/index.js +36 -15
  27. package/build/services/hotmesh/index.d.ts +66 -15
  28. package/build/services/hotmesh/index.js +84 -15
  29. package/build/services/memflow/index.d.ts +100 -14
  30. package/build/services/memflow/index.js +100 -14
  31. package/build/services/memflow/worker.d.ts +97 -0
  32. package/build/services/memflow/worker.js +217 -0
  33. package/build/services/memflow/workflow/proxyActivities.d.ts +74 -3
  34. package/build/services/memflow/workflow/proxyActivities.js +81 -4
  35. package/build/services/router/consumption/index.d.ts +2 -1
  36. package/build/services/router/consumption/index.js +39 -3
  37. package/build/services/router/error-handling/index.d.ts +3 -3
  38. package/build/services/router/error-handling/index.js +48 -13
  39. package/build/services/router/index.d.ts +1 -0
  40. package/build/services/router/index.js +2 -1
  41. package/build/services/search/factory.js +1 -9
  42. package/build/services/store/factory.js +1 -9
  43. package/build/services/store/index.d.ts +8 -2
  44. package/build/services/store/providers/postgres/kvsql.d.ts +4 -0
  45. package/build/services/store/providers/postgres/kvsql.js +4 -0
  46. package/build/services/store/providers/postgres/kvtransaction.d.ts +2 -0
  47. package/build/services/store/providers/postgres/kvtransaction.js +23 -0
  48. package/build/services/store/providers/postgres/kvtypes/hash/basic.d.ts +51 -0
  49. package/build/services/store/providers/postgres/kvtypes/hash/basic.js +229 -7
  50. package/build/services/store/providers/postgres/kvtypes/hash/expire.js +12 -2
  51. package/build/services/store/providers/postgres/kvtypes/hash/index.d.ts +4 -0
  52. package/build/services/store/providers/postgres/kvtypes/hash/index.js +6 -0
  53. package/build/services/store/providers/postgres/kvtypes/hash/scan.js +30 -10
  54. package/build/services/store/providers/postgres/kvtypes/list.js +68 -10
  55. package/build/services/store/providers/postgres/kvtypes/string.js +60 -10
  56. package/build/services/store/providers/postgres/kvtypes/zset.js +92 -22
  57. package/build/services/store/providers/postgres/postgres.d.ts +23 -3
  58. package/build/services/store/providers/postgres/postgres.js +38 -1
  59. package/build/services/stream/factory.js +1 -17
  60. package/build/services/stream/providers/postgres/kvtables.js +76 -23
  61. package/build/services/stream/providers/postgres/lifecycle.d.ts +19 -0
  62. package/build/services/stream/providers/postgres/lifecycle.js +54 -0
  63. package/build/services/stream/providers/postgres/messages.d.ts +56 -0
  64. package/build/services/stream/providers/postgres/messages.js +253 -0
  65. package/build/services/stream/providers/postgres/notifications.d.ts +59 -0
  66. package/build/services/stream/providers/postgres/notifications.js +357 -0
  67. package/build/services/stream/providers/postgres/postgres.d.ts +110 -11
  68. package/build/services/stream/providers/postgres/postgres.js +196 -488
  69. package/build/services/stream/providers/postgres/scout.d.ts +68 -0
  70. package/build/services/stream/providers/postgres/scout.js +233 -0
  71. package/build/services/stream/providers/postgres/stats.d.ts +49 -0
  72. package/build/services/stream/providers/postgres/stats.js +113 -0
  73. package/build/services/sub/factory.js +1 -9
  74. package/build/services/sub/index.d.ts +1 -1
  75. package/build/services/sub/providers/postgres/postgres.d.ts +1 -1
  76. package/build/services/sub/providers/postgres/postgres.js +53 -6
  77. package/build/services/task/index.d.ts +1 -1
  78. package/build/services/task/index.js +2 -6
  79. package/build/services/worker/index.d.ts +1 -0
  80. package/build/services/worker/index.js +2 -0
  81. package/build/types/hotmesh.d.ts +42 -2
  82. package/build/types/index.d.ts +3 -4
  83. package/build/types/index.js +1 -4
  84. package/build/types/memflow.d.ts +32 -0
  85. package/build/types/provider.d.ts +17 -1
  86. package/build/types/stream.d.ts +92 -1
  87. package/index.ts +0 -4
  88. package/package.json +18 -27
  89. package/build/services/connector/providers/ioredis.d.ts +0 -9
  90. package/build/services/connector/providers/ioredis.js +0 -26
  91. package/build/services/connector/providers/redis.d.ts +0 -9
  92. package/build/services/connector/providers/redis.js +0 -38
  93. package/build/services/search/providers/redis/ioredis.d.ts +0 -23
  94. package/build/services/search/providers/redis/ioredis.js +0 -189
  95. package/build/services/search/providers/redis/redis.d.ts +0 -23
  96. package/build/services/search/providers/redis/redis.js +0 -202
  97. package/build/services/store/providers/redis/_base.d.ts +0 -137
  98. package/build/services/store/providers/redis/_base.js +0 -980
  99. package/build/services/store/providers/redis/ioredis.d.ts +0 -20
  100. package/build/services/store/providers/redis/ioredis.js +0 -180
  101. package/build/services/store/providers/redis/redis.d.ts +0 -18
  102. package/build/services/store/providers/redis/redis.js +0 -199
  103. package/build/services/stream/providers/redis/ioredis.d.ts +0 -61
  104. package/build/services/stream/providers/redis/ioredis.js +0 -272
  105. package/build/services/stream/providers/redis/redis.d.ts +0 -61
  106. package/build/services/stream/providers/redis/redis.js +0 -305
  107. package/build/services/sub/providers/redis/ioredis.d.ts +0 -20
  108. package/build/services/sub/providers/redis/ioredis.js +0 -150
  109. package/build/services/sub/providers/redis/redis.d.ts +0 -18
  110. package/build/services/sub/providers/redis/redis.js +0 -137
  111. package/build/types/redis.d.ts +0 -258
  112. package/build/types/redis.js +0 -11
@@ -4,6 +4,12 @@ import { HookRules } from './hook';
4
4
  import { StreamData, StreamDataResponse } from './stream';
5
5
  import { LogLevel } from './logger';
6
6
  import { ProviderClient, ProviderConfig, ProvidersConfig } from './provider';
7
+ /**
8
+ * Scout role types for distributed task processing.
9
+ * At any given time, only a single engine will hold a scout role
10
+ * to check for and process work items in the respective queues.
11
+ */
12
+ type ScoutType = 'time' | 'signal' | 'activate' | 'router';
7
13
  /**
8
14
  * the full set of entity types that are stored in the key/value store
9
15
  */
@@ -42,7 +48,7 @@ type KeyStoreParams = {
42
48
  facet?: string;
43
49
  topic?: string;
44
50
  timeValue?: number;
45
- scoutType?: 'signal' | 'time' | 'activate';
51
+ scoutType?: ScoutType;
46
52
  };
47
53
  type HotMesh = typeof HotMeshService;
48
54
  type HotMeshEngine = {
@@ -108,6 +114,23 @@ type HotMeshEngine = {
108
114
  * that share the same task queue and database configuration.
109
115
  */
110
116
  taskQueue?: string;
117
+ /**
118
+ * Retry policy for stream messages. Configures automatic retry
119
+ * behavior with exponential backoff for failed operations.
120
+ * Applied to the stream connection during initialization.
121
+ *
122
+ * @example
123
+ * ```typescript
124
+ * {
125
+ * retryPolicy: {
126
+ * maximumAttempts: 5,
127
+ * backoffCoefficient: 2,
128
+ * maximumInterval: '300s'
129
+ * }
130
+ * }
131
+ * ```
132
+ */
133
+ retryPolicy?: import('./stream').RetryPolicy;
111
134
  };
112
135
  type HotMeshWorker = {
113
136
  /**
@@ -175,6 +198,23 @@ type HotMeshWorker = {
175
198
  * that share the same task queue and database configuration.
176
199
  */
177
200
  taskQueue?: string;
201
+ /**
202
+ * Retry policy for stream messages. Configures automatic retry
203
+ * behavior with exponential backoff for failed operations.
204
+ * Applied to the stream connection during initialization.
205
+ *
206
+ * @example
207
+ * ```typescript
208
+ * {
209
+ * retryPolicy: {
210
+ * maximumAttempts: 5,
211
+ * backoffCoefficient: 2,
212
+ * maximumInterval: '300s'
213
+ * }
214
+ * }
215
+ * ```
216
+ */
217
+ retryPolicy?: import('./stream').RetryPolicy;
178
218
  };
179
219
  type HotMeshConfig = {
180
220
  appId: string;
@@ -266,4 +306,4 @@ type HotMeshApp = VersionedFields & {
266
306
  type HotMeshApps = {
267
307
  [appId: string]: HotMeshApp;
268
308
  };
269
- export { HotMesh, HotMeshEngine, HotMeshWorker, HotMeshSettings, HotMeshApp, HotMeshApps, HotMeshConfig, HotMeshManifest, HotMeshGraph, KeyType, KeyStoreParams, };
309
+ export { HotMesh, HotMeshEngine, HotMeshWorker, HotMeshSettings, HotMeshApp, HotMeshApps, HotMeshConfig, HotMeshManifest, HotMeshGraph, KeyType, KeyStoreParams, ScoutType, };
@@ -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';
@@ -17,10 +17,9 @@ export { MeshCallConnectParams, MeshCallExecParams, MeshCallCronParams, MeshCall
17
17
  export { PostgresClassType, PostgresClientOptions, PostgresClientType, PostgresConsumerGroup, PostgresPendingMessage, PostgresPoolClientType, PostgresQueryConfigType, PostgresQueryResultType, PostgresStreamMessage, PostgresStreamOptions, PostgresTransaction, } from './postgres';
18
18
  export { ActivateMessage, CronMessage, JobMessage, JobMessageCallback, PingMessage, PongMessage, QuorumMessage, QuorumMessageCallback, QuorumProfile, RollCallMessage, RollCallOptions, SubscriptionCallback, SubscriptionOptions, SystemHealth, ThrottleMessage, ThrottleOptions, WorkMessage, } from './quorum';
19
19
  export { NatsAckPolicy, NatsAckPolicyExplicitType, NatsClassType, NatsClientType, NatsClientOptions, NatsConsumerConfigType, NatsJetStreamManager, NatsConnection, NatsJetStreamType, NatsConnectionOptions, NatsConsumerConfig, NatsConsumerInfo, NatsConsumerManager, NatsDeliveryInfo, NatsJetStreamOptions, NatsError, NatsErrorType, NatsJetStreamClient, NatsJsMsg, NatsMessageType, NatsMsgExpect, NatsPubAck, NatsPubAckType, NatsPublishOptions, NatsRetentionPolicy, NatsRetentionPolicyWorkqueueType, NatsSequenceInfo, NatsStorageMemoryType, NatsStorageType, NatsStreamConfig, NatsStreamInfo, NatsStreamManager, NatsStreamConfigType, NatsStreamInfoType, NatsStreamOptions, NatsStreamState, NatsTransaction, } from './nats';
20
- export { RedisClass, RedisRedisClientType, RedisRedisClientOptions, RedisRedisClassType, IORedisClientType, RedisClient, RedisMulti, RedisRedisMultiType, IORedisClientOptions, IORedisClassType, IORedisMultiType, RedisOptions, isRedisClient, isIORedisClient, } from './redis';
21
20
  export { JSONSchema, StringAnyType, StringScalarType, StringStringType, SymbolMap, SymbolMaps, SymbolRanges, Symbols, SymbolSets, } from './serializer';
22
21
  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';
22
+ export { ReclaimedMessageType, RetryPolicy, RouterConfig, StreamCode, StreamConfig, StreamData, StreamDataType, StreamError, StreamDataResponse, StreamMessage, StreamMessageMetadata, StreamProviderType, StreamRetryPolicy, StreamRole, StreamStats, StreamStatus, PublishMessageConfig, } from './stream';
24
23
  export { context, Context, Counter, Meter, metrics, propagation, SpanContext, Span, SpanStatus, SpanStatusCode, SpanKind, trace, Tracer, ValueType, } from './telemetry';
25
24
  export { WorkListTaskType } from './task';
26
25
  export { TransitionMatch, TransitionRule, Transitions } from './transition';
@@ -1,15 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ValueType = exports.trace = exports.SpanKind = exports.SpanStatusCode = exports.propagation = exports.metrics = exports.context = exports.StreamStatus = exports.StreamRole = exports.StreamDataType = exports.isIORedisClient = exports.isRedisClient = exports.KeyType = exports.HookGate = exports.CollationFaultType = void 0;
3
+ exports.ValueType = exports.trace = exports.SpanKind = exports.SpanStatusCode = exports.propagation = exports.metrics = exports.context = exports.StreamStatus = exports.StreamRole = exports.StreamDataType = exports.KeyType = exports.HookGate = exports.CollationFaultType = void 0;
4
4
  var collator_1 = require("./collator");
5
5
  Object.defineProperty(exports, "CollationFaultType", { enumerable: true, get: function () { return collator_1.CollationFaultType; } });
6
6
  var hook_1 = require("./hook");
7
7
  Object.defineProperty(exports, "HookGate", { enumerable: true, get: function () { return hook_1.HookGate; } });
8
8
  var hotmesh_1 = require("./hotmesh");
9
9
  Object.defineProperty(exports, "KeyType", { enumerable: true, get: function () { return hotmesh_1.KeyType; } });
10
- var redis_1 = require("./redis");
11
- Object.defineProperty(exports, "isRedisClient", { enumerable: true, get: function () { return redis_1.isRedisClient; } });
12
- Object.defineProperty(exports, "isIORedisClient", { enumerable: true, get: function () { return redis_1.isIORedisClient; } });
13
10
  var stream_1 = require("./stream");
14
11
  Object.defineProperty(exports, "StreamDataType", { enumerable: true, get: function () { return stream_1.StreamDataType; } });
15
12
  Object.defineProperty(exports, "StreamRole", { enumerable: true, get: function () { return stream_1.StreamRole; } });
@@ -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) */
@@ -12,7 +12,7 @@ export interface ProviderClass {
12
12
  export interface ProviderOptions {
13
13
  [key: string]: any;
14
14
  }
15
- export type Providers = 'nats' | 'postgres' | 'redis' | 'ioredis';
15
+ export type Providers = 'nats' | 'postgres';
16
16
  /**
17
17
  * A provider transaction is a set of operations that are executed
18
18
  * atomically by the provider. The transaction is created by calling
@@ -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/index.ts CHANGED
@@ -16,17 +16,13 @@ import * as Enums from './modules/enums';
16
16
  import * as KeyStore from './modules/key';
17
17
  import { ConnectorService as Connector } from './services/connector/factory';
18
18
  import { PostgresConnection as ConnectorPostgres } from './services/connector/providers/postgres';
19
- import { RedisConnection as ConnectorIORedis } from './services/connector/providers/ioredis';
20
- import { RedisConnection as ConnectorRedis } from './services/connector/providers/redis';
21
19
  import { NatsConnection as ConnectorNATS } from './services/connector/providers/nats';
22
20
 
23
21
  export {
24
22
  //Provider Connectors
25
23
  Connector, //factory
26
- ConnectorIORedis,
27
24
  ConnectorNATS,
28
25
  ConnectorPostgres,
29
- ConnectorRedis,
30
26
 
31
27
  //Top-level Modules
32
28
  HotMesh,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hotmeshio/hotmesh",
3
- "version": "0.6.1",
3
+ "version": "0.8.0",
4
4
  "description": "Permanent-Memory Workflows & AI Agents",
5
5
  "main": "./build/index.js",
6
6
  "types": "./build/index.d.ts",
@@ -23,16 +23,15 @@
23
23
  "test:await": "NODE_ENV=test jest ./tests/functional/awaiter/postgres.test.ts --detectOpenHandles --forceExit --verbose",
24
24
  "test:compile": "NODE_ENV=test jest ./tests/functional/compile/index.test.ts --detectOpenHandles --forceExit --verbose",
25
25
  "test:connect": "NODE_ENV=test jest ./tests/unit/services/connector/* --detectOpenHandles --forceExit --verbose",
26
- "test:connect:ioredis": "NODE_ENV=test jest ./tests/unit/services/connector/providers/ioredis.test.ts --detectOpenHandles --forceExit --verbose",
27
26
  "test:connect:postgres": "NODE_ENV=test jest ./tests/unit/services/connector/providers/postgres.test.ts --detectOpenHandles --forceExit --verbose",
28
- "test:connect:redis": "NODE_ENV=test jest ./tests/unit/services/connector/providers/ioredis.test.ts --detectOpenHandles --forceExit --verbose",
29
27
  "test:connect:nats": "NODE_ENV=test jest ./tests/unit/services/connector/providers/nats.test.ts --detectOpenHandles --forceExit --verbose",
30
28
  "test:memflow": "NODE_ENV=test jest ./tests/memflow/*/*.test.ts --detectOpenHandles --forceExit --verbose",
29
+ "test:memflow:postgres": "HMSH_LOGLEVEL=info NODE_ENV=test jest ./tests/memflow/*/postgres.test.ts --detectOpenHandles --forceExit --verbose",
31
30
  "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",
31
+ "test:memflow:collision": "NODE_ENV=test jest ./tests/memflow/collision/postgres.test.ts --detectOpenHandles --forceExit --verbose",
33
32
  "test:memflow:fatal": "NODE_ENV=test jest ./tests/memflow/fatal/*.test.ts --detectOpenHandles --forceExit --verbose",
34
33
  "test:memflow:goodbye": "NODE_ENV=test HMSH_LOGLEVEL=debug jest ./tests/memflow/goodbye/postgres.test.ts --detectOpenHandles --forceExit --verbose",
35
- "test:memflow:interceptor": "NODE_ENV=test HMSH_LOGLEVEL=debug jest ./tests/memflow/interceptor/postgres.test.ts --detectOpenHandles --forceExit --verbose",
34
+ "test:memflow:interceptor": "NODE_ENV=test HMSH_LOGLEVEL=info jest ./tests/memflow/interceptor/postgres.test.ts --detectOpenHandles --forceExit --verbose",
36
35
  "test:memflow:entity": "NODE_ENV=test HMSH_LOGLEVEL=debug jest ./tests/memflow/entity/postgres.test.ts --detectOpenHandles --forceExit --verbose",
37
36
  "test:memflow:agent": "NODE_ENV=test HMSH_LOGLEVEL=debug jest ./tests/memflow/agent/postgres.test.ts --detectOpenHandles --forceExit --verbose",
38
37
  "test:memflow:hello": "HMSH_TELEMETRY=debug HMSH_LOGLEVEL=debug NODE_ENV=test jest ./tests/memflow/helloworld/postgres.test.ts --detectOpenHandles --forceExit --verbose",
@@ -42,37 +41,33 @@
42
41
  "test:memflow:nested": "NODE_ENV=test jest ./tests/memflow/nested/postgres.test.ts --detectOpenHandles --forceExit --verbose",
43
42
  "test:memflow:pipeline": "NODE_ENV=test jest ./tests/memflow/pipeline/postgres.test.ts --detectOpenHandles --forceExit --verbose",
44
43
  "test:memflow:retry": "NODE_ENV=test jest ./tests/memflow/retry/postgres.test.ts --detectOpenHandles --forceExit --verbose",
44
+ "test:memflow:retrypolicy": "NODE_ENV=test jest ./tests/memflow/retry-policy/*.test.ts --detectOpenHandles --forceExit --verbose",
45
45
  "test:memflow:sleep": "NODE_ENV=test jest ./tests/memflow/sleep/postgres.test.ts --detectOpenHandles --forceExit --verbose",
46
46
  "test:memflow:signal": "NODE_ENV=test jest ./tests/memflow/signal/postgres.test.ts --detectOpenHandles --forceExit --verbose",
47
47
  "test:memflow:unknown": "NODE_ENV=test jest ./tests/memflow/unknown/postgres.test.ts --detectOpenHandles --forceExit --verbose",
48
48
  "test:cycle": "NODE_ENV=test jest ./tests/functional/cycle/*.test.ts --detectOpenHandles --forceExit --verbose",
49
- "test:functional": "NODE_ENV=test jest ./tests/functional/* --detectOpenHandles --forceExit --verbose",
49
+ "test:functional": "NODE_ENV=test jest ./tests/functional/**/postgres.test.ts --detectOpenHandles --forceExit --verbose",
50
50
  "test:emit": "NODE_ENV=test jest ./tests/functional/emit/*.test.ts --detectOpenHandles --forceExit --verbose",
51
51
  "test:pending": "NODE_ENV=test jest ./tests/functional/pending/index.test.ts --detectOpenHandles --forceExit --verbose",
52
- "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:interrupt": "NODE_ENV=test jest ./tests/functional/interrupt/*.test.ts --detectOpenHandles --forceExit --verbose",
52
+ "test:hmsh": "NODE_ENV=test jest ./tests/functional/postgres.test.ts --detectOpenHandles --verbose --forceExit",
53
+ "test:hook": "NODE_ENV=test jest ./tests/functional/hook/postgres.test.ts --detectOpenHandles --forceExit --verbose",
54
+ "test:interrupt": "NODE_ENV=test jest ./tests/functional/interrupt/postgres.test.ts --detectOpenHandles --forceExit --verbose",
55
55
  "test:parallel": "NODE_ENV=test jest ./tests/functional/parallel/index.test.ts --detectOpenHandles --forceExit --verbose",
56
56
  "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:reclaim": "NODE_ENV=test jest ./tests/functional/reclaim/*.test.ts --detectOpenHandles --forceExit --verbose",
59
- "test:redeploy": "NODE_ENV=test jest ./tests/functional/redeploy/*.test.ts --detectOpenHandles --forceExit --verbose",
57
+ "test:quorum": "NODE_ENV=test jest ./tests/functional/quorum/postgres.test.ts --detectOpenHandles --forceExit --verbose",
58
+ "test:reclaim": "NODE_ENV=test jest ./tests/functional/reclaim/postgres.test.ts --detectOpenHandles --forceExit --verbose",
59
+ "test:redeploy": "NODE_ENV=test jest ./tests/functional/redeploy/postgres.test.ts --detectOpenHandles --forceExit --verbose",
60
60
  "test:reporter": "NODE_ENV=test jest ./tests/unit/services/reporter/index.test.ts --detectOpenHandles --forceExit --verbose",
61
- "test:reentrant": "NODE_ENV=test jest ./tests/functional/reentrant/*.test.ts --detectOpenHandles --forceExit --verbose",
62
- "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:signal": "NODE_ENV=test jest ./tests/functional/signal/*.test.ts --detectOpenHandles --forceExit --verbose",
61
+ "test:reentrant": "NODE_ENV=test jest ./tests/functional/reentrant/postgres.test.ts --detectOpenHandles --forceExit --verbose",
62
+ "test:retry": "NODE_ENV=test jest ./tests/functional/retry/postgres.test.ts --detectOpenHandles --forceExit --verbose",
63
+ "test:retrypolicy": "NODE_ENV=test jest ./tests/functional/retry-policy/*.test.ts --detectOpenHandles --forceExit --verbose",
64
+ "test:sequence": "NODE_ENV=test HMSH_LOGLEVEL=info jest ./tests/functional/sequence/postgres.test.ts --detectOpenHandles --forceExit --verbose",
65
+ "test:signal": "NODE_ENV=test jest ./tests/functional/signal/postgres.test.ts --detectOpenHandles --forceExit --verbose",
65
66
  "test:status": "NODE_ENV=test jest ./tests/functional/status/index.test.ts --detectOpenHandles --forceExit --verbose",
66
67
  "test:providers": "NODE_ENV=test jest ./tests/functional/*/providers/*/*.test.ts --detectOpenHandles --forceExit --verbose",
67
- "test:store:ioredis": "NODE_ENV=test jest ./tests/functional/store/providers/redis/ioredis.test.ts --detectOpenHandles --forceExit --verbose",
68
- "test:store:redis": "NODE_ENV=test jest ./tests/functional/store/providers/redis/redis.test.ts --detectOpenHandles --forceExit --verbose",
69
68
  "test:store:postgres": "NODE_ENV=test jest ./tests/functional/store/providers/postgres/postgres.test.ts --detectOpenHandles --forceExit --verbose",
70
- "test:stream:ioredis": "NODE_ENV=test jest ./tests/functional/stream/providers/redis/ioredis.test.ts --detectOpenHandles --forceExit --verbose",
71
- "test:stream:redis": "NODE_ENV=test jest ./tests/functional/stream/providers/redis/redis.test.ts --detectOpenHandles --forceExit --verbose",
72
69
  "test:stream:postgres": "NODE_ENV=test jest ./tests/functional/stream/providers/postgres/postgres.test.ts --detectOpenHandles --forceExit --verbose",
73
70
  "test:stream:nats": "NODE_ENV=test jest ./tests/functional/stream/providers/nats/nats.test.ts --detectOpenHandles --forceExit --verbose",
74
- "test:sub:ioredis": "NODE_ENV=test jest ./tests/functional/sub/providers/redis/ioredis.test.ts --detectOpenHandles --forceExit --verbose",
75
- "test:sub:redis": "NODE_ENV=test jest ./tests/functional/sub/providers/redis/redis.test.ts --detectOpenHandles --forceExit --verbose",
76
71
  "test:sub:postgres": "NODE_ENV=test jest ./tests/functional/sub/providers/postgres/postgres.test.ts --detectOpenHandles --forceExit --verbose",
77
72
  "test:sub:nats": "NODE_ENV=test jest ./tests/functional/sub/providers/nats/nats.test.ts --detectOpenHandles --forceExit --verbose",
78
73
  "test:trigger": "NODE_ENV=test jest ./tests/unit/services/activities/trigger.test.ts --detectOpenHandles --forceExit --verbose",
@@ -114,13 +109,11 @@
114
109
  "eslint-config-prettier": "^9.1.0",
115
110
  "eslint-plugin-import": "^2.29.1",
116
111
  "eslint-plugin-prettier": "^5.1.3",
117
- "ioredis": "^5.3.2",
118
112
  "javascript-obfuscator": "^0.6.2",
119
113
  "jest": "^29.5.0",
120
114
  "nats": "^2.28.0",
121
115
  "openai": "^5.9.0",
122
116
  "pg": "^8.10.0",
123
- "redis": "^4.6.13",
124
117
  "rimraf": "^4.4.1",
125
118
  "terser": "^5.37.0",
126
119
  "ts-jest": "^29.0.5",
@@ -130,9 +123,7 @@
130
123
  "typescript": "^5.0.4"
131
124
  },
132
125
  "peerDependencies": {
133
- "ioredis": "^4.0.0 || ^5.0.0",
134
126
  "nats": "^2.0.0",
135
- "pg": "^8.0.0",
136
- "redis": "^4.0.0"
127
+ "pg": "^8.0.0"
137
128
  }
138
129
  }
@@ -1,9 +0,0 @@
1
- import { AbstractConnection } from '..';
2
- import { IORedisClientOptions as RedisClientOptions, IORedisClassType as RedisClassType, IORedisClientType as RedisClientType } from '../../../types/redis';
3
- declare class RedisConnection extends AbstractConnection<RedisClassType, RedisClientOptions> {
4
- defaultOptions: RedisClientOptions;
5
- createConnection(Redis: RedisClassType, options: RedisClientOptions): Promise<RedisClientType>;
6
- getClient(): RedisClientType;
7
- closeConnection(connection: RedisClientType): Promise<void>;
8
- }
9
- export { RedisConnection };
@@ -1,26 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RedisConnection = void 0;
4
- const __1 = require("..");
5
- class RedisConnection extends __1.AbstractConnection {
6
- constructor() {
7
- super(...arguments);
8
- this.defaultOptions = {
9
- host: 'localhost',
10
- port: 6379,
11
- };
12
- }
13
- async createConnection(Redis, options) {
14
- return new Redis(options);
15
- }
16
- getClient() {
17
- if (!this.connection) {
18
- throw new Error('Redis client is not connected');
19
- }
20
- return this.connection;
21
- }
22
- async closeConnection(connection) {
23
- await connection.quit();
24
- }
25
- }
26
- exports.RedisConnection = RedisConnection;
@@ -1,9 +0,0 @@
1
- import { AbstractConnection } from '..';
2
- import { RedisRedisClassType as RedisClassType, RedisRedisClientType as RedisClientType, RedisRedisClientOptions as RedisClientOptions } from '../../../types/redis';
3
- declare class RedisConnection extends AbstractConnection<RedisClassType, RedisClientOptions> {
4
- defaultOptions: RedisClientOptions;
5
- createConnection(Redis: Partial<RedisClassType>, options: RedisClientOptions): Promise<Partial<RedisClientType>>;
6
- getClient(): RedisClientType;
7
- closeConnection(connection: any): Promise<void>;
8
- }
9
- export { RedisConnection, RedisClientType };
@@ -1,38 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RedisConnection = void 0;
4
- const __1 = require("..");
5
- class RedisConnection extends __1.AbstractConnection {
6
- constructor() {
7
- super(...arguments);
8
- this.defaultOptions = {
9
- socket: {
10
- host: 'localhost',
11
- port: 6379,
12
- tls: false,
13
- },
14
- };
15
- }
16
- async createConnection(Redis, options) {
17
- return new Promise((resolve, reject) => {
18
- const client = Redis.createClient(options);
19
- client.on('error', (error) => {
20
- reject(error);
21
- });
22
- client.on('ready', () => {
23
- resolve(client);
24
- });
25
- client.connect();
26
- });
27
- }
28
- getClient() {
29
- if (!this.connection) {
30
- throw new Error('Redis client is not connected');
31
- }
32
- return this.connection;
33
- }
34
- async closeConnection(connection) {
35
- await connection.quit();
36
- }
37
- }
38
- exports.RedisConnection = RedisConnection;
@@ -1,23 +0,0 @@
1
- import { SearchService } from '../../index';
2
- import { ILogger } from '../../../logger';
3
- import { IORedisClientType } from '../../../../types/redis';
4
- declare class IORedisSearchService extends SearchService<IORedisClientType> {
5
- constructor(searchClient: IORedisClientType, storeClient?: IORedisClientType);
6
- init(namespace: string, appId: string, logger: ILogger): Promise<void>;
7
- createSearchIndex(indexName: string, prefixes: string[], schema: string[]): Promise<void>;
8
- listSearchIndexes(): Promise<string[]>;
9
- updateContext(key: string, fields: Record<string, string>): Promise<any>;
10
- setFields(key: string, fields: Record<string, string>): Promise<number>;
11
- getField(key: string, field: string): Promise<string>;
12
- getFields(key: string, fields: string[]): Promise<string[]>;
13
- getAllFields(key: string): Promise<Record<string, string>>;
14
- deleteFields(key: string, fields: string[]): Promise<number>;
15
- incrementFieldByFloat(key: string, field: string, increment: number): Promise<number>;
16
- sendQuery(...query: [string, ...string[]]): Promise<any>;
17
- sendIndexedQuery(index: string, query: string[]): Promise<string[]>;
18
- findEntities(): Promise<any[]>;
19
- findEntityById(): Promise<any>;
20
- findEntitiesByCondition(): Promise<any[]>;
21
- createEntityIndex(): Promise<void>;
22
- }
23
- export { IORedisSearchService };