@hotmeshio/hotmesh 0.6.0 → 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.
- package/README.md +179 -142
- package/build/index.d.ts +3 -1
- package/build/index.js +5 -1
- package/build/modules/enums.d.ts +18 -0
- package/build/modules/enums.js +27 -1
- package/build/modules/utils.d.ts +27 -0
- package/build/modules/utils.js +79 -1
- package/build/package.json +24 -10
- package/build/services/connector/factory.d.ts +1 -1
- package/build/services/connector/factory.js +15 -1
- package/build/services/connector/providers/ioredis.d.ts +9 -0
- package/build/services/connector/providers/ioredis.js +26 -0
- package/build/services/connector/providers/postgres.js +3 -0
- package/build/services/connector/providers/redis.d.ts +9 -0
- package/build/services/connector/providers/redis.js +38 -0
- package/build/services/hotmesh/index.d.ts +66 -15
- package/build/services/hotmesh/index.js +84 -15
- package/build/services/memflow/index.d.ts +100 -14
- package/build/services/memflow/index.js +100 -14
- package/build/services/memflow/worker.d.ts +97 -0
- package/build/services/memflow/worker.js +217 -0
- package/build/services/memflow/workflow/proxyActivities.d.ts +74 -3
- package/build/services/memflow/workflow/proxyActivities.js +81 -4
- package/build/services/router/consumption/index.d.ts +2 -1
- package/build/services/router/consumption/index.js +38 -2
- package/build/services/router/error-handling/index.d.ts +3 -3
- package/build/services/router/error-handling/index.js +48 -13
- package/build/services/router/index.d.ts +1 -0
- package/build/services/router/index.js +2 -1
- package/build/services/search/factory.js +8 -0
- package/build/services/search/providers/redis/ioredis.d.ts +23 -0
- package/build/services/search/providers/redis/ioredis.js +189 -0
- package/build/services/search/providers/redis/redis.d.ts +23 -0
- package/build/services/search/providers/redis/redis.js +202 -0
- package/build/services/store/factory.js +9 -1
- package/build/services/store/index.d.ts +3 -2
- package/build/services/store/providers/postgres/kvtypes/hash/basic.js +36 -6
- package/build/services/store/providers/postgres/kvtypes/hash/expire.js +12 -2
- package/build/services/store/providers/postgres/kvtypes/hash/scan.js +30 -10
- package/build/services/store/providers/postgres/kvtypes/list.js +68 -10
- package/build/services/store/providers/postgres/kvtypes/string.js +60 -10
- package/build/services/store/providers/postgres/kvtypes/zset.js +92 -22
- package/build/services/store/providers/postgres/postgres.d.ts +3 -3
- package/build/services/store/providers/redis/_base.d.ts +137 -0
- package/build/services/store/providers/redis/_base.js +980 -0
- package/build/services/store/providers/redis/ioredis.d.ts +20 -0
- package/build/services/store/providers/redis/ioredis.js +190 -0
- package/build/services/store/providers/redis/redis.d.ts +18 -0
- package/build/services/store/providers/redis/redis.js +199 -0
- package/build/services/stream/factory.js +17 -1
- package/build/services/stream/providers/postgres/kvtables.js +76 -23
- package/build/services/stream/providers/postgres/lifecycle.d.ts +19 -0
- package/build/services/stream/providers/postgres/lifecycle.js +54 -0
- package/build/services/stream/providers/postgres/messages.d.ts +56 -0
- package/build/services/stream/providers/postgres/messages.js +253 -0
- package/build/services/stream/providers/postgres/notifications.d.ts +59 -0
- package/build/services/stream/providers/postgres/notifications.js +357 -0
- package/build/services/stream/providers/postgres/postgres.d.ts +110 -11
- package/build/services/stream/providers/postgres/postgres.js +196 -488
- package/build/services/stream/providers/postgres/scout.d.ts +68 -0
- package/build/services/stream/providers/postgres/scout.js +233 -0
- package/build/services/stream/providers/postgres/stats.d.ts +49 -0
- package/build/services/stream/providers/postgres/stats.js +113 -0
- package/build/services/stream/providers/redis/ioredis.d.ts +61 -0
- package/build/services/stream/providers/redis/ioredis.js +272 -0
- package/build/services/stream/providers/redis/redis.d.ts +61 -0
- package/build/services/stream/providers/redis/redis.js +305 -0
- package/build/services/sub/factory.js +8 -0
- package/build/services/sub/providers/postgres/postgres.js +37 -5
- package/build/services/sub/providers/redis/ioredis.d.ts +20 -0
- package/build/services/sub/providers/redis/ioredis.js +161 -0
- package/build/services/sub/providers/redis/redis.d.ts +18 -0
- package/build/services/sub/providers/redis/redis.js +148 -0
- package/build/services/worker/index.d.ts +1 -0
- package/build/services/worker/index.js +2 -0
- package/build/types/hotmesh.d.ts +42 -2
- package/build/types/index.d.ts +4 -3
- package/build/types/index.js +4 -1
- package/build/types/memflow.d.ts +32 -0
- package/build/types/provider.d.ts +17 -1
- package/build/types/redis.d.ts +258 -0
- package/build/types/redis.js +11 -0
- package/build/types/stream.d.ts +92 -1
- package/index.ts +4 -0
- package/package.json +24 -10
package/build/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hotmeshio/hotmesh",
|
|
3
|
-
"version": "0.
|
|
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",
|
|
@@ -23,11 +23,13 @@
|
|
|
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",
|
|
26
27
|
"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",
|
|
27
29
|
"test:connect:nats": "NODE_ENV=test jest ./tests/unit/services/connector/providers/nats.test.ts --detectOpenHandles --forceExit --verbose",
|
|
28
|
-
"test:memflow": "NODE_ENV=test jest ./tests/memflow
|
|
30
|
+
"test:memflow": "NODE_ENV=test jest ./tests/memflow/*/*.test.ts --detectOpenHandles --forceExit --verbose",
|
|
29
31
|
"test:memflow:basic": "HMSH_LOGLEVEL=info NODE_ENV=test jest ./tests/memflow/basic/postgres.test.ts --detectOpenHandles --forceExit --verbose",
|
|
30
|
-
"test:memflow:collision": "NODE_ENV=test jest ./tests/memflow/collision
|
|
32
|
+
"test:memflow:collision": "NODE_ENV=test jest ./tests/memflow/collision/postgres.test.ts --detectOpenHandles --forceExit --verbose",
|
|
31
33
|
"test:memflow:fatal": "NODE_ENV=test jest ./tests/memflow/fatal/*.test.ts --detectOpenHandles --forceExit --verbose",
|
|
32
34
|
"test:memflow:goodbye": "NODE_ENV=test HMSH_LOGLEVEL=debug jest ./tests/memflow/goodbye/postgres.test.ts --detectOpenHandles --forceExit --verbose",
|
|
33
35
|
"test:memflow:interceptor": "NODE_ENV=test HMSH_LOGLEVEL=debug jest ./tests/memflow/interceptor/postgres.test.ts --detectOpenHandles --forceExit --verbose",
|
|
@@ -35,36 +37,44 @@
|
|
|
35
37
|
"test:memflow:agent": "NODE_ENV=test HMSH_LOGLEVEL=debug jest ./tests/memflow/agent/postgres.test.ts --detectOpenHandles --forceExit --verbose",
|
|
36
38
|
"test:memflow:hello": "HMSH_TELEMETRY=debug HMSH_LOGLEVEL=debug NODE_ENV=test jest ./tests/memflow/helloworld/postgres.test.ts --detectOpenHandles --forceExit --verbose",
|
|
37
39
|
"test:memflow:hook": "NODE_ENV=test jest ./tests/memflow/hook/postgres.test.ts --detectOpenHandles --forceExit --verbose",
|
|
38
|
-
"test:memflow:interrupt": "NODE_ENV=test jest ./tests/memflow/interrupt
|
|
39
|
-
"test:memflow:loopactivity": "NODE_ENV=test jest ./tests/memflow/loopactivity
|
|
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",
|
|
40
42
|
"test:memflow:nested": "NODE_ENV=test jest ./tests/memflow/nested/postgres.test.ts --detectOpenHandles --forceExit --verbose",
|
|
41
43
|
"test:memflow:pipeline": "NODE_ENV=test jest ./tests/memflow/pipeline/postgres.test.ts --detectOpenHandles --forceExit --verbose",
|
|
42
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",
|
|
43
46
|
"test:memflow:sleep": "NODE_ENV=test jest ./tests/memflow/sleep/postgres.test.ts --detectOpenHandles --forceExit --verbose",
|
|
44
47
|
"test:memflow:signal": "NODE_ENV=test jest ./tests/memflow/signal/postgres.test.ts --detectOpenHandles --forceExit --verbose",
|
|
45
|
-
"test:memflow:unknown": "NODE_ENV=test jest ./tests/memflow/unknown
|
|
48
|
+
"test:memflow:unknown": "NODE_ENV=test jest ./tests/memflow/unknown/*.test.ts --detectOpenHandles --forceExit --verbose",
|
|
46
49
|
"test:cycle": "NODE_ENV=test jest ./tests/functional/cycle/*.test.ts --detectOpenHandles --forceExit --verbose",
|
|
47
50
|
"test:functional": "NODE_ENV=test jest ./tests/functional/* --detectOpenHandles --forceExit --verbose",
|
|
48
51
|
"test:emit": "NODE_ENV=test jest ./tests/functional/emit/*.test.ts --detectOpenHandles --forceExit --verbose",
|
|
49
52
|
"test:pending": "NODE_ENV=test jest ./tests/functional/pending/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
50
53
|
"test:hmsh": "NODE_ENV=test jest ./tests/functional/*.test.ts --detectOpenHandles --verbose --forceExit",
|
|
51
|
-
"test:hook": "NODE_ENV=test jest ./tests/functional/hook/
|
|
54
|
+
"test:hook": "NODE_ENV=test jest ./tests/functional/hook/postgres.test.ts --detectOpenHandles --forceExit --verbose",
|
|
52
55
|
"test:interrupt": "NODE_ENV=test jest ./tests/functional/interrupt/*.test.ts --detectOpenHandles --forceExit --verbose",
|
|
53
56
|
"test:parallel": "NODE_ENV=test jest ./tests/functional/parallel/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
54
57
|
"test:pipe": "NODE_ENV=test jest ./tests/unit/services/pipe/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
55
|
-
"test:quorum": "NODE_ENV=test jest ./tests/functional/quorum
|
|
58
|
+
"test:quorum": "NODE_ENV=test jest ./tests/functional/quorum/postgres.test.ts --detectOpenHandles --forceExit --verbose",
|
|
56
59
|
"test:reclaim": "NODE_ENV=test jest ./tests/functional/reclaim/*.test.ts --detectOpenHandles --forceExit --verbose",
|
|
57
60
|
"test:redeploy": "NODE_ENV=test jest ./tests/functional/redeploy/*.test.ts --detectOpenHandles --forceExit --verbose",
|
|
58
61
|
"test:reporter": "NODE_ENV=test jest ./tests/unit/services/reporter/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
59
62
|
"test:reentrant": "NODE_ENV=test jest ./tests/functional/reentrant/*.test.ts --detectOpenHandles --forceExit --verbose",
|
|
60
63
|
"test:retry": "NODE_ENV=test jest ./tests/functional/retry/*.test.ts --detectOpenHandles --forceExit --verbose",
|
|
61
|
-
"test:
|
|
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",
|
|
62
66
|
"test:signal": "NODE_ENV=test jest ./tests/functional/signal/*.test.ts --detectOpenHandles --forceExit --verbose",
|
|
63
67
|
"test:status": "NODE_ENV=test jest ./tests/functional/status/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
64
68
|
"test:providers": "NODE_ENV=test jest ./tests/functional/*/providers/*/*.test.ts --detectOpenHandles --forceExit --verbose",
|
|
69
|
+
"test:store:ioredis": "NODE_ENV=test jest ./tests/functional/store/providers/redis/ioredis.test.ts --detectOpenHandles --forceExit --verbose",
|
|
70
|
+
"test:store:redis": "NODE_ENV=test jest ./tests/functional/store/providers/redis/redis.test.ts --detectOpenHandles --forceExit --verbose",
|
|
65
71
|
"test:store:postgres": "NODE_ENV=test jest ./tests/functional/store/providers/postgres/postgres.test.ts --detectOpenHandles --forceExit --verbose",
|
|
72
|
+
"test:stream:ioredis": "NODE_ENV=test jest ./tests/functional/stream/providers/redis/ioredis.test.ts --detectOpenHandles --forceExit --verbose",
|
|
73
|
+
"test:stream:redis": "NODE_ENV=test jest ./tests/functional/stream/providers/redis/redis.test.ts --detectOpenHandles --forceExit --verbose",
|
|
66
74
|
"test:stream:postgres": "NODE_ENV=test jest ./tests/functional/stream/providers/postgres/postgres.test.ts --detectOpenHandles --forceExit --verbose",
|
|
67
75
|
"test:stream:nats": "NODE_ENV=test jest ./tests/functional/stream/providers/nats/nats.test.ts --detectOpenHandles --forceExit --verbose",
|
|
76
|
+
"test:sub:ioredis": "NODE_ENV=test jest ./tests/functional/sub/providers/redis/ioredis.test.ts --detectOpenHandles --forceExit --verbose",
|
|
77
|
+
"test:sub:redis": "NODE_ENV=test jest ./tests/functional/sub/providers/redis/redis.test.ts --detectOpenHandles --forceExit --verbose",
|
|
68
78
|
"test:sub:postgres": "NODE_ENV=test jest ./tests/functional/sub/providers/postgres/postgres.test.ts --detectOpenHandles --forceExit --verbose",
|
|
69
79
|
"test:sub:nats": "NODE_ENV=test jest ./tests/functional/sub/providers/nats/nats.test.ts --detectOpenHandles --forceExit --verbose",
|
|
70
80
|
"test:trigger": "NODE_ENV=test jest ./tests/unit/services/activities/trigger.test.ts --detectOpenHandles --forceExit --verbose",
|
|
@@ -106,11 +116,13 @@
|
|
|
106
116
|
"eslint-config-prettier": "^9.1.0",
|
|
107
117
|
"eslint-plugin-import": "^2.29.1",
|
|
108
118
|
"eslint-plugin-prettier": "^5.1.3",
|
|
119
|
+
"ioredis": "^5.3.2",
|
|
109
120
|
"javascript-obfuscator": "^0.6.2",
|
|
110
121
|
"jest": "^29.5.0",
|
|
111
122
|
"nats": "^2.28.0",
|
|
112
123
|
"openai": "^5.9.0",
|
|
113
124
|
"pg": "^8.10.0",
|
|
125
|
+
"redis": "^4.6.13",
|
|
114
126
|
"rimraf": "^4.4.1",
|
|
115
127
|
"terser": "^5.37.0",
|
|
116
128
|
"ts-jest": "^29.0.5",
|
|
@@ -120,7 +132,9 @@
|
|
|
120
132
|
"typescript": "^5.0.4"
|
|
121
133
|
},
|
|
122
134
|
"peerDependencies": {
|
|
135
|
+
"ioredis": "^4.0.0 || ^5.0.0",
|
|
123
136
|
"nats": "^2.0.0",
|
|
124
|
-
"pg": "^8.0.0"
|
|
137
|
+
"pg": "^8.0.0",
|
|
138
|
+
"redis": "^4.0.0"
|
|
125
139
|
}
|
|
126
140
|
}
|
|
@@ -3,7 +3,7 @@ import { ProviderConfig, ProviderNativeClient } from '../../types/provider';
|
|
|
3
3
|
export declare class ConnectorService {
|
|
4
4
|
static disconnectAll(): Promise<void>;
|
|
5
5
|
/**
|
|
6
|
-
* Connect to a provider (
|
|
6
|
+
* Connect to a provider (redis, nats, postgres) and return the native
|
|
7
7
|
* client. Connections are handled by the engine and worker routers at
|
|
8
8
|
* initialization, but the factory method provided here is useful
|
|
9
9
|
* for testing provider configurations.
|
|
@@ -2,15 +2,19 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ConnectorService = void 0;
|
|
4
4
|
const utils_1 = require("../../modules/utils");
|
|
5
|
+
const ioredis_1 = require("./providers/ioredis");
|
|
5
6
|
const nats_1 = require("./providers/nats");
|
|
6
7
|
const postgres_1 = require("./providers/postgres");
|
|
8
|
+
const redis_1 = require("./providers/redis");
|
|
7
9
|
class ConnectorService {
|
|
8
10
|
static async disconnectAll() {
|
|
11
|
+
await redis_1.RedisConnection.disconnectAll();
|
|
12
|
+
await ioredis_1.RedisConnection.disconnectAll();
|
|
9
13
|
await postgres_1.PostgresConnection.disconnectAll();
|
|
10
14
|
await nats_1.NatsConnection.disconnectAll();
|
|
11
15
|
}
|
|
12
16
|
/**
|
|
13
|
-
* Connect to a provider (
|
|
17
|
+
* Connect to a provider (redis, nats, postgres) and return the native
|
|
14
18
|
* client. Connections are handled by the engine and worker routers at
|
|
15
19
|
* initialization, but the factory method provided here is useful
|
|
16
20
|
* for testing provider configurations.
|
|
@@ -69,10 +73,20 @@ class ConnectorService {
|
|
|
69
73
|
const providerClass = ProviderConfig.class;
|
|
70
74
|
const options = ProviderConfig.options;
|
|
71
75
|
const providerName = ProviderConfig.provider || (0, utils_1.identifyProvider)(providerClass); //e.g. 'postgres.poolclient'
|
|
76
|
+
if (!providerName) {
|
|
77
|
+
throw new Error(`Unable to identify provider type. Please explicitly set the 'provider' field in your connection config. ` +
|
|
78
|
+
`Received class: ${providerClass?.constructor?.name || 'unknown'}`);
|
|
79
|
+
}
|
|
72
80
|
const providerType = providerName.split('.')[0]; //e.g. 'postgres'
|
|
73
81
|
let clientInstance;
|
|
74
82
|
const id = (0, utils_1.guid)();
|
|
75
83
|
switch (providerType) {
|
|
84
|
+
case 'redis':
|
|
85
|
+
clientInstance = await redis_1.RedisConnection.connect(id, providerClass, options, { provider: providerName });
|
|
86
|
+
break;
|
|
87
|
+
case 'ioredis':
|
|
88
|
+
clientInstance = await ioredis_1.RedisConnection.connect(id, providerClass, options, { provider: providerName });
|
|
89
|
+
break;
|
|
76
90
|
case 'nats':
|
|
77
91
|
clientInstance = await nats_1.NatsConnection.connect(id, providerClass, options, { provider: providerName });
|
|
78
92
|
break;
|
|
@@ -0,0 +1,9 @@
|
|
|
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 };
|
|
@@ -0,0 +1,26 @@
|
|
|
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;
|
|
@@ -121,7 +121,10 @@ class PostgresConnection extends __1.AbstractConnection {
|
|
|
121
121
|
this.disconnecting = true;
|
|
122
122
|
await this.disconnectPoolClients();
|
|
123
123
|
await this.disconnectConnections();
|
|
124
|
+
// Clear taskQueue connections cache when disconnecting all
|
|
124
125
|
this.taskQueueConnections.clear();
|
|
126
|
+
// Clear the base class instances cache to allow reconnection with same IDs
|
|
127
|
+
this.instances.clear();
|
|
125
128
|
this.disconnecting = false;
|
|
126
129
|
}
|
|
127
130
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
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 };
|
|
@@ -0,0 +1,38 @@
|
|
|
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;
|
|
@@ -10,30 +10,19 @@ import { StringAnyType, StringStringType } from '../../types/serializer';
|
|
|
10
10
|
import { JobStatsInput, GetStatsOptions, IdsResponse, StatsResponse } from '../../types/stats';
|
|
11
11
|
import { StreamCode, StreamData, StreamDataResponse, StreamStatus } from '../../types/stream';
|
|
12
12
|
/**
|
|
13
|
-
* HotMesh
|
|
14
|
-
* Postgres into a resilient service mesh capable of running
|
|
13
|
+
* HotMesh transforms Postgres into a durable workflow orchestration engine capable of running
|
|
15
14
|
* fault-tolerant workflows across multiple services and systems.
|
|
16
15
|
*
|
|
17
|
-
* ## Core Concepts
|
|
18
|
-
*
|
|
19
|
-
* **Distributed Quorum Architecture**: HotMesh operates as a distributed quorum
|
|
20
|
-
* where multiple engine and worker instances coordinate using CQRS principles.
|
|
21
|
-
* Each member reads from assigned topic queues and writes results to other queues,
|
|
22
|
-
* creating emergent workflow orchestration without a central controller.
|
|
23
|
-
*
|
|
24
|
-
* **Reentrant Process Engine**: Unlike traditional workflow engines, HotMesh
|
|
25
|
-
* provides built-in retry logic, idempotency, and failure recovery. Your business
|
|
26
|
-
* logic doesn't need to handle timeouts or retries - the engine manages all of that.
|
|
27
|
-
*
|
|
28
16
|
* ## Key Features
|
|
29
17
|
*
|
|
30
|
-
* - **Fault Tolerance**: Automatic retry
|
|
18
|
+
* - **Fault Tolerance**: Automatic retry with exponential backoff and configurable policies
|
|
31
19
|
* - **Distributed Execution**: No single point of failure
|
|
32
20
|
* - **YAML-Driven**: Model-driven development with declarative workflow definitions
|
|
33
21
|
* - **OpenTelemetry**: Built-in observability and tracing
|
|
34
22
|
* - **Durable State**: Workflow state persists across system restarts
|
|
35
23
|
* - **Pattern Matching**: Pub/sub with wildcard pattern support
|
|
36
24
|
* - **Throttling**: Dynamic flow control and backpressure management
|
|
25
|
+
* - **Retry Policies**: PostgreSQL-native retry configuration with exponential backoff
|
|
37
26
|
*
|
|
38
27
|
* ## Architecture
|
|
39
28
|
*
|
|
@@ -225,7 +214,12 @@ declare class HotMesh {
|
|
|
225
214
|
* similarly to the engine, but as an array with
|
|
226
215
|
* multiple worker objects.
|
|
227
216
|
*
|
|
228
|
-
*
|
|
217
|
+
* ## Retry Policy Configuration
|
|
218
|
+
*
|
|
219
|
+
* HotMesh supports robust retry policies with exponential backoff for PostgreSQL.
|
|
220
|
+
* Configure retry behavior at the stream level for automatic fault tolerance.
|
|
221
|
+
*
|
|
222
|
+
* @example Basic Configuration
|
|
229
223
|
* ```typescript
|
|
230
224
|
* const config: HotMeshConfig = {
|
|
231
225
|
* appId: 'myapp',
|
|
@@ -241,6 +235,57 @@ declare class HotMesh {
|
|
|
241
235
|
* };
|
|
242
236
|
* const hotMesh = await HotMesh.init(config);
|
|
243
237
|
* ```
|
|
238
|
+
*
|
|
239
|
+
* @example With Retry Policy (PostgreSQL)
|
|
240
|
+
* ```typescript
|
|
241
|
+
* import { HotMesh } from '@hotmeshio/hotmesh';
|
|
242
|
+
* import { Client as Postgres } from 'pg';
|
|
243
|
+
*
|
|
244
|
+
* const hotMesh = await HotMesh.init({
|
|
245
|
+
* appId: 'my-app',
|
|
246
|
+
* engine: {
|
|
247
|
+
* connection: {
|
|
248
|
+
* class: Postgres,
|
|
249
|
+
* options: { connectionString: 'postgresql://...' }
|
|
250
|
+
* },
|
|
251
|
+
* // Default retry policy for engine streams
|
|
252
|
+
* retryPolicy: {
|
|
253
|
+
* maximumAttempts: 5, // Retry up to 5 times
|
|
254
|
+
* backoffCoefficient: 2, // Exponential: 2^0, 2^1, 2^2...
|
|
255
|
+
* maximumInterval: '300s' // Cap delay at 5 minutes
|
|
256
|
+
* }
|
|
257
|
+
* },
|
|
258
|
+
* workers: [{
|
|
259
|
+
* topic: 'order.process',
|
|
260
|
+
* connection: {
|
|
261
|
+
* class: Postgres,
|
|
262
|
+
* options: { connectionString: 'postgresql://...' }
|
|
263
|
+
* },
|
|
264
|
+
* // Worker-specific retry policy
|
|
265
|
+
* retryPolicy: {
|
|
266
|
+
* maximumAttempts: 10,
|
|
267
|
+
* backoffCoefficient: 1.5,
|
|
268
|
+
* maximumInterval: '600s'
|
|
269
|
+
* },
|
|
270
|
+
* callback: async (data) => {
|
|
271
|
+
* // Your business logic here
|
|
272
|
+
* // Failures will automatically retry with exponential backoff
|
|
273
|
+
* return { status: 'success', data: processedData };
|
|
274
|
+
* }
|
|
275
|
+
* }]
|
|
276
|
+
* });
|
|
277
|
+
* ```
|
|
278
|
+
*
|
|
279
|
+
* **Retry Policy Options**:
|
|
280
|
+
* - `maximumAttempts` - Maximum retry attempts before failure (default: 3)
|
|
281
|
+
* - `backoffCoefficient` - Base for exponential backoff calculation (default: 10)
|
|
282
|
+
* - `maximumInterval` - Maximum delay between retries in seconds or duration string (default: '120s')
|
|
283
|
+
*
|
|
284
|
+
* **Retry Delays**: For `backoffCoefficient: 2`, delays are: 2s, 4s, 8s, 16s, 32s...
|
|
285
|
+
* capped at `maximumInterval`.
|
|
286
|
+
*
|
|
287
|
+
* **Note**: Retry policies are stored in PostgreSQL columns for efficient querying and
|
|
288
|
+
* observability. Each retry creates a new message, preserving message immutability.
|
|
244
289
|
*/
|
|
245
290
|
static init(config: HotMeshConfig): Promise<HotMesh>;
|
|
246
291
|
/**
|
|
@@ -272,6 +317,12 @@ declare class HotMesh {
|
|
|
272
317
|
* @private
|
|
273
318
|
*/
|
|
274
319
|
private initTaskQueue;
|
|
320
|
+
/**
|
|
321
|
+
* Apply retry policy to the stream connection within a ProviderConfig or ProvidersConfig.
|
|
322
|
+
* Handles both short-form (ProviderConfig) and long-form (ProvidersConfig) connection configs.
|
|
323
|
+
* @private
|
|
324
|
+
*/
|
|
325
|
+
private applyRetryPolicy;
|
|
275
326
|
/**
|
|
276
327
|
* Starts a workflow
|
|
277
328
|
* @example
|
|
@@ -11,30 +11,19 @@ const router_1 = require("../router");
|
|
|
11
11
|
const worker_1 = require("../worker");
|
|
12
12
|
const enums_1 = require("../../modules/enums");
|
|
13
13
|
/**
|
|
14
|
-
* HotMesh
|
|
15
|
-
* Postgres into a resilient service mesh capable of running
|
|
14
|
+
* HotMesh transforms Postgres into a durable workflow orchestration engine capable of running
|
|
16
15
|
* fault-tolerant workflows across multiple services and systems.
|
|
17
16
|
*
|
|
18
|
-
* ## Core Concepts
|
|
19
|
-
*
|
|
20
|
-
* **Distributed Quorum Architecture**: HotMesh operates as a distributed quorum
|
|
21
|
-
* where multiple engine and worker instances coordinate using CQRS principles.
|
|
22
|
-
* Each member reads from assigned topic queues and writes results to other queues,
|
|
23
|
-
* creating emergent workflow orchestration without a central controller.
|
|
24
|
-
*
|
|
25
|
-
* **Reentrant Process Engine**: Unlike traditional workflow engines, HotMesh
|
|
26
|
-
* provides built-in retry logic, idempotency, and failure recovery. Your business
|
|
27
|
-
* logic doesn't need to handle timeouts or retries - the engine manages all of that.
|
|
28
|
-
*
|
|
29
17
|
* ## Key Features
|
|
30
18
|
*
|
|
31
|
-
* - **Fault Tolerance**: Automatic retry
|
|
19
|
+
* - **Fault Tolerance**: Automatic retry with exponential backoff and configurable policies
|
|
32
20
|
* - **Distributed Execution**: No single point of failure
|
|
33
21
|
* - **YAML-Driven**: Model-driven development with declarative workflow definitions
|
|
34
22
|
* - **OpenTelemetry**: Built-in observability and tracing
|
|
35
23
|
* - **Durable State**: Workflow state persists across system restarts
|
|
36
24
|
* - **Pattern Matching**: Pub/sub with wildcard pattern support
|
|
37
25
|
* - **Throttling**: Dynamic flow control and backpressure management
|
|
26
|
+
* - **Retry Policies**: PostgreSQL-native retry configuration with exponential backoff
|
|
38
27
|
*
|
|
39
28
|
* ## Architecture
|
|
40
29
|
*
|
|
@@ -229,7 +218,12 @@ class HotMesh {
|
|
|
229
218
|
* similarly to the engine, but as an array with
|
|
230
219
|
* multiple worker objects.
|
|
231
220
|
*
|
|
232
|
-
*
|
|
221
|
+
* ## Retry Policy Configuration
|
|
222
|
+
*
|
|
223
|
+
* HotMesh supports robust retry policies with exponential backoff for PostgreSQL.
|
|
224
|
+
* Configure retry behavior at the stream level for automatic fault tolerance.
|
|
225
|
+
*
|
|
226
|
+
* @example Basic Configuration
|
|
233
227
|
* ```typescript
|
|
234
228
|
* const config: HotMeshConfig = {
|
|
235
229
|
* appId: 'myapp',
|
|
@@ -245,6 +239,57 @@ class HotMesh {
|
|
|
245
239
|
* };
|
|
246
240
|
* const hotMesh = await HotMesh.init(config);
|
|
247
241
|
* ```
|
|
242
|
+
*
|
|
243
|
+
* @example With Retry Policy (PostgreSQL)
|
|
244
|
+
* ```typescript
|
|
245
|
+
* import { HotMesh } from '@hotmeshio/hotmesh';
|
|
246
|
+
* import { Client as Postgres } from 'pg';
|
|
247
|
+
*
|
|
248
|
+
* const hotMesh = await HotMesh.init({
|
|
249
|
+
* appId: 'my-app',
|
|
250
|
+
* engine: {
|
|
251
|
+
* connection: {
|
|
252
|
+
* class: Postgres,
|
|
253
|
+
* options: { connectionString: 'postgresql://...' }
|
|
254
|
+
* },
|
|
255
|
+
* // Default retry policy for engine streams
|
|
256
|
+
* retryPolicy: {
|
|
257
|
+
* maximumAttempts: 5, // Retry up to 5 times
|
|
258
|
+
* backoffCoefficient: 2, // Exponential: 2^0, 2^1, 2^2...
|
|
259
|
+
* maximumInterval: '300s' // Cap delay at 5 minutes
|
|
260
|
+
* }
|
|
261
|
+
* },
|
|
262
|
+
* workers: [{
|
|
263
|
+
* topic: 'order.process',
|
|
264
|
+
* connection: {
|
|
265
|
+
* class: Postgres,
|
|
266
|
+
* options: { connectionString: 'postgresql://...' }
|
|
267
|
+
* },
|
|
268
|
+
* // Worker-specific retry policy
|
|
269
|
+
* retryPolicy: {
|
|
270
|
+
* maximumAttempts: 10,
|
|
271
|
+
* backoffCoefficient: 1.5,
|
|
272
|
+
* maximumInterval: '600s'
|
|
273
|
+
* },
|
|
274
|
+
* callback: async (data) => {
|
|
275
|
+
* // Your business logic here
|
|
276
|
+
* // Failures will automatically retry with exponential backoff
|
|
277
|
+
* return { status: 'success', data: processedData };
|
|
278
|
+
* }
|
|
279
|
+
* }]
|
|
280
|
+
* });
|
|
281
|
+
* ```
|
|
282
|
+
*
|
|
283
|
+
* **Retry Policy Options**:
|
|
284
|
+
* - `maximumAttempts` - Maximum retry attempts before failure (default: 3)
|
|
285
|
+
* - `backoffCoefficient` - Base for exponential backoff calculation (default: 10)
|
|
286
|
+
* - `maximumInterval` - Maximum delay between retries in seconds or duration string (default: '120s')
|
|
287
|
+
*
|
|
288
|
+
* **Retry Delays**: For `backoffCoefficient: 2`, delays are: 2s, 4s, 8s, 16s, 32s...
|
|
289
|
+
* capped at `maximumInterval`.
|
|
290
|
+
*
|
|
291
|
+
* **Note**: Retry policies are stored in PostgreSQL columns for efficient querying and
|
|
292
|
+
* observability. Each retry creates a new message, preserving message immutability.
|
|
248
293
|
*/
|
|
249
294
|
static async init(config) {
|
|
250
295
|
const instance = new HotMesh();
|
|
@@ -275,6 +320,10 @@ class HotMesh {
|
|
|
275
320
|
if (config.engine.connection.readonly) {
|
|
276
321
|
config.engine.readonly = true;
|
|
277
322
|
}
|
|
323
|
+
// Apply retry policy to stream connection if provided
|
|
324
|
+
if (config.engine.retryPolicy) {
|
|
325
|
+
this.applyRetryPolicy(config.engine.connection, config.engine.retryPolicy);
|
|
326
|
+
}
|
|
278
327
|
// Initialize task queue for engine
|
|
279
328
|
config.engine.taskQueue = this.initTaskQueue(config.engine.taskQueue, config.taskQueue);
|
|
280
329
|
await factory_1.ConnectorService.initClients(config.engine);
|
|
@@ -313,6 +362,10 @@ class HotMesh {
|
|
|
313
362
|
// Initialize task queues for workers
|
|
314
363
|
if (config.workers) {
|
|
315
364
|
for (const worker of config.workers) {
|
|
365
|
+
// Apply retry policy to stream connection if provided
|
|
366
|
+
if (worker.retryPolicy) {
|
|
367
|
+
this.applyRetryPolicy(worker.connection, worker.retryPolicy);
|
|
368
|
+
}
|
|
316
369
|
worker.taskQueue = this.initTaskQueue(worker.taskQueue, config.taskQueue);
|
|
317
370
|
}
|
|
318
371
|
}
|
|
@@ -337,6 +390,22 @@ class HotMesh {
|
|
|
337
390
|
// Default queue as fallback
|
|
338
391
|
return enums_1.DEFAULT_TASK_QUEUE;
|
|
339
392
|
}
|
|
393
|
+
/**
|
|
394
|
+
* Apply retry policy to the stream connection within a ProviderConfig or ProvidersConfig.
|
|
395
|
+
* Handles both short-form (ProviderConfig) and long-form (ProvidersConfig) connection configs.
|
|
396
|
+
* @private
|
|
397
|
+
*/
|
|
398
|
+
applyRetryPolicy(connection, retryPolicy) {
|
|
399
|
+
// Check if this is ProvidersConfig (has 'stream' property)
|
|
400
|
+
if ('stream' in connection && connection.stream) {
|
|
401
|
+
// Long-form: apply to the stream sub-config
|
|
402
|
+
connection.stream.retryPolicy = retryPolicy;
|
|
403
|
+
}
|
|
404
|
+
else {
|
|
405
|
+
// Short-form: apply directly to the connection
|
|
406
|
+
connection.retryPolicy = retryPolicy;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
340
409
|
// ************* PUB/SUB METHODS *************
|
|
341
410
|
/**
|
|
342
411
|
* Starts a workflow
|