@hotmeshio/hotmesh 0.4.0 → 0.4.1
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/build/modules/enums.d.ts +110 -0
- package/build/modules/enums.js +134 -0
- package/build/modules/errors.d.ts +124 -0
- package/build/modules/errors.js +191 -0
- package/build/modules/key.d.ts +66 -0
- package/build/modules/key.js +190 -0
- package/build/modules/storage.d.ts +3 -0
- package/build/modules/storage.js +5 -0
- package/build/modules/utils.d.ts +119 -0
- package/build/modules/utils.js +374 -0
- package/build/package.json +1 -1
- package/build/services/activities/activity.d.ts +104 -0
- package/build/services/activities/activity.js +549 -0
- package/build/services/activities/await.d.ts +12 -0
- package/build/services/activities/await.js +114 -0
- package/build/services/activities/cycle.d.ts +19 -0
- package/build/services/activities/cycle.js +112 -0
- package/build/services/activities/hook.d.ts +27 -0
- package/build/services/activities/hook.js +168 -0
- package/build/services/activities/index.d.ts +19 -0
- package/build/services/activities/index.js +20 -0
- package/build/services/activities/interrupt.d.ts +16 -0
- package/build/services/activities/interrupt.js +158 -0
- package/build/services/activities/signal.d.ts +20 -0
- package/build/services/activities/signal.js +134 -0
- package/build/services/activities/trigger.d.ts +37 -0
- package/build/services/activities/trigger.js +246 -0
- package/build/services/activities/worker.d.ts +12 -0
- package/build/services/activities/worker.js +106 -0
- package/build/services/collator/index.d.ts +111 -0
- package/build/services/collator/index.js +293 -0
- package/build/services/compiler/deployer.d.ts +40 -0
- package/build/services/compiler/deployer.js +488 -0
- package/build/services/compiler/index.d.ts +32 -0
- package/build/services/compiler/index.js +112 -0
- package/build/services/compiler/validator.d.ts +34 -0
- package/build/services/compiler/validator.js +147 -0
- package/build/services/connector/factory.d.ts +22 -0
- package/build/services/connector/factory.js +99 -0
- package/build/services/connector/index.d.ts +30 -0
- package/build/services/connector/index.js +54 -0
- package/build/services/connector/providers/ioredis.d.ts +9 -0
- package/build/services/connector/providers/ioredis.js +26 -0
- package/build/services/connector/providers/nats.d.ts +9 -0
- package/build/services/connector/providers/nats.js +34 -0
- package/build/services/connector/providers/postgres.d.ts +20 -0
- package/build/services/connector/providers/postgres.js +102 -0
- package/build/services/connector/providers/redis.d.ts +9 -0
- package/build/services/connector/providers/redis.js +38 -0
- package/build/services/engine/index.d.ts +264 -0
- package/build/services/engine/index.js +761 -0
- package/build/services/exporter/index.d.ts +44 -0
- package/build/services/exporter/index.js +126 -0
- package/build/services/hotmesh/index.d.ts +483 -0
- package/build/services/hotmesh/index.js +622 -0
- package/build/services/logger/index.d.ts +16 -0
- package/build/services/logger/index.js +54 -0
- package/build/services/mapper/index.d.ts +28 -0
- package/build/services/mapper/index.js +81 -0
- package/build/services/memflow/client.d.ts +108 -0
- package/build/services/memflow/client.js +372 -0
- package/build/services/memflow/connection.d.ts +23 -0
- package/build/services/memflow/connection.js +33 -0
- package/build/services/memflow/context.d.ts +143 -0
- package/build/services/memflow/context.js +299 -0
- package/build/services/memflow/exporter.d.ts +51 -0
- package/build/services/memflow/exporter.js +215 -0
- package/build/services/memflow/handle.d.ts +90 -0
- package/build/services/memflow/handle.js +176 -0
- package/build/services/memflow/index.d.ts +116 -0
- package/build/services/memflow/index.js +122 -0
- package/build/services/memflow/schemas/factory.d.ts +29 -0
- package/build/services/memflow/schemas/factory.js +2492 -0
- package/build/services/memflow/search.d.ts +142 -0
- package/build/services/memflow/search.js +320 -0
- package/build/services/memflow/worker.d.ts +124 -0
- package/build/services/memflow/worker.js +514 -0
- package/build/services/memflow/workflow/all.d.ts +7 -0
- package/build/services/memflow/workflow/all.js +15 -0
- package/build/services/memflow/workflow/common.d.ts +20 -0
- package/build/services/memflow/workflow/common.js +47 -0
- package/build/services/memflow/workflow/context.d.ts +6 -0
- package/build/services/memflow/workflow/context.js +45 -0
- package/build/services/memflow/workflow/contextMethods.d.ts +14 -0
- package/build/services/memflow/workflow/contextMethods.js +33 -0
- package/build/services/memflow/workflow/didRun.d.ts +7 -0
- package/build/services/memflow/workflow/didRun.js +22 -0
- package/build/services/memflow/workflow/emit.d.ts +11 -0
- package/build/services/memflow/workflow/emit.js +29 -0
- package/build/services/memflow/workflow/enrich.d.ts +9 -0
- package/build/services/memflow/workflow/enrich.js +17 -0
- package/build/services/memflow/workflow/execChild.d.ts +18 -0
- package/build/services/memflow/workflow/execChild.js +102 -0
- package/build/services/memflow/workflow/execHook.d.ts +65 -0
- package/build/services/memflow/workflow/execHook.js +73 -0
- package/build/services/memflow/workflow/hook.d.ts +9 -0
- package/build/services/memflow/workflow/hook.js +56 -0
- package/build/services/memflow/workflow/index.d.ts +74 -0
- package/build/services/memflow/workflow/index.js +87 -0
- package/build/services/memflow/workflow/interrupt.d.ts +9 -0
- package/build/services/memflow/workflow/interrupt.js +24 -0
- package/build/services/memflow/workflow/isSideEffectAllowed.d.ts +10 -0
- package/build/services/memflow/workflow/isSideEffectAllowed.js +33 -0
- package/build/services/memflow/workflow/proxyActivities.d.ts +20 -0
- package/build/services/memflow/workflow/proxyActivities.js +97 -0
- package/build/services/memflow/workflow/random.d.ts +6 -0
- package/build/services/memflow/workflow/random.js +16 -0
- package/build/services/memflow/workflow/searchMethods.d.ts +6 -0
- package/build/services/memflow/workflow/searchMethods.js +25 -0
- package/build/services/memflow/workflow/signal.d.ts +7 -0
- package/build/services/memflow/workflow/signal.js +28 -0
- package/build/services/memflow/workflow/sleepFor.d.ts +8 -0
- package/build/services/memflow/workflow/sleepFor.js +35 -0
- package/build/services/memflow/workflow/trace.d.ts +14 -0
- package/build/services/memflow/workflow/trace.js +33 -0
- package/build/services/memflow/workflow/waitFor.d.ts +8 -0
- package/build/services/memflow/workflow/waitFor.js +35 -0
- package/build/services/meshcall/index.d.ts +194 -0
- package/build/services/meshcall/index.js +452 -0
- package/build/services/meshcall/schemas/factory.d.ts +9 -0
- package/build/services/meshcall/schemas/factory.js +189 -0
- package/build/services/meshdata/index.d.ts +795 -0
- package/build/services/meshdata/index.js +1235 -0
- package/build/services/meshos/index.d.ts +293 -0
- package/build/services/meshos/index.js +547 -0
- package/build/services/pipe/functions/array.d.ts +17 -0
- package/build/services/pipe/functions/array.js +74 -0
- package/build/services/pipe/functions/bitwise.d.ts +9 -0
- package/build/services/pipe/functions/bitwise.js +24 -0
- package/build/services/pipe/functions/conditional.d.ts +13 -0
- package/build/services/pipe/functions/conditional.js +36 -0
- package/build/services/pipe/functions/cron.d.ts +12 -0
- package/build/services/pipe/functions/cron.js +40 -0
- package/build/services/pipe/functions/date.d.ts +58 -0
- package/build/services/pipe/functions/date.js +171 -0
- package/build/services/pipe/functions/index.d.ts +29 -0
- package/build/services/pipe/functions/index.js +30 -0
- package/build/services/pipe/functions/json.d.ts +5 -0
- package/build/services/pipe/functions/json.js +12 -0
- package/build/services/pipe/functions/logical.d.ts +5 -0
- package/build/services/pipe/functions/logical.js +12 -0
- package/build/services/pipe/functions/math.d.ts +42 -0
- package/build/services/pipe/functions/math.js +184 -0
- package/build/services/pipe/functions/number.d.ts +21 -0
- package/build/services/pipe/functions/number.js +60 -0
- package/build/services/pipe/functions/object.d.ts +25 -0
- package/build/services/pipe/functions/object.js +81 -0
- package/build/services/pipe/functions/string.d.ts +23 -0
- package/build/services/pipe/functions/string.js +69 -0
- package/build/services/pipe/functions/symbol.d.ts +12 -0
- package/build/services/pipe/functions/symbol.js +33 -0
- package/build/services/pipe/functions/unary.d.ts +7 -0
- package/build/services/pipe/functions/unary.js +18 -0
- package/build/services/pipe/index.d.ts +48 -0
- package/build/services/pipe/index.js +242 -0
- package/build/services/quorum/index.d.ts +90 -0
- package/build/services/quorum/index.js +263 -0
- package/build/services/reporter/index.d.ts +50 -0
- package/build/services/reporter/index.js +348 -0
- package/build/services/router/config/index.d.ts +11 -0
- package/build/services/router/config/index.js +36 -0
- package/build/services/router/consumption/index.d.ts +34 -0
- package/build/services/router/consumption/index.js +395 -0
- package/build/services/router/error-handling/index.d.ts +8 -0
- package/build/services/router/error-handling/index.js +98 -0
- package/build/services/router/index.d.ts +57 -0
- package/build/services/router/index.js +121 -0
- package/build/services/router/lifecycle/index.d.ts +27 -0
- package/build/services/router/lifecycle/index.js +80 -0
- package/build/services/router/telemetry/index.d.ts +11 -0
- package/build/services/router/telemetry/index.js +32 -0
- package/build/services/router/throttling/index.d.ts +23 -0
- package/build/services/router/throttling/index.js +76 -0
- package/build/services/search/factory.d.ts +7 -0
- package/build/services/search/factory.js +24 -0
- package/build/services/search/index.d.ts +23 -0
- package/build/services/search/index.js +10 -0
- package/build/services/search/providers/postgres/postgres.d.ts +25 -0
- package/build/services/search/providers/postgres/postgres.js +149 -0
- package/build/services/search/providers/redis/ioredis.d.ts +19 -0
- package/build/services/search/providers/redis/ioredis.js +121 -0
- package/build/services/search/providers/redis/redis.d.ts +19 -0
- package/build/services/search/providers/redis/redis.js +134 -0
- package/build/services/serializer/index.d.ts +42 -0
- package/build/services/serializer/index.js +282 -0
- package/build/services/store/cache.d.ts +67 -0
- package/build/services/store/cache.js +128 -0
- package/build/services/store/factory.d.ts +8 -0
- package/build/services/store/factory.js +24 -0
- package/build/services/store/index.d.ts +89 -0
- package/build/services/store/index.js +9 -0
- package/build/services/store/providers/postgres/kvsql.d.ts +168 -0
- package/build/services/store/providers/postgres/kvsql.js +198 -0
- package/build/services/store/providers/postgres/kvtables.d.ts +20 -0
- package/build/services/store/providers/postgres/kvtables.js +441 -0
- package/build/services/store/providers/postgres/kvtransaction.d.ts +36 -0
- package/build/services/store/providers/postgres/kvtransaction.js +248 -0
- package/build/services/store/providers/postgres/kvtypes/hash.d.ts +60 -0
- package/build/services/store/providers/postgres/kvtypes/hash.js +1287 -0
- package/build/services/store/providers/postgres/kvtypes/list.d.ts +33 -0
- package/build/services/store/providers/postgres/kvtypes/list.js +194 -0
- package/build/services/store/providers/postgres/kvtypes/string.d.ts +20 -0
- package/build/services/store/providers/postgres/kvtypes/string.js +115 -0
- package/build/services/store/providers/postgres/kvtypes/zset.d.ts +41 -0
- package/build/services/store/providers/postgres/kvtypes/zset.js +214 -0
- package/build/services/store/providers/postgres/postgres.d.ts +145 -0
- package/build/services/store/providers/postgres/postgres.js +1036 -0
- 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 +180 -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/store/providers/store-initializable.d.ts +5 -0
- package/build/services/store/providers/store-initializable.js +2 -0
- package/build/services/stream/factory.d.ts +8 -0
- package/build/services/stream/factory.js +37 -0
- package/build/services/stream/index.d.ts +69 -0
- package/build/services/stream/index.js +11 -0
- package/build/services/stream/providers/nats/nats.d.ts +60 -0
- package/build/services/stream/providers/nats/nats.js +225 -0
- package/build/services/stream/providers/postgres/kvtables.d.ts +3 -0
- package/build/services/stream/providers/postgres/kvtables.js +146 -0
- package/build/services/stream/providers/postgres/postgres.d.ts +107 -0
- package/build/services/stream/providers/postgres/postgres.js +519 -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/stream/providers/stream-initializable.d.ts +4 -0
- package/build/services/stream/providers/stream-initializable.js +2 -0
- package/build/services/sub/factory.d.ts +7 -0
- package/build/services/sub/factory.js +29 -0
- package/build/services/sub/index.d.ts +22 -0
- package/build/services/sub/index.js +10 -0
- package/build/services/sub/providers/nats/nats.d.ts +19 -0
- package/build/services/sub/providers/nats/nats.js +105 -0
- package/build/services/sub/providers/postgres/postgres.d.ts +19 -0
- package/build/services/sub/providers/postgres/postgres.js +92 -0
- package/build/services/sub/providers/redis/ioredis.d.ts +17 -0
- package/build/services/sub/providers/redis/ioredis.js +81 -0
- package/build/services/sub/providers/redis/redis.d.ts +17 -0
- package/build/services/sub/providers/redis/redis.js +72 -0
- package/build/services/task/index.d.ts +36 -0
- package/build/services/task/index.js +206 -0
- package/build/services/telemetry/index.d.ts +52 -0
- package/build/services/telemetry/index.js +306 -0
- package/build/services/worker/index.d.ts +77 -0
- package/build/services/worker/index.js +197 -0
- package/package.json +1 -1
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -38
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
- package/typedoc.json +0 -47
- package/types/activity.ts +0 -268
- package/types/app.ts +0 -20
- package/types/async.ts +0 -6
- package/types/cache.ts +0 -1
- package/types/collator.ts +0 -9
- package/types/error.ts +0 -56
- package/types/exporter.ts +0 -102
- package/types/hook.ts +0 -44
- package/types/hotmesh.ts +0 -314
- package/types/index.ts +0 -306
- package/types/job.ts +0 -233
- package/types/logger.ts +0 -8
- package/types/manifest.ts +0 -70
- package/types/map.ts +0 -5
- package/types/memflow.ts +0 -645
- package/types/meshcall.ts +0 -235
- package/types/meshdata.ts +0 -278
- package/types/ms.d.ts +0 -7
- package/types/nats.ts +0 -270
- package/types/pipe.ts +0 -90
- package/types/postgres.ts +0 -114
- package/types/provider.ts +0 -161
- package/types/quorum.ts +0 -167
- package/types/redis.ts +0 -404
- package/types/serializer.ts +0 -40
- package/types/stats.ts +0 -117
- package/types/stream.ts +0 -231
- package/types/task.ts +0 -7
- package/types/telemetry.ts +0 -16
- package/types/transition.ts +0 -20
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NatsStreamService = void 0;
|
|
4
|
+
const index_1 = require("../../index");
|
|
5
|
+
const key_1 = require("../../../../modules/key");
|
|
6
|
+
const enums_1 = require("../../../../modules/enums");
|
|
7
|
+
const utils_1 = require("../../../../modules/utils");
|
|
8
|
+
class NatsStreamService extends index_1.StreamService {
|
|
9
|
+
constructor(streamClient, storeClient, config = {}) {
|
|
10
|
+
super(streamClient, storeClient, config);
|
|
11
|
+
this.jetstream = streamClient.jetstream();
|
|
12
|
+
}
|
|
13
|
+
async init(namespace, appId, logger) {
|
|
14
|
+
this.namespace = namespace;
|
|
15
|
+
this.logger = logger;
|
|
16
|
+
this.appId = appId;
|
|
17
|
+
this.jsm = await this.jetstream.jetstreamManager();
|
|
18
|
+
}
|
|
19
|
+
mintKey(type, params) {
|
|
20
|
+
if (!this.namespace)
|
|
21
|
+
throw new Error('namespace not set');
|
|
22
|
+
return key_1.KeyService.mintKey(this.namespace, type, {
|
|
23
|
+
...params,
|
|
24
|
+
appId: this.appId,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
transact() {
|
|
28
|
+
return {};
|
|
29
|
+
}
|
|
30
|
+
async createStream(streamName) {
|
|
31
|
+
try {
|
|
32
|
+
const config = {
|
|
33
|
+
name: streamName,
|
|
34
|
+
subjects: [`${streamName}.*`],
|
|
35
|
+
retention: 'workqueue',
|
|
36
|
+
storage: 'memory',
|
|
37
|
+
num_replicas: 1,
|
|
38
|
+
};
|
|
39
|
+
await this.jsm.streams.add(config);
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
this.logger.error(`Error creating stream ${streamName}`, { error });
|
|
44
|
+
throw error;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
async deleteStream(streamName) {
|
|
48
|
+
try {
|
|
49
|
+
await this.jsm.streams.delete(streamName);
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
this.logger.error(`Error deleting stream ${streamName}`, { error });
|
|
54
|
+
throw error;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
async createConsumerGroup(streamName, groupName) {
|
|
58
|
+
try {
|
|
59
|
+
const consumerConfig = {
|
|
60
|
+
durable_name: groupName,
|
|
61
|
+
deliver_group: groupName,
|
|
62
|
+
ack_policy: 'explicit',
|
|
63
|
+
ack_wait: 30 * 1000,
|
|
64
|
+
max_deliver: 10,
|
|
65
|
+
};
|
|
66
|
+
await this.jsm.consumers.add(streamName, consumerConfig);
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
this.logger.error(`Error creating consumer group ${groupName} for stream ${streamName}`, { error });
|
|
71
|
+
throw error;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
async deleteConsumerGroup(streamName, groupName) {
|
|
75
|
+
try {
|
|
76
|
+
await this.jsm.consumers.delete(streamName, groupName);
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
this.logger.error(`Error deleting consumer group ${groupName} for stream ${streamName}`, { error });
|
|
81
|
+
throw error;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
async publishMessages(streamName, messages, options) {
|
|
85
|
+
try {
|
|
86
|
+
const publishPromises = messages.map(async (message) => {
|
|
87
|
+
const subject = `${streamName}.message`;
|
|
88
|
+
const ack = await this.jetstream.publish(subject, Buffer.from(message));
|
|
89
|
+
return ack;
|
|
90
|
+
});
|
|
91
|
+
const acks = await Promise.all(publishPromises);
|
|
92
|
+
return acks.map((ack) => ack.seq.toString());
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
this.logger.error(`Error publishing messages to ${streamName}`, {
|
|
96
|
+
error,
|
|
97
|
+
});
|
|
98
|
+
throw error;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
async consumeMessages(streamName, groupName, consumerName, options) {
|
|
102
|
+
try {
|
|
103
|
+
const consumer = await this.jetstream.consumers.get(streamName, groupName);
|
|
104
|
+
const messages = [];
|
|
105
|
+
const fetchOptions = {
|
|
106
|
+
max_messages: options?.batchSize || 1,
|
|
107
|
+
expires: options?.blockTimeout || enums_1.HMSH_BLOCK_TIME_MS,
|
|
108
|
+
};
|
|
109
|
+
const fetchedMessages = await consumer.fetch(fetchOptions);
|
|
110
|
+
for await (const msg of fetchedMessages) {
|
|
111
|
+
messages.push({
|
|
112
|
+
id: msg.seq.toString(),
|
|
113
|
+
data: (0, utils_1.parseStreamMessage)(msg.string()),
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
return messages;
|
|
117
|
+
}
|
|
118
|
+
catch (error) {
|
|
119
|
+
this.logger.error(`Error consuming messages from ${streamName}`, {
|
|
120
|
+
error,
|
|
121
|
+
});
|
|
122
|
+
throw error;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
async ackAndDelete(streamName, groupName, messageIds) {
|
|
126
|
+
try {
|
|
127
|
+
await this.acknowledgeMessages(streamName, groupName, messageIds);
|
|
128
|
+
return messageIds.length;
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
this.logger.error(`Error in ack and delete for stream ${streamName}`, {
|
|
132
|
+
error,
|
|
133
|
+
});
|
|
134
|
+
throw error;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
async acknowledgeMessages(streamName, groupName, messageIds, options) {
|
|
138
|
+
//no-op
|
|
139
|
+
return messageIds.length;
|
|
140
|
+
}
|
|
141
|
+
async deleteMessages(streamName, groupName, messageIds, options) {
|
|
142
|
+
try {
|
|
143
|
+
await Promise.all(messageIds.map((id) => this.jsm.streams.deleteMessage(streamName, parseInt(id))));
|
|
144
|
+
return messageIds.length;
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
this.logger.error(`Error deleting messages from ${streamName}`, {
|
|
148
|
+
error,
|
|
149
|
+
});
|
|
150
|
+
throw error;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
async retryMessages(streamName, groupName, options) {
|
|
154
|
+
return [];
|
|
155
|
+
}
|
|
156
|
+
async getStreamStats(streamName) {
|
|
157
|
+
try {
|
|
158
|
+
const info = await this.jsm.streams.info(streamName);
|
|
159
|
+
return {
|
|
160
|
+
messageCount: info.state.messages,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
this.logger.error(`Error getting stats for ${streamName}`, { error });
|
|
165
|
+
throw error;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
async getStreamDepth(streamName) {
|
|
169
|
+
try {
|
|
170
|
+
const info = await this.jsm.streams.info(streamName);
|
|
171
|
+
return info.state.messages;
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
this.logger.error(`Error getting depth for ${streamName}`, { error });
|
|
175
|
+
throw error;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
async getStreamDepths(streamNames) {
|
|
179
|
+
try {
|
|
180
|
+
const results = await Promise.all(streamNames.map(async ({ stream }) => ({
|
|
181
|
+
stream,
|
|
182
|
+
depth: await this.getStreamDepth(stream),
|
|
183
|
+
})));
|
|
184
|
+
return results;
|
|
185
|
+
}
|
|
186
|
+
catch (error) {
|
|
187
|
+
this.logger.error('Error getting multiple stream depths', { error });
|
|
188
|
+
throw error;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
async trimStream(streamName, options) {
|
|
192
|
+
try {
|
|
193
|
+
// Retrieve the current stream info
|
|
194
|
+
const streamInfo = await this.jsm.streams.info(streamName);
|
|
195
|
+
const config = { ...streamInfo.config }; // Clone to avoid direct mutation
|
|
196
|
+
// Apply new limits based on options
|
|
197
|
+
if (options.maxLen !== undefined) {
|
|
198
|
+
config.max_msgs = options.maxLen;
|
|
199
|
+
}
|
|
200
|
+
if (options.maxAge !== undefined) {
|
|
201
|
+
config.max_age = options.maxAge * 1e9; // Convert maxAge to nanoseconds
|
|
202
|
+
}
|
|
203
|
+
// Update the stream with the modified config
|
|
204
|
+
await this.jsm.streams.update(streamName, config);
|
|
205
|
+
return 0; // Trimming is applied automatically based on updated config
|
|
206
|
+
}
|
|
207
|
+
catch (error) {
|
|
208
|
+
this.logger.error(`Error trimming stream ${streamName}`, { error });
|
|
209
|
+
throw error;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
getProviderSpecificFeatures() {
|
|
213
|
+
return {
|
|
214
|
+
supportsBatching: true,
|
|
215
|
+
supportsDeadLetterQueue: true,
|
|
216
|
+
supportsOrdering: true,
|
|
217
|
+
supportsTrimming: true,
|
|
218
|
+
supportsRetry: false,
|
|
219
|
+
supportsNotifications: false,
|
|
220
|
+
maxMessageSize: 1024 * 1024,
|
|
221
|
+
maxBatchSize: 256,
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
exports.NatsStreamService = NatsStreamService;
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getNotificationChannelName = exports.deploySchema = void 0;
|
|
4
|
+
async function deploySchema(streamClient, appId, logger) {
|
|
5
|
+
const client = 'connect' in streamClient && 'release' in streamClient
|
|
6
|
+
? await streamClient.connect()
|
|
7
|
+
: streamClient;
|
|
8
|
+
const releaseClient = 'release' in streamClient;
|
|
9
|
+
try {
|
|
10
|
+
const lockId = getAdvisoryLockId(appId);
|
|
11
|
+
const lockResult = await client.query('SELECT pg_try_advisory_lock($1) AS locked', [lockId]);
|
|
12
|
+
if (lockResult.rows[0].locked) {
|
|
13
|
+
await client.query('BEGIN');
|
|
14
|
+
const schemaName = appId.replace(/[^a-zA-Z0-9_]/g, '_');
|
|
15
|
+
const tableName = `${schemaName}.streams`;
|
|
16
|
+
await createTables(client, schemaName, tableName);
|
|
17
|
+
await createNotificationTriggers(client, schemaName, tableName);
|
|
18
|
+
await client.query('COMMIT');
|
|
19
|
+
await client.query('SELECT pg_advisory_unlock($1)', [lockId]);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
throw new Error('Table deployment in progress by another process.');
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
logger.error('Error deploying schema', { error });
|
|
27
|
+
throw error;
|
|
28
|
+
}
|
|
29
|
+
finally {
|
|
30
|
+
if (releaseClient) {
|
|
31
|
+
await client.release();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
exports.deploySchema = deploySchema;
|
|
36
|
+
function getAdvisoryLockId(appId) {
|
|
37
|
+
return hashStringToInt(appId);
|
|
38
|
+
}
|
|
39
|
+
function hashStringToInt(str) {
|
|
40
|
+
let hash = 0;
|
|
41
|
+
for (let i = 0; i < str.length; i++) {
|
|
42
|
+
hash = (hash << 5) - hash + str.charCodeAt(i);
|
|
43
|
+
hash |= 0; // Convert to 32-bit integer
|
|
44
|
+
}
|
|
45
|
+
return Math.abs(hash);
|
|
46
|
+
}
|
|
47
|
+
async function createTables(client, schemaName, tableName) {
|
|
48
|
+
await client.query(`CREATE SCHEMA IF NOT EXISTS ${schemaName};`);
|
|
49
|
+
// Main table creation with partitions
|
|
50
|
+
await client.query(`
|
|
51
|
+
CREATE TABLE IF NOT EXISTS ${tableName} (
|
|
52
|
+
id BIGSERIAL,
|
|
53
|
+
stream_name TEXT NOT NULL,
|
|
54
|
+
group_name TEXT NOT NULL DEFAULT 'ENGINE',
|
|
55
|
+
message TEXT NOT NULL,
|
|
56
|
+
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
57
|
+
reserved_at TIMESTAMPTZ,
|
|
58
|
+
reserved_by TEXT,
|
|
59
|
+
expired_at TIMESTAMPTZ,
|
|
60
|
+
PRIMARY KEY (stream_name, id)
|
|
61
|
+
) PARTITION BY HASH (stream_name);
|
|
62
|
+
`);
|
|
63
|
+
for (let i = 0; i < 8; i++) {
|
|
64
|
+
const partitionTableName = `${schemaName}.streams_part_${i}`;
|
|
65
|
+
await client.query(`
|
|
66
|
+
CREATE TABLE IF NOT EXISTS ${partitionTableName}
|
|
67
|
+
PARTITION OF ${tableName}
|
|
68
|
+
FOR VALUES WITH (modulus 8, remainder ${i});
|
|
69
|
+
`);
|
|
70
|
+
}
|
|
71
|
+
// Index for active messages
|
|
72
|
+
await client.query(`
|
|
73
|
+
CREATE INDEX IF NOT EXISTS idx_streams_active_messages
|
|
74
|
+
ON ${tableName} (group_name, stream_name, reserved_at, id)
|
|
75
|
+
WHERE reserved_at IS NULL AND expired_at IS NULL;
|
|
76
|
+
`);
|
|
77
|
+
// Optimized index for the simplified fetchMessages query
|
|
78
|
+
await client.query(`
|
|
79
|
+
CREATE INDEX IF NOT EXISTS idx_streams_message_fetch
|
|
80
|
+
ON ${tableName} (stream_name, group_name, id)
|
|
81
|
+
WHERE expired_at IS NULL;
|
|
82
|
+
`);
|
|
83
|
+
// Index for expired messages
|
|
84
|
+
await client.query(`
|
|
85
|
+
CREATE INDEX IF NOT EXISTS idx_streams_expired_at
|
|
86
|
+
ON ${tableName} (expired_at);
|
|
87
|
+
`);
|
|
88
|
+
// New index for stream stats optimization
|
|
89
|
+
await client.query(`
|
|
90
|
+
CREATE INDEX IF NOT EXISTS idx_stream_name_expired_at
|
|
91
|
+
ON ${tableName} (stream_name)
|
|
92
|
+
WHERE expired_at IS NULL;
|
|
93
|
+
`);
|
|
94
|
+
// TODO: revisit this index when solving automated cleanup
|
|
95
|
+
// Optional index for querying by creation time, if needed
|
|
96
|
+
// await client.query(`
|
|
97
|
+
// CREATE INDEX IF NOT EXISTS idx_streams_created_at
|
|
98
|
+
// ON ${tableName} (created_at);
|
|
99
|
+
// `);
|
|
100
|
+
}
|
|
101
|
+
async function createNotificationTriggers(client, schemaName, tableName) {
|
|
102
|
+
// Create the notification function
|
|
103
|
+
await client.query(`
|
|
104
|
+
CREATE OR REPLACE FUNCTION ${schemaName}.notify_new_stream_message()
|
|
105
|
+
RETURNS TRIGGER AS $$
|
|
106
|
+
DECLARE
|
|
107
|
+
channel_name TEXT;
|
|
108
|
+
payload JSON;
|
|
109
|
+
BEGIN
|
|
110
|
+
-- Create channel name: stream_{stream_name}_{group_name}
|
|
111
|
+
-- Truncate if too long (PostgreSQL channel names limited to 63 chars)
|
|
112
|
+
channel_name := 'stream_' || NEW.stream_name || '_' || NEW.group_name;
|
|
113
|
+
IF length(channel_name) > 63 THEN
|
|
114
|
+
channel_name := left(channel_name, 63);
|
|
115
|
+
END IF;
|
|
116
|
+
|
|
117
|
+
-- Create payload with message details
|
|
118
|
+
payload := json_build_object(
|
|
119
|
+
'id', NEW.id,
|
|
120
|
+
'stream_name', NEW.stream_name,
|
|
121
|
+
'group_name', NEW.group_name,
|
|
122
|
+
'created_at', extract(epoch from NEW.created_at)
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
-- Send notification
|
|
126
|
+
PERFORM pg_notify(channel_name, payload::text);
|
|
127
|
+
|
|
128
|
+
RETURN NEW;
|
|
129
|
+
END;
|
|
130
|
+
$$ LANGUAGE plpgsql;
|
|
131
|
+
`);
|
|
132
|
+
// Create trigger only on the main table - it will automatically apply to all partitions
|
|
133
|
+
await client.query(`
|
|
134
|
+
DROP TRIGGER IF EXISTS notify_stream_insert ON ${tableName};
|
|
135
|
+
CREATE TRIGGER notify_stream_insert
|
|
136
|
+
AFTER INSERT ON ${tableName}
|
|
137
|
+
FOR EACH ROW
|
|
138
|
+
EXECUTE FUNCTION ${schemaName}.notify_new_stream_message();
|
|
139
|
+
`);
|
|
140
|
+
}
|
|
141
|
+
function getNotificationChannelName(streamName, groupName) {
|
|
142
|
+
const channelName = `stream_${streamName}_${groupName}`;
|
|
143
|
+
// PostgreSQL channel names are limited to 63 characters
|
|
144
|
+
return channelName.length > 63 ? channelName.substring(0, 63) : channelName;
|
|
145
|
+
}
|
|
146
|
+
exports.getNotificationChannelName = getNotificationChannelName;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { ILogger } from '../../../logger';
|
|
2
|
+
import { KeyType } from '../../../../modules/key';
|
|
3
|
+
import { StreamService } from '../../index';
|
|
4
|
+
import { KeyStoreParams, StringAnyType } from '../../../../types';
|
|
5
|
+
import { PostgresClientType } from '../../../../types/postgres';
|
|
6
|
+
import { PublishMessageConfig, StreamConfig, StreamMessage, StreamStats } from '../../../../types/stream';
|
|
7
|
+
import { ProviderClient, ProviderTransaction } from '../../../../types/provider';
|
|
8
|
+
declare class PostgresStreamService extends StreamService<PostgresClientType & ProviderClient, any> {
|
|
9
|
+
namespace: string;
|
|
10
|
+
appId: string;
|
|
11
|
+
logger: ILogger;
|
|
12
|
+
private notificationConsumers;
|
|
13
|
+
private notificationHandlerBound;
|
|
14
|
+
private fallbackIntervalId;
|
|
15
|
+
constructor(streamClient: PostgresClientType & ProviderClient, storeClient: ProviderClient, config?: StreamConfig);
|
|
16
|
+
init(namespace: string, appId: string, logger: ILogger): Promise<void>;
|
|
17
|
+
private isNotificationsEnabled;
|
|
18
|
+
private getFallbackInterval;
|
|
19
|
+
private getNotificationTimeout;
|
|
20
|
+
private startFallbackPoller;
|
|
21
|
+
private checkForMissedMessages;
|
|
22
|
+
private handleNotification;
|
|
23
|
+
private fetchAndDeliverMessages;
|
|
24
|
+
private getConsumerKey;
|
|
25
|
+
mintKey(type: KeyType, params: KeyStoreParams): string;
|
|
26
|
+
transact(): ProviderTransaction;
|
|
27
|
+
getTableName(): string;
|
|
28
|
+
safeName(appId: string): string;
|
|
29
|
+
createStream(streamName: string): Promise<boolean>;
|
|
30
|
+
deleteStream(streamName: string): Promise<boolean>;
|
|
31
|
+
createConsumerGroup(streamName: string, groupName: string): Promise<boolean>;
|
|
32
|
+
deleteConsumerGroup(streamName: string, groupName: string): Promise<boolean>;
|
|
33
|
+
/**
|
|
34
|
+
* `publishMessages` can be roped into a transaction by the `store`
|
|
35
|
+
* service. If so, it will add the SQL and params to the
|
|
36
|
+
* transaction. [Process Overview]: The engine keeps a reference
|
|
37
|
+
* to the `store` and `stream` providers; it asks the `store` to
|
|
38
|
+
* create a transaction and then starts adding store commands to the
|
|
39
|
+
* transaction. The engine then calls the router to publish a
|
|
40
|
+
* message using the `stream` provider (which the router keeps
|
|
41
|
+
* a reference to), and provides the transaction object.
|
|
42
|
+
* The `stream` provider then calls this method to generate
|
|
43
|
+
* the SQL and params for the transaction (but, of course, the sql
|
|
44
|
+
* is not executed until the engine calls the `exec` method on
|
|
45
|
+
* the transaction object provided by `store`).
|
|
46
|
+
*
|
|
47
|
+
* NOTE: this strategy keeps `stream` and `store` operations separate but
|
|
48
|
+
* allows calls to the stream to be roped into a single SQL transaction.
|
|
49
|
+
*/
|
|
50
|
+
publishMessages(streamName: string, messages: string[], options?: PublishMessageConfig): Promise<string[] | ProviderTransaction>;
|
|
51
|
+
_publishMessages(streamName: string, messages: string[]): {
|
|
52
|
+
sql: string;
|
|
53
|
+
params: any[];
|
|
54
|
+
};
|
|
55
|
+
consumeMessages(streamName: string, groupName: string, consumerName: string, options?: {
|
|
56
|
+
batchSize?: number;
|
|
57
|
+
blockTimeout?: number;
|
|
58
|
+
autoAck?: boolean;
|
|
59
|
+
reservationTimeout?: number;
|
|
60
|
+
enableBackoff?: boolean;
|
|
61
|
+
initialBackoff?: number;
|
|
62
|
+
maxBackoff?: number;
|
|
63
|
+
maxRetries?: number;
|
|
64
|
+
enableNotifications?: boolean;
|
|
65
|
+
notificationCallback?: (messages: StreamMessage[]) => void;
|
|
66
|
+
}): Promise<StreamMessage[]>;
|
|
67
|
+
private shouldUseNotifications;
|
|
68
|
+
private setupNotificationConsumer;
|
|
69
|
+
stopNotificationConsumer(streamName: string, groupName: string): Promise<void>;
|
|
70
|
+
private fetchMessages;
|
|
71
|
+
ackAndDelete(streamName: string, groupName: string, messageIds: string[]): Promise<number>;
|
|
72
|
+
acknowledgeMessages(streamName: string, groupName: string, messageIds: string[], options?: StringAnyType): Promise<number>;
|
|
73
|
+
deleteMessages(streamName: string, groupName: string, messageIds: string[], options?: StringAnyType): Promise<number>;
|
|
74
|
+
retryMessages(streamName: string, groupName: string, options?: {
|
|
75
|
+
consumerName?: string;
|
|
76
|
+
minIdleTime?: number;
|
|
77
|
+
messageIds?: string[];
|
|
78
|
+
delay?: number;
|
|
79
|
+
maxRetries?: number;
|
|
80
|
+
limit?: number;
|
|
81
|
+
}): Promise<StreamMessage[]>;
|
|
82
|
+
getStreamStats(streamName: string): Promise<StreamStats>;
|
|
83
|
+
getStreamDepth(streamName: string): Promise<number>;
|
|
84
|
+
getStreamDepths(streamNames: {
|
|
85
|
+
stream: string;
|
|
86
|
+
}[]): Promise<{
|
|
87
|
+
stream: string;
|
|
88
|
+
depth: number;
|
|
89
|
+
}[]>;
|
|
90
|
+
trimStream(streamName: string, options: {
|
|
91
|
+
maxLen?: number;
|
|
92
|
+
maxAge?: number;
|
|
93
|
+
exactLimit?: boolean;
|
|
94
|
+
}): Promise<number>;
|
|
95
|
+
getProviderSpecificFeatures(): {
|
|
96
|
+
supportsBatching: boolean;
|
|
97
|
+
supportsDeadLetterQueue: boolean;
|
|
98
|
+
supportsOrdering: boolean;
|
|
99
|
+
supportsTrimming: boolean;
|
|
100
|
+
supportsRetry: boolean;
|
|
101
|
+
supportsNotifications: boolean;
|
|
102
|
+
maxMessageSize: number;
|
|
103
|
+
maxBatchSize: number;
|
|
104
|
+
};
|
|
105
|
+
cleanup(): Promise<void>;
|
|
106
|
+
}
|
|
107
|
+
export { PostgresStreamService };
|