@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.
- package/.claude/settings.local.json +7 -0
- package/README.md +179 -142
- package/build/index.d.ts +1 -3
- package/build/index.js +1 -5
- package/build/modules/enums.d.ts +7 -0
- package/build/modules/enums.js +16 -1
- package/build/modules/utils.d.ts +27 -0
- package/build/modules/utils.js +55 -32
- package/build/package.json +18 -27
- package/build/services/activities/activity.d.ts +43 -6
- package/build/services/activities/activity.js +262 -54
- package/build/services/activities/await.js +2 -2
- package/build/services/activities/cycle.js +1 -1
- package/build/services/activities/hook.d.ts +5 -0
- package/build/services/activities/hook.js +22 -19
- package/build/services/activities/interrupt.js +17 -25
- package/build/services/activities/signal.d.ts +4 -2
- package/build/services/activities/signal.js +27 -24
- package/build/services/activities/worker.js +2 -2
- package/build/services/collator/index.d.ts +123 -25
- package/build/services/collator/index.js +224 -101
- package/build/services/connector/factory.d.ts +1 -1
- package/build/services/connector/factory.js +1 -11
- package/build/services/connector/providers/postgres.js +3 -0
- package/build/services/engine/index.d.ts +5 -5
- package/build/services/engine/index.js +36 -15
- 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 +39 -3
- 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 +1 -9
- package/build/services/store/factory.js +1 -9
- package/build/services/store/index.d.ts +8 -2
- package/build/services/store/providers/postgres/kvsql.d.ts +4 -0
- package/build/services/store/providers/postgres/kvsql.js +4 -0
- package/build/services/store/providers/postgres/kvtransaction.d.ts +2 -0
- package/build/services/store/providers/postgres/kvtransaction.js +23 -0
- package/build/services/store/providers/postgres/kvtypes/hash/basic.d.ts +51 -0
- package/build/services/store/providers/postgres/kvtypes/hash/basic.js +229 -7
- package/build/services/store/providers/postgres/kvtypes/hash/expire.js +12 -2
- package/build/services/store/providers/postgres/kvtypes/hash/index.d.ts +4 -0
- package/build/services/store/providers/postgres/kvtypes/hash/index.js +6 -0
- 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 +23 -3
- package/build/services/store/providers/postgres/postgres.js +38 -1
- package/build/services/stream/factory.js +1 -17
- 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/sub/factory.js +1 -9
- package/build/services/sub/index.d.ts +1 -1
- package/build/services/sub/providers/postgres/postgres.d.ts +1 -1
- package/build/services/sub/providers/postgres/postgres.js +53 -6
- package/build/services/task/index.d.ts +1 -1
- package/build/services/task/index.js +2 -6
- 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 +3 -4
- package/build/types/index.js +1 -4
- package/build/types/memflow.d.ts +32 -0
- package/build/types/provider.d.ts +17 -1
- package/build/types/stream.d.ts +92 -1
- package/index.ts +0 -4
- package/package.json +18 -27
- package/build/services/connector/providers/ioredis.d.ts +0 -9
- package/build/services/connector/providers/ioredis.js +0 -26
- package/build/services/connector/providers/redis.d.ts +0 -9
- package/build/services/connector/providers/redis.js +0 -38
- package/build/services/search/providers/redis/ioredis.d.ts +0 -23
- package/build/services/search/providers/redis/ioredis.js +0 -189
- package/build/services/search/providers/redis/redis.d.ts +0 -23
- package/build/services/search/providers/redis/redis.js +0 -202
- package/build/services/store/providers/redis/_base.d.ts +0 -137
- package/build/services/store/providers/redis/_base.js +0 -980
- package/build/services/store/providers/redis/ioredis.d.ts +0 -20
- package/build/services/store/providers/redis/ioredis.js +0 -180
- package/build/services/store/providers/redis/redis.d.ts +0 -18
- package/build/services/store/providers/redis/redis.js +0 -199
- package/build/services/stream/providers/redis/ioredis.d.ts +0 -61
- package/build/services/stream/providers/redis/ioredis.js +0 -272
- package/build/services/stream/providers/redis/redis.d.ts +0 -61
- package/build/services/stream/providers/redis/redis.js +0 -305
- package/build/services/sub/providers/redis/ioredis.d.ts +0 -20
- package/build/services/sub/providers/redis/ioredis.js +0 -150
- package/build/services/sub/providers/redis/redis.d.ts +0 -18
- package/build/services/sub/providers/redis/redis.js +0 -137
- package/build/types/redis.d.ts +0 -258
- package/build/types/redis.js +0 -11
|
@@ -17,13 +17,23 @@ function createScanOperations(context) {
|
|
|
17
17
|
return Promise.resolve({ cursor: '0', items: {} });
|
|
18
18
|
}
|
|
19
19
|
else {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
try {
|
|
21
|
+
const res = await context.pgClient.query(sql, params);
|
|
22
|
+
const items = {};
|
|
23
|
+
for (const row of res.rows) {
|
|
24
|
+
items[row.field] = row.value;
|
|
25
|
+
}
|
|
26
|
+
const newCursor = res.rowCount < count ? 0 : Number(cursor) + res.rowCount;
|
|
27
|
+
return { cursor: newCursor.toString(), items };
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
// Connection closed during test cleanup - return empty result
|
|
31
|
+
if (error?.message?.includes('closed') || error?.message?.includes('queryable')) {
|
|
32
|
+
return { cursor: '0', items: {} };
|
|
33
|
+
}
|
|
34
|
+
// Re-throw unexpected errors
|
|
35
|
+
throw error;
|
|
24
36
|
}
|
|
25
|
-
const newCursor = res.rowCount < count ? 0 : Number(cursor) + res.rowCount;
|
|
26
|
-
return { cursor: newCursor.toString(), items };
|
|
27
37
|
}
|
|
28
38
|
},
|
|
29
39
|
async scan(cursor, count = 10, pattern, multi) {
|
|
@@ -37,10 +47,20 @@ function createScanOperations(context) {
|
|
|
37
47
|
return Promise.resolve({ cursor: 0, keys: [] });
|
|
38
48
|
}
|
|
39
49
|
else {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
50
|
+
try {
|
|
51
|
+
const res = await context.pgClient.query(sql, params);
|
|
52
|
+
const keys = res.rows.map((row) => row.key);
|
|
53
|
+
const newCursor = cursor + res.rowCount;
|
|
54
|
+
return { cursor: newCursor, keys };
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
// Connection closed during test cleanup - return empty result
|
|
58
|
+
if (error?.message?.includes('closed') || error?.message?.includes('queryable')) {
|
|
59
|
+
return { cursor: 0, keys: [] };
|
|
60
|
+
}
|
|
61
|
+
// Re-throw unexpected errors
|
|
62
|
+
throw error;
|
|
63
|
+
}
|
|
44
64
|
}
|
|
45
65
|
},
|
|
46
66
|
};
|
|
@@ -9,8 +9,18 @@ const listModule = (context) => ({
|
|
|
9
9
|
return Promise.resolve([]);
|
|
10
10
|
}
|
|
11
11
|
else {
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
try {
|
|
13
|
+
const res = await context.pgClient.query(sql, params);
|
|
14
|
+
return res.rows.map((row) => row.value);
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
// Connection closed during test cleanup - return empty array
|
|
18
|
+
if (error?.message?.includes('closed') || error?.message?.includes('queryable')) {
|
|
19
|
+
return [];
|
|
20
|
+
}
|
|
21
|
+
// Re-throw unexpected errors
|
|
22
|
+
throw error;
|
|
23
|
+
}
|
|
14
24
|
}
|
|
15
25
|
},
|
|
16
26
|
_lrange(key, start, end) {
|
|
@@ -44,8 +54,18 @@ const listModule = (context) => ({
|
|
|
44
54
|
return Promise.resolve(0);
|
|
45
55
|
}
|
|
46
56
|
else {
|
|
47
|
-
|
|
48
|
-
|
|
57
|
+
try {
|
|
58
|
+
const res = await context.pgClient.query(sql, params);
|
|
59
|
+
return Number(res.rows[0]?.count || 0);
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
// Connection closed during test cleanup - return 0
|
|
63
|
+
if (error?.message?.includes('closed') || error?.message?.includes('queryable')) {
|
|
64
|
+
return 0;
|
|
65
|
+
}
|
|
66
|
+
// Re-throw unexpected errors
|
|
67
|
+
throw error;
|
|
68
|
+
}
|
|
49
69
|
}
|
|
50
70
|
},
|
|
51
71
|
_rpush(key, value) {
|
|
@@ -72,8 +92,18 @@ const listModule = (context) => ({
|
|
|
72
92
|
return Promise.resolve(0);
|
|
73
93
|
}
|
|
74
94
|
else {
|
|
75
|
-
|
|
76
|
-
|
|
95
|
+
try {
|
|
96
|
+
const res = await context.pgClient.query(sql, params);
|
|
97
|
+
return Number(res.rows[0]?.count || 0);
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
// Connection closed during test cleanup - return 0
|
|
101
|
+
if (error?.message?.includes('closed') || error?.message?.includes('queryable')) {
|
|
102
|
+
return 0;
|
|
103
|
+
}
|
|
104
|
+
// Re-throw unexpected errors
|
|
105
|
+
throw error;
|
|
106
|
+
}
|
|
77
107
|
}
|
|
78
108
|
},
|
|
79
109
|
_lpush(key, value) {
|
|
@@ -100,8 +130,18 @@ const listModule = (context) => ({
|
|
|
100
130
|
return Promise.resolve(null);
|
|
101
131
|
}
|
|
102
132
|
else {
|
|
103
|
-
|
|
104
|
-
|
|
133
|
+
try {
|
|
134
|
+
const res = await context.pgClient.query(sql, params);
|
|
135
|
+
return res.rows[0]?.value || null;
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
// Connection closed during test cleanup - return null
|
|
139
|
+
if (error?.message?.includes('closed') || error?.message?.includes('queryable')) {
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
// Re-throw unexpected errors
|
|
143
|
+
throw error;
|
|
144
|
+
}
|
|
105
145
|
}
|
|
106
146
|
},
|
|
107
147
|
_lpop(key) {
|
|
@@ -131,7 +171,16 @@ const listModule = (context) => ({
|
|
|
131
171
|
return res.rows[0]?.value || null;
|
|
132
172
|
}
|
|
133
173
|
catch (err) {
|
|
134
|
-
|
|
174
|
+
// Connection closed during test cleanup - return null
|
|
175
|
+
if (err?.message?.includes('closed') || err?.message?.includes('queryable')) {
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
try {
|
|
179
|
+
await client.query('ROLLBACK');
|
|
180
|
+
}
|
|
181
|
+
catch (rollbackErr) {
|
|
182
|
+
// Ignore rollback errors if connection is closed
|
|
183
|
+
}
|
|
135
184
|
throw err;
|
|
136
185
|
}
|
|
137
186
|
}
|
|
@@ -177,7 +226,16 @@ const listModule = (context) => ({
|
|
|
177
226
|
await client.query('COMMIT');
|
|
178
227
|
}
|
|
179
228
|
catch (err) {
|
|
180
|
-
|
|
229
|
+
// Connection closed during test cleanup - silently return
|
|
230
|
+
if (err?.message?.includes('closed') || err?.message?.includes('queryable')) {
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
try {
|
|
234
|
+
await client.query('ROLLBACK');
|
|
235
|
+
}
|
|
236
|
+
catch (rollbackErr) {
|
|
237
|
+
// Ignore rollback errors if connection is closed
|
|
238
|
+
}
|
|
181
239
|
throw err;
|
|
182
240
|
}
|
|
183
241
|
}
|
|
@@ -9,8 +9,18 @@ const stringModule = (context) => ({
|
|
|
9
9
|
return Promise.resolve(null);
|
|
10
10
|
}
|
|
11
11
|
else {
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
try {
|
|
13
|
+
const res = await context.pgClient.query(sql, params);
|
|
14
|
+
return res.rows[0]?.value || null;
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
// Connection closed during test cleanup - log and return null
|
|
18
|
+
if (error?.message?.includes('closed') || error?.message?.includes('queryable')) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
// Re-throw unexpected errors
|
|
22
|
+
throw error;
|
|
23
|
+
}
|
|
14
24
|
}
|
|
15
25
|
},
|
|
16
26
|
_get(key) {
|
|
@@ -30,8 +40,18 @@ const stringModule = (context) => ({
|
|
|
30
40
|
return Promise.resolve(true);
|
|
31
41
|
}
|
|
32
42
|
else {
|
|
33
|
-
|
|
34
|
-
|
|
43
|
+
try {
|
|
44
|
+
const res = await context.pgClient.query(sql, params);
|
|
45
|
+
return res.rowCount > 0;
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
// Connection closed during test cleanup - log and return false
|
|
49
|
+
if (error?.message?.includes('closed') || error?.message?.includes('queryable')) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
// Re-throw unexpected errors
|
|
53
|
+
throw error;
|
|
54
|
+
}
|
|
35
55
|
}
|
|
36
56
|
},
|
|
37
57
|
async setnxex(key, value, delay, multi) {
|
|
@@ -41,8 +61,18 @@ const stringModule = (context) => ({
|
|
|
41
61
|
return Promise.resolve(true);
|
|
42
62
|
}
|
|
43
63
|
else {
|
|
44
|
-
|
|
45
|
-
|
|
64
|
+
try {
|
|
65
|
+
const res = await context.pgClient.query(sql, params);
|
|
66
|
+
return res.rowCount > 0;
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
// Connection closed during test cleanup - log and return false
|
|
70
|
+
if (error?.message?.includes('closed') || error?.message?.includes('queryable')) {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
// Re-throw unexpected errors
|
|
74
|
+
throw error;
|
|
75
|
+
}
|
|
46
76
|
}
|
|
47
77
|
},
|
|
48
78
|
async set(key, value, options, multi) {
|
|
@@ -52,8 +82,18 @@ const stringModule = (context) => ({
|
|
|
52
82
|
return Promise.resolve(true);
|
|
53
83
|
}
|
|
54
84
|
else {
|
|
55
|
-
|
|
56
|
-
|
|
85
|
+
try {
|
|
86
|
+
const res = await context.pgClient.query(sql, params);
|
|
87
|
+
return res.rowCount > 0;
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
// Connection closed during test cleanup - log and return false
|
|
91
|
+
if (error?.message?.includes('closed') || error?.message?.includes('queryable')) {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
// Re-throw unexpected errors
|
|
95
|
+
throw error;
|
|
96
|
+
}
|
|
57
97
|
}
|
|
58
98
|
},
|
|
59
99
|
_set(key, value, options) {
|
|
@@ -95,8 +135,18 @@ const stringModule = (context) => ({
|
|
|
95
135
|
return Promise.resolve(0);
|
|
96
136
|
}
|
|
97
137
|
else {
|
|
98
|
-
|
|
99
|
-
|
|
138
|
+
try {
|
|
139
|
+
const res = await context.pgClient.query(sql, params);
|
|
140
|
+
return Number(res.rows[0]?.count || 0);
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
// Connection closed during test cleanup - log and return 0
|
|
144
|
+
if (error?.message?.includes('closed') || error?.message?.includes('queryable')) {
|
|
145
|
+
return 0;
|
|
146
|
+
}
|
|
147
|
+
// Re-throw unexpected errors
|
|
148
|
+
throw error;
|
|
149
|
+
}
|
|
100
150
|
}
|
|
101
151
|
},
|
|
102
152
|
_del(key) {
|
|
@@ -9,8 +9,18 @@ const zsetModule = (context) => ({
|
|
|
9
9
|
return Promise.resolve(0);
|
|
10
10
|
}
|
|
11
11
|
else {
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
try {
|
|
13
|
+
const res = await context.pgClient.query(sql, params);
|
|
14
|
+
return Number(res.rows[0]?.count || 0);
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
// Connection closed during test cleanup - return 0
|
|
18
|
+
if (error?.message?.includes('closed') || error?.message?.includes('queryable')) {
|
|
19
|
+
return 0;
|
|
20
|
+
}
|
|
21
|
+
// Re-throw unexpected errors
|
|
22
|
+
throw error;
|
|
23
|
+
}
|
|
14
24
|
}
|
|
15
25
|
},
|
|
16
26
|
_zadd(key, score, member, options) {
|
|
@@ -50,13 +60,23 @@ const zsetModule = (context) => ({
|
|
|
50
60
|
return Promise.resolve([]);
|
|
51
61
|
}
|
|
52
62
|
else {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
63
|
+
try {
|
|
64
|
+
const res = await context.pgClient.query(sql, params);
|
|
65
|
+
if (facet === 'WITHSCORES') {
|
|
66
|
+
// Include scores in the result
|
|
67
|
+
return res.rows.flatMap((row) => [row.member, row.score.toString()]);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
return res.rows.map((row) => row.member);
|
|
71
|
+
}
|
|
57
72
|
}
|
|
58
|
-
|
|
59
|
-
return
|
|
73
|
+
catch (error) {
|
|
74
|
+
// Connection closed during test cleanup - return empty array
|
|
75
|
+
if (error?.message?.includes('closed') || error?.message?.includes('queryable')) {
|
|
76
|
+
return [];
|
|
77
|
+
}
|
|
78
|
+
// Re-throw unexpected errors
|
|
79
|
+
throw error;
|
|
60
80
|
}
|
|
61
81
|
}
|
|
62
82
|
},
|
|
@@ -99,8 +119,18 @@ const zsetModule = (context) => ({
|
|
|
99
119
|
return Promise.resolve(null);
|
|
100
120
|
}
|
|
101
121
|
else {
|
|
102
|
-
|
|
103
|
-
|
|
122
|
+
try {
|
|
123
|
+
const res = await context.pgClient.query(sql, params);
|
|
124
|
+
return res.rows.length ? parseFloat(res.rows[0].score) : null;
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
// Connection closed during test cleanup - return null
|
|
128
|
+
if (error?.message?.includes('closed') || error?.message?.includes('queryable')) {
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
// Re-throw unexpected errors
|
|
132
|
+
throw error;
|
|
133
|
+
}
|
|
104
134
|
}
|
|
105
135
|
},
|
|
106
136
|
_zscore(key, member) {
|
|
@@ -122,8 +152,18 @@ const zsetModule = (context) => ({
|
|
|
122
152
|
return Promise.resolve([]);
|
|
123
153
|
}
|
|
124
154
|
else {
|
|
125
|
-
|
|
126
|
-
|
|
155
|
+
try {
|
|
156
|
+
const res = await context.pgClient.query(sql, params);
|
|
157
|
+
return res.rows.map((row) => row.member);
|
|
158
|
+
}
|
|
159
|
+
catch (error) {
|
|
160
|
+
// Connection closed during test cleanup - return empty array
|
|
161
|
+
if (error?.message?.includes('closed') || error?.message?.includes('queryable')) {
|
|
162
|
+
return [];
|
|
163
|
+
}
|
|
164
|
+
// Re-throw unexpected errors
|
|
165
|
+
throw error;
|
|
166
|
+
}
|
|
127
167
|
}
|
|
128
168
|
},
|
|
129
169
|
_zrangebyscore(key, min, max) {
|
|
@@ -143,8 +183,18 @@ const zsetModule = (context) => ({
|
|
|
143
183
|
return Promise.resolve([]);
|
|
144
184
|
}
|
|
145
185
|
else {
|
|
146
|
-
|
|
147
|
-
|
|
186
|
+
try {
|
|
187
|
+
const res = await context.pgClient.query(sql, params);
|
|
188
|
+
return res.rows.map((row) => ({ member: row.member, score: row.score }));
|
|
189
|
+
}
|
|
190
|
+
catch (error) {
|
|
191
|
+
// Connection closed during test cleanup - return empty array
|
|
192
|
+
if (error?.message?.includes('closed') || error?.message?.includes('queryable')) {
|
|
193
|
+
return [];
|
|
194
|
+
}
|
|
195
|
+
// Re-throw unexpected errors
|
|
196
|
+
throw error;
|
|
197
|
+
}
|
|
148
198
|
}
|
|
149
199
|
},
|
|
150
200
|
_zrangebyscore_withscores(key, min, max) {
|
|
@@ -164,8 +214,18 @@ const zsetModule = (context) => ({
|
|
|
164
214
|
return Promise.resolve(0);
|
|
165
215
|
}
|
|
166
216
|
else {
|
|
167
|
-
|
|
168
|
-
|
|
217
|
+
try {
|
|
218
|
+
const res = await context.pgClient.query(sql, params);
|
|
219
|
+
return Number(res.rows[0]?.count || 0);
|
|
220
|
+
}
|
|
221
|
+
catch (error) {
|
|
222
|
+
// Connection closed during test cleanup - return 0
|
|
223
|
+
if (error?.message?.includes('closed') || error?.message?.includes('queryable')) {
|
|
224
|
+
return 0;
|
|
225
|
+
}
|
|
226
|
+
// Re-throw unexpected errors
|
|
227
|
+
throw error;
|
|
228
|
+
}
|
|
169
229
|
}
|
|
170
230
|
},
|
|
171
231
|
_zrem(key, member) {
|
|
@@ -188,12 +248,22 @@ const zsetModule = (context) => ({
|
|
|
188
248
|
return Promise.resolve(null);
|
|
189
249
|
}
|
|
190
250
|
else {
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
? parseInt(res.rows[0].rank, 10)
|
|
195
|
-
|
|
196
|
-
|
|
251
|
+
try {
|
|
252
|
+
const res = await context.pgClient.query(sql, params);
|
|
253
|
+
return res.rows[0]?.rank
|
|
254
|
+
? parseInt(res.rows[0].rank, 10) > 0
|
|
255
|
+
? parseInt(res.rows[0].rank, 10) - 1
|
|
256
|
+
: null
|
|
257
|
+
: null;
|
|
258
|
+
}
|
|
259
|
+
catch (error) {
|
|
260
|
+
// Connection closed during test cleanup - return null
|
|
261
|
+
if (error?.message?.includes('closed') || error?.message?.includes('queryable')) {
|
|
262
|
+
return null;
|
|
263
|
+
}
|
|
264
|
+
// Re-throw unexpected errors
|
|
265
|
+
throw error;
|
|
266
|
+
}
|
|
197
267
|
}
|
|
198
268
|
},
|
|
199
269
|
_zrank(key, member) {
|
|
@@ -3,7 +3,7 @@ import { ILogger } from '../../../logger';
|
|
|
3
3
|
import { ActivityType, Consumes } from '../../../../types/activity';
|
|
4
4
|
import { AppVID } from '../../../../types/app';
|
|
5
5
|
import { HookRule, HookSignal } from '../../../../types/hook';
|
|
6
|
-
import { HotMeshApp, HotMeshApps, HotMeshSettings } from '../../../../types/hotmesh';
|
|
6
|
+
import { HotMeshApp, HotMeshApps, HotMeshSettings, ScoutType } from '../../../../types/hotmesh';
|
|
7
7
|
import { ProviderClient, ProviderTransaction } from '../../../../types/provider';
|
|
8
8
|
import { SymbolSets, StringStringType, StringAnyType, Symbols } from '../../../../types/serializer';
|
|
9
9
|
import { IdsData, JobStatsRange, StatsType } from '../../../../types/stats';
|
|
@@ -38,8 +38,8 @@ declare class PostgresStoreService extends StoreService<ProviderClient, Provider
|
|
|
38
38
|
* check for and process work items in the
|
|
39
39
|
* time and signal task queues.
|
|
40
40
|
*/
|
|
41
|
-
reserveScoutRole(scoutType:
|
|
42
|
-
releaseScoutRole(scoutType:
|
|
41
|
+
reserveScoutRole(scoutType: ScoutType, delay?: number): Promise<boolean>;
|
|
42
|
+
releaseScoutRole(scoutType: ScoutType): Promise<boolean>;
|
|
43
43
|
getSettings(bCreate?: boolean): Promise<HotMeshSettings>;
|
|
44
44
|
setSettings(manifest: HotMeshSettings): Promise<any>;
|
|
45
45
|
reserveSymbolRange(target: string, size: number, type: 'JOB' | 'ACTIVITY', tryCount?: number): Promise<[number, number, Symbols]>;
|
|
@@ -61,6 +61,20 @@ declare class PostgresStoreService extends StoreService<ProviderClient, Provider
|
|
|
61
61
|
getJobStats(jobKeys: string[]): Promise<JobStatsRange>;
|
|
62
62
|
getJobIds(indexKeys: string[], idRange: [number, number]): Promise<IdsData>;
|
|
63
63
|
setStatus(collationKeyStatus: number, jobId: string, appId: string, transaction?: ProviderTransaction): Promise<any>;
|
|
64
|
+
/**
|
|
65
|
+
* 1) HIGH-LEVEL STORE METHOD (engine/activity-facing)
|
|
66
|
+
* ---------------------------------------------------
|
|
67
|
+
* Mirrors setStatus(), but performs the compound Step-2 requirement:
|
|
68
|
+
* - apply delta to job semaphore (jobs.status)
|
|
69
|
+
* - compute thresholdHit (0/1) for desired threshold
|
|
70
|
+
* - persist thresholdHit onto the Leg2 GUID ledger by incrementing the 100B digit (or other weight)
|
|
71
|
+
* - return thresholdHit (0/1)
|
|
72
|
+
*/
|
|
73
|
+
setStatusAndCollateGuid(statusDelta: number, // typically (N - 1)
|
|
74
|
+
threshold: number, // typically 0 (but supports 0,1,12,...)
|
|
75
|
+
jobId: string, appId: string, guidField: string, // the jobs_attributes.field for the Leg2 GUID ledger row
|
|
76
|
+
guidWeight: number, // e.g. 100_000_000_000 for GUID 100B digit
|
|
77
|
+
transaction?: ProviderTransaction): Promise<number>;
|
|
64
78
|
getStatus(jobId: string, appId: string): Promise<number>;
|
|
65
79
|
setState({ ...state }: StringAnyType, status: number | null, jobId: string, symbolNames: string[], dIds: StringStringType, transaction?: ProviderTransaction): Promise<string>;
|
|
66
80
|
/**
|
|
@@ -76,6 +90,12 @@ declare class PostgresStoreService extends StoreService<ProviderClient, Provider
|
|
|
76
90
|
* in order to track their progress during processing.
|
|
77
91
|
*/
|
|
78
92
|
collate(jobId: string, activityId: string, amount: number, dIds: StringStringType, transaction?: ProviderTransaction): Promise<number>;
|
|
93
|
+
/**
|
|
94
|
+
* Compound Leg2 entry: atomically increments the activity Leg2 entry
|
|
95
|
+
* counter and seeds the GUID ledger with the ordinal IF NOT EXISTS.
|
|
96
|
+
* Returns [activityValue, guidValue].
|
|
97
|
+
*/
|
|
98
|
+
collateLeg2Entry(jobId: string, activityId: string, guid: string, dIds: StringStringType, transaction?: ProviderTransaction): Promise<[number, number]>;
|
|
79
99
|
/**
|
|
80
100
|
* Synthentic collation affects those activities in the graph
|
|
81
101
|
* that represent the synthetic DAG that was materialized during compilation;
|
|
@@ -439,6 +439,23 @@ class PostgresStoreService extends __1.StoreService {
|
|
|
439
439
|
const jobKey = this.mintKey(key_1.KeyType.JOB_STATE, { appId, jobId });
|
|
440
440
|
return await this.kvsql(transaction).hincrbyfloat(jobKey, ':', collationKeyStatus);
|
|
441
441
|
}
|
|
442
|
+
/**
|
|
443
|
+
* 1) HIGH-LEVEL STORE METHOD (engine/activity-facing)
|
|
444
|
+
* ---------------------------------------------------
|
|
445
|
+
* Mirrors setStatus(), but performs the compound Step-2 requirement:
|
|
446
|
+
* - apply delta to job semaphore (jobs.status)
|
|
447
|
+
* - compute thresholdHit (0/1) for desired threshold
|
|
448
|
+
* - persist thresholdHit onto the Leg2 GUID ledger by incrementing the 100B digit (or other weight)
|
|
449
|
+
* - return thresholdHit (0/1)
|
|
450
|
+
*/
|
|
451
|
+
async setStatusAndCollateGuid(statusDelta, // typically (N - 1)
|
|
452
|
+
threshold, // typically 0 (but supports 0,1,12,...)
|
|
453
|
+
jobId, appId, guidField, // the jobs_attributes.field for the Leg2 GUID ledger row
|
|
454
|
+
guidWeight, // e.g. 100_000_000_000 for GUID 100B digit
|
|
455
|
+
transaction) {
|
|
456
|
+
const jobKey = this.mintKey(key_1.KeyType.JOB_STATE, { appId, jobId });
|
|
457
|
+
return await this.kvsql(transaction).setStatusAndCollateGuid(jobKey, statusDelta, threshold, guidField, guidWeight);
|
|
458
|
+
}
|
|
442
459
|
async getStatus(jobId, appId) {
|
|
443
460
|
const jobKey = this.mintKey(key_1.KeyType.JOB_STATE, { appId, jobId });
|
|
444
461
|
const status = await this.kvsql().hget(jobKey, ':');
|
|
@@ -551,6 +568,26 @@ class PostgresStoreService extends __1.StoreService {
|
|
|
551
568
|
const targetId = Object.keys(hashData)[0];
|
|
552
569
|
return await this.kvsql(transaction).hincrbyfloat(jobKey, targetId, amount);
|
|
553
570
|
}
|
|
571
|
+
/**
|
|
572
|
+
* Compound Leg2 entry: atomically increments the activity Leg2 entry
|
|
573
|
+
* counter and seeds the GUID ledger with the ordinal IF NOT EXISTS.
|
|
574
|
+
* Returns [activityValue, guidValue].
|
|
575
|
+
*/
|
|
576
|
+
async collateLeg2Entry(jobId, activityId, guid, dIds, transaction) {
|
|
577
|
+
const jobKey = this.mintKey(key_1.KeyType.JOB_STATE, {
|
|
578
|
+
appId: this.appId,
|
|
579
|
+
jobId,
|
|
580
|
+
});
|
|
581
|
+
const collationKey = `${activityId}/output/metadata/as`;
|
|
582
|
+
const symbolNames = [activityId];
|
|
583
|
+
const symKeys = await this.getSymbolKeys(symbolNames);
|
|
584
|
+
const symVals = await this.getSymbolValues();
|
|
585
|
+
this.serializer.resetSymbols(symKeys, symVals, dIds);
|
|
586
|
+
const payload = { [collationKey]: '1' };
|
|
587
|
+
const hashData = this.serializer.package(payload, symbolNames);
|
|
588
|
+
const targetId = Object.keys(hashData)[0];
|
|
589
|
+
return await this.kvsql(transaction).collateLeg2Entry(jobKey, targetId, 1, guid);
|
|
590
|
+
}
|
|
554
591
|
/**
|
|
555
592
|
* Synthentic collation affects those activities in the graph
|
|
556
593
|
* that represent the synthetic DAG that was materialized during compilation;
|
|
@@ -1044,7 +1081,7 @@ class PostgresStoreService extends __1.StoreService {
|
|
|
1044
1081
|
const sql = (0, time_notify_1.getTimeNotifySql)(schemaName);
|
|
1045
1082
|
// Execute the entire SQL as one statement (functions contain $$ blocks with semicolons)
|
|
1046
1083
|
await client.query(sql);
|
|
1047
|
-
this.logger.
|
|
1084
|
+
this.logger.debug('postgres-time-notifications-deployed', {
|
|
1048
1085
|
appId,
|
|
1049
1086
|
schemaName,
|
|
1050
1087
|
message: 'Time-aware notifications ENABLED - using LISTEN/NOTIFY instead of polling',
|
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.StreamServiceFactory = void 0;
|
|
4
4
|
const utils_1 = require("../../modules/utils");
|
|
5
|
-
const ioredis_1 = require("./providers/redis/ioredis");
|
|
6
|
-
const redis_1 = require("./providers/redis/redis");
|
|
7
5
|
const nats_1 = require("./providers/nats/nats");
|
|
8
6
|
const postgres_1 = require("./providers/postgres/postgres");
|
|
9
7
|
class StreamServiceFactory {
|
|
@@ -11,24 +9,10 @@ class StreamServiceFactory {
|
|
|
11
9
|
let service;
|
|
12
10
|
const providerType = (0, utils_1.identifyProvider)(provider);
|
|
13
11
|
if (providerType === 'nats') {
|
|
14
|
-
|
|
15
|
-
if ((0, utils_1.identifyProvider)(storeProvider) === 'redis') {
|
|
16
|
-
redisStoreProvider = storeProvider;
|
|
17
|
-
}
|
|
18
|
-
else {
|
|
19
|
-
//ioredis
|
|
20
|
-
redisStoreProvider = storeProvider;
|
|
21
|
-
}
|
|
22
|
-
service = new nats_1.NatsStreamService(provider, redisStoreProvider);
|
|
12
|
+
service = new nats_1.NatsStreamService(provider, storeProvider);
|
|
23
13
|
}
|
|
24
14
|
else if (providerType === 'postgres') {
|
|
25
15
|
service = new postgres_1.PostgresStreamService(provider, storeProvider);
|
|
26
|
-
}
|
|
27
|
-
else if (providerType === 'redis') {
|
|
28
|
-
service = new redis_1.RedisStreamService(provider, storeProvider);
|
|
29
|
-
}
|
|
30
|
-
else if (providerType === 'ioredis') {
|
|
31
|
-
service = new ioredis_1.IORedisStreamService(provider, storeProvider);
|
|
32
16
|
} //etc register other providers here
|
|
33
17
|
await service.init(namespace, appId, logger);
|
|
34
18
|
return service;
|