@hahnpro/flow-sdk 9.2.0 → 9.4.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/dist/FlowApplication.js +34 -9
- package/dist/FlowLogger.js +7 -1
- package/dist/nats.d.ts +1 -0
- package/dist/nats.js +14 -1
- package/package.json +7 -7
package/dist/FlowApplication.js
CHANGED
|
@@ -4,6 +4,7 @@ exports.FlowApplication = void 0;
|
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
require("reflect-metadata");
|
|
6
6
|
const hpc_api_1 = require("@hahnpro/hpc-api");
|
|
7
|
+
const jetstream_1 = require("@nats-io/jetstream");
|
|
7
8
|
const cloudevents_1 = require("cloudevents");
|
|
8
9
|
const lodash_1 = require("lodash");
|
|
9
10
|
const object_sizeof_1 = tslib_1.__importDefault(require("object-sizeof"));
|
|
@@ -177,15 +178,15 @@ class FlowApplication {
|
|
|
177
178
|
return;
|
|
178
179
|
}
|
|
179
180
|
try {
|
|
180
|
-
const
|
|
181
|
-
if ((0, object_sizeof_1.default)(
|
|
182
|
-
|
|
181
|
+
const formatedEvent = event.format();
|
|
182
|
+
if ((0, object_sizeof_1.default)(formatedEvent) > MAX_EVENT_SIZE_BYTES) {
|
|
183
|
+
formatedEvent.data = (0, utils_1.truncate)(formatedEvent.data);
|
|
183
184
|
}
|
|
184
185
|
const natsEvent = {
|
|
185
186
|
source: `hpc/flow-application`,
|
|
186
187
|
type: `${nats_1.natsFlowsPrefixFlowDeployment}.flowlogs`,
|
|
187
188
|
subject: `${this.context.deploymentId}`,
|
|
188
|
-
data:
|
|
189
|
+
data: formatedEvent,
|
|
189
190
|
};
|
|
190
191
|
await (0, nats_1.publishNatsEvent)(this.logger, this.natsConnection, natsEvent);
|
|
191
192
|
return true;
|
|
@@ -250,11 +251,11 @@ class FlowApplication {
|
|
|
250
251
|
getProperties() {
|
|
251
252
|
return this.contextManager.getProperties();
|
|
252
253
|
}
|
|
253
|
-
async consumeNatsMessagesOfConsumer(consumer,
|
|
254
|
+
async consumeNatsMessagesOfConsumer(consumer, consumeOptions) {
|
|
254
255
|
if (this.natsMessageIterator) {
|
|
255
256
|
await this.natsMessageIterator.close();
|
|
256
257
|
}
|
|
257
|
-
this.natsMessageIterator = await consumer.consume(
|
|
258
|
+
this.natsMessageIterator = await consumer.consume(consumeOptions);
|
|
258
259
|
for await (const msg of this.natsMessageIterator) {
|
|
259
260
|
try {
|
|
260
261
|
let event;
|
|
@@ -313,9 +314,23 @@ class FlowApplication {
|
|
|
313
314
|
...nats_1.defaultConsumerConfig,
|
|
314
315
|
name: `flow-deployment-${this.context.deploymentId}`,
|
|
315
316
|
filter_subject: `${nats_1.natsFlowsPrefixFlowDeployment}.${this.context.deploymentId}.*`,
|
|
317
|
+
inactive_threshold: 10 * 60 * 1_000_000_000,
|
|
316
318
|
};
|
|
317
319
|
const consumer = await (0, nats_1.getOrCreateConsumer)(this.logger, this._natsConnection, nats_1.FLOWS_STREAM_NAME, consumerOptions.name, consumerOptions);
|
|
318
|
-
|
|
320
|
+
const handleNatsStatus = async () => {
|
|
321
|
+
try {
|
|
322
|
+
this.logger.debug('ConsumerService: Reconnected to Nats and re-creating non-durable consumers');
|
|
323
|
+
await (0, nats_1.getOrCreateConsumer)(this.logger, this._natsConnection, nats_1.FLOWS_STREAM_NAME, consumerOptions.name, consumerOptions);
|
|
324
|
+
this.consumeNatsMessagesOfConsumer(consumer, { expires: 10 * 1_000_000_000 });
|
|
325
|
+
}
|
|
326
|
+
catch (e) {
|
|
327
|
+
this.logger.error('NATS Status-AsyncIterator is not available, cannot listen. Due to error:');
|
|
328
|
+
this.logger.error(e);
|
|
329
|
+
(0, nats_1.natsEventListener)(this._natsConnection, this.logger, handleNatsStatus);
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
(0, nats_1.natsEventListener)(this._natsConnection, this.logger, handleNatsStatus);
|
|
333
|
+
this.consumeNatsMessagesOfConsumer(consumer, { expires: 10 * 1_000_000_000 });
|
|
319
334
|
}
|
|
320
335
|
catch (e) {
|
|
321
336
|
await logErrorAndExit(`Could not set up consumer for deployment messages exchanges: ${e}`);
|
|
@@ -438,8 +453,18 @@ class FlowApplication {
|
|
|
438
453
|
if (this.amqpConnection) {
|
|
439
454
|
await this.amqpConnection.close();
|
|
440
455
|
}
|
|
441
|
-
if (this.
|
|
442
|
-
await this._natsConnection
|
|
456
|
+
if (this._natsConnection && !this._natsConnection.isClosed()) {
|
|
457
|
+
await (0, jetstream_1.jetstreamManager)(this._natsConnection).then((jsm) => {
|
|
458
|
+
jsm.consumers
|
|
459
|
+
.delete(nats_1.FLOWS_STREAM_NAME, `flow-deployment-${this.context.deploymentId}`)
|
|
460
|
+
.then(() => {
|
|
461
|
+
this.logger.error(`Deleted consumer for flow deployment ${this.context.deploymentId}`);
|
|
462
|
+
})
|
|
463
|
+
.catch((err) => {
|
|
464
|
+
this.logger.error(`Could not delete consumer for flow deployment ${this.context.deploymentId}: ${err.message}`);
|
|
465
|
+
});
|
|
466
|
+
});
|
|
467
|
+
await this._natsConnection.drain();
|
|
443
468
|
}
|
|
444
469
|
await this.natsMessageIterator?.close();
|
|
445
470
|
await this._natsConnection?.close();
|
package/dist/FlowLogger.js
CHANGED
|
@@ -36,7 +36,13 @@ class FlowLogger {
|
|
|
36
36
|
}
|
|
37
37
|
publish(message, level, options) {
|
|
38
38
|
if (this.publishEvent) {
|
|
39
|
-
const
|
|
39
|
+
const data = message?.message
|
|
40
|
+
? message
|
|
41
|
+
: {
|
|
42
|
+
...message,
|
|
43
|
+
message: typeof message === 'string' ? message : JSON.stringify(message),
|
|
44
|
+
};
|
|
45
|
+
const event = new FlowEvent_1.FlowEvent(this.metadata, data, `flow.log.${level}`);
|
|
40
46
|
this.publishEvent(event);
|
|
41
47
|
}
|
|
42
48
|
switch (level) {
|
package/dist/nats.d.ts
CHANGED
|
@@ -7,5 +7,6 @@ export declare const natsFlowsPrefixFlowDeployment = "fs.flowdeployment";
|
|
|
7
7
|
export declare const defaultConsumerConfig: ConsumerConfig;
|
|
8
8
|
export declare const FLOWS_STREAM_NAME = "flows";
|
|
9
9
|
export declare function getOrCreateConsumer(logger: Logger, natsConnection: NatsConnection, streamName: string, consumerName: string, options: Partial<ConsumerConfig>): Promise<Consumer>;
|
|
10
|
+
export declare function natsEventListener(nc: NatsConnection, logger: Logger, reconnectHandler: () => void): Promise<void>;
|
|
10
11
|
export declare function publishNatsEvent<T>(logger: Logger, nc: NatsConnection, event: NatsEvent<T>, subject?: string): Promise<PubAck>;
|
|
11
12
|
export declare function createNatsConnection(config: ConnectionOptions): Promise<NatsConnection>;
|
package/dist/nats.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.FLOWS_STREAM_NAME = exports.defaultConsumerConfig = exports.natsFlowsPrefixFlowDeployment = void 0;
|
|
4
4
|
exports.getOrCreateConsumer = getOrCreateConsumer;
|
|
5
|
+
exports.natsEventListener = natsEventListener;
|
|
5
6
|
exports.publishNatsEvent = publishNatsEvent;
|
|
6
7
|
exports.createNatsConnection = createNatsConnection;
|
|
7
8
|
const transport_node_1 = require("@nats-io/transport-node");
|
|
@@ -51,6 +52,18 @@ async function getOrCreateConsumer(logger, natsConnection, streamName, consumerN
|
|
|
51
52
|
}
|
|
52
53
|
return await (0, jetstream_1.jetstream)(natsConnection).consumers.get(streamName, consumerName);
|
|
53
54
|
}
|
|
55
|
+
async function natsEventListener(nc, logger, reconnectHandler) {
|
|
56
|
+
const statusAsyncIterator = nc?.status();
|
|
57
|
+
if (!statusAsyncIterator) {
|
|
58
|
+
logger.error('NATS Status-AsyncIterator is not available, cannot listen for events to re-create consumers at reconnects');
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
for await (const status of statusAsyncIterator) {
|
|
62
|
+
if (status.type === 'reconnect') {
|
|
63
|
+
reconnectHandler();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
54
67
|
async function publishNatsEvent(logger, nc, event, subject) {
|
|
55
68
|
if (!nc || nc.isClosed()) {
|
|
56
69
|
return;
|
|
@@ -70,7 +83,7 @@ async function publishNatsEvent(logger, nc, event, subject) {
|
|
|
70
83
|
async function createNatsConnection(config) {
|
|
71
84
|
const servers = config?.servers ?? process.env.NATS_SERVERS?.split(',') ?? [];
|
|
72
85
|
const reconnect = config?.reconnect ?? (process.env.NATS_RECONNECT ?? 'true') === 'true';
|
|
73
|
-
let maxReconnectAttempts = config?.maxReconnectAttempts ?? parseInt(process.env.NATS_MAX_RECONNECT_ATTEMPTS ?? '
|
|
86
|
+
let maxReconnectAttempts = config?.maxReconnectAttempts ?? parseInt(process.env.NATS_MAX_RECONNECT_ATTEMPTS ?? '-1', 10);
|
|
74
87
|
if (isNaN(maxReconnectAttempts)) {
|
|
75
88
|
maxReconnectAttempts = 10;
|
|
76
89
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hahnpro/flow-sdk",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.4.0",
|
|
4
4
|
"description": "SDK for building Flow Modules",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
@@ -24,10 +24,10 @@
|
|
|
24
24
|
"access": "public"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@hahnpro/hpc-api": "2025.
|
|
28
|
-
"@nats-io/jetstream": "3.0
|
|
29
|
-
"@nats-io/nats-core": "3.0
|
|
30
|
-
"@nats-io/transport-node": "3.0
|
|
27
|
+
"@hahnpro/hpc-api": "2025.3.1",
|
|
28
|
+
"@nats-io/jetstream": "3.1.0",
|
|
29
|
+
"@nats-io/nats-core": "3.1.0",
|
|
30
|
+
"@nats-io/transport-node": "3.1.0",
|
|
31
31
|
"amqp-connection-manager": "4.1.14",
|
|
32
32
|
"amqplib": "0.10.8",
|
|
33
33
|
"class-transformer": "0.5.1",
|
|
@@ -44,9 +44,9 @@
|
|
|
44
44
|
"@types/amqplib": "0.10.7",
|
|
45
45
|
"@types/jest": "30.0.0",
|
|
46
46
|
"@types/lodash": "4.17.20",
|
|
47
|
-
"@types/node": "22.16.
|
|
47
|
+
"@types/node": "22.16.5",
|
|
48
48
|
"class-validator-jsonschema": "5.0.2",
|
|
49
|
-
"jest": "30.0.
|
|
49
|
+
"jest": "30.0.5",
|
|
50
50
|
"typescript": "5.8.3"
|
|
51
51
|
},
|
|
52
52
|
"peerDependencies": {
|