@palmetto/pubsub 3.2.4 → 3.3.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.
|
@@ -24,7 +24,7 @@ class SubscribedMessage {
|
|
|
24
24
|
stopSubscribe() {
|
|
25
25
|
return __awaiter(this, void 0, void 0, function* () {
|
|
26
26
|
var _a, _b;
|
|
27
|
-
(_b = (_a = this.logger).debug) === null || _b === void 0 ? void 0 : _b.call(_a, `
|
|
27
|
+
(_b = (_a = this.logger).debug) === null || _b === void 0 ? void 0 : _b.call(_a, `BullMQ closing worker for ${this.worker.name}`);
|
|
28
28
|
yield this.worker.close();
|
|
29
29
|
this.owner.removeSubscriber(this);
|
|
30
30
|
});
|
|
@@ -98,7 +98,7 @@ class BullMqSubscriber {
|
|
|
98
98
|
if (job.failedReason !== MessageRetryError.failedReason &&
|
|
99
99
|
job.failedReason !== MessageFailError.failedReason) {
|
|
100
100
|
const log = {
|
|
101
|
-
message: "
|
|
101
|
+
message: "BullMQ PubSub job failed",
|
|
102
102
|
error: (0, create_log_error_payload_js_1.createLogErrorPayload)(err),
|
|
103
103
|
extra: {
|
|
104
104
|
job: config.name,
|
|
@@ -112,7 +112,7 @@ class BullMqSubscriber {
|
|
|
112
112
|
});
|
|
113
113
|
worker.on("error", (err) => {
|
|
114
114
|
const log = {
|
|
115
|
-
message: "
|
|
115
|
+
message: "BullMQ PubSub handler exception",
|
|
116
116
|
error: (0, create_log_error_payload_js_1.createLogErrorPayload)(err),
|
|
117
117
|
extra: {
|
|
118
118
|
job: config.name,
|
|
@@ -120,22 +120,22 @@ class BullMqSubscriber {
|
|
|
120
120
|
};
|
|
121
121
|
this.logger.error(log);
|
|
122
122
|
});
|
|
123
|
-
(_b = (_a = this.logger).debug) === null || _b === void 0 ? void 0 : _b.call(_a, `
|
|
123
|
+
(_b = (_a = this.logger).debug) === null || _b === void 0 ? void 0 : _b.call(_a, `BullMQ PubSub subscriber starting for ${worker.name}`);
|
|
124
124
|
worker
|
|
125
125
|
.run()
|
|
126
126
|
.then(() => {
|
|
127
127
|
var _a, _b;
|
|
128
|
-
(_b = (_a = this.logger).debug) === null || _b === void 0 ? void 0 : _b.call(_a, `
|
|
128
|
+
(_b = (_a = this.logger).debug) === null || _b === void 0 ? void 0 : _b.call(_a, `BullMQ PubSub subscriber stopped for ${worker.name}`);
|
|
129
129
|
})
|
|
130
130
|
.catch((err) => {
|
|
131
131
|
this.logger.error({
|
|
132
|
-
message: `
|
|
132
|
+
message: `BullMQ PubSub subscriber crashed for ${worker.name}`,
|
|
133
133
|
error: (0, create_log_error_payload_js_1.createLogErrorPayload)(err),
|
|
134
134
|
});
|
|
135
135
|
});
|
|
136
136
|
const subscribedMessage = new SubscribedMessage(this, worker, this.logger);
|
|
137
137
|
this.stops.set(config, subscribedMessage);
|
|
138
|
-
(_d = (_c = this.logger).debug) === null || _d === void 0 ? void 0 : _d.call(_c, `
|
|
138
|
+
(_d = (_c = this.logger).debug) === null || _d === void 0 ? void 0 : _d.call(_c, `BullMQ PubSub subscriber started for ${worker.name}`);
|
|
139
139
|
return () => subscribedMessage.stopSubscribe();
|
|
140
140
|
});
|
|
141
141
|
}
|
package/dist/interfaces.d.ts
CHANGED
|
@@ -25,7 +25,7 @@ export type Meta = z.infer<typeof MetaSchema>;
|
|
|
25
25
|
export type BaseMessage = Record<string, unknown> & z.infer<typeof IdMetaSchema>;
|
|
26
26
|
export interface PublishMessageOptions {
|
|
27
27
|
/**
|
|
28
|
-
* The date and time at which the message should be published. Only supported by
|
|
28
|
+
* The date and time at which the message should be published. Only supported by BullMQ at this time.
|
|
29
29
|
* If the date is in the past, the message will be sent immediately.
|
|
30
30
|
*/
|
|
31
31
|
scheduledAt?: Date;
|
|
@@ -47,7 +47,7 @@ class RabbitMqPublisher {
|
|
|
47
47
|
confirm: true,
|
|
48
48
|
json: false,
|
|
49
49
|
});
|
|
50
|
-
(_b = (_a = this.logger).debug) === null || _b === void 0 ? void 0 : _b.call(_a, "
|
|
50
|
+
(_b = (_a = this.logger).debug) === null || _b === void 0 ? void 0 : _b.call(_a, "RabbitMQ created confirm channel for publisher");
|
|
51
51
|
}
|
|
52
52
|
if (!this.connected) {
|
|
53
53
|
yield this.channel.waitForConnect();
|
|
@@ -57,7 +57,7 @@ class RabbitMqPublisher {
|
|
|
57
57
|
yield this.channel.addSetup((channel) => __awaiter(this, void 0, void 0, function* () {
|
|
58
58
|
yield this.connection.assertExchange(channel, config);
|
|
59
59
|
}));
|
|
60
|
-
(_d = (_c = this.logger).debug) === null || _d === void 0 ? void 0 : _d.call(_c, `
|
|
60
|
+
(_d = (_c = this.logger).debug) === null || _d === void 0 ? void 0 : _d.call(_c, `RabbitMQ created setup for publisher for ${(0, config_js_1.getExchangeName)(config)}`);
|
|
61
61
|
this.inited.add(config);
|
|
62
62
|
}
|
|
63
63
|
return this.channel;
|
|
@@ -127,7 +127,7 @@ class RabbitMqPublisher {
|
|
|
127
127
|
.map(({ index }) => messages[index]);
|
|
128
128
|
if (failedMessages.length > 0) {
|
|
129
129
|
const allOrSome = failedMessages.length === messages.length ? "all" : "some";
|
|
130
|
-
throw new errors_js_1.PublishError(`
|
|
130
|
+
throw new errors_js_1.PublishError(`RabbitMQ ${action} ${name} failed for ${allOrSome} messages`, failedMessages);
|
|
131
131
|
}
|
|
132
132
|
});
|
|
133
133
|
}
|
|
@@ -35,7 +35,7 @@ class SubscribedMessage {
|
|
|
35
35
|
this.stop = undefined;
|
|
36
36
|
this.owner.removeSubscriber(this);
|
|
37
37
|
if (this.busy) {
|
|
38
|
-
(_b = (_a = this.logger).debug) === null || _b === void 0 ? void 0 : _b.call(_a, `
|
|
38
|
+
(_b = (_a = this.logger).debug) === null || _b === void 0 ? void 0 : _b.call(_a, `RabbitMQ subscriber waiting for ${this.queueName} handler to finish`);
|
|
39
39
|
const start = Date.now();
|
|
40
40
|
const waitDelay = 5;
|
|
41
41
|
let busyCheck = 5000 / waitDelay; // wait a few seconds before shutdown
|
|
@@ -44,7 +44,7 @@ class SubscribedMessage {
|
|
|
44
44
|
busyCheck -= waitDelay;
|
|
45
45
|
}
|
|
46
46
|
const delay = Date.now() - start;
|
|
47
|
-
(_d = (_c = this.logger).debug) === null || _d === void 0 ? void 0 : _d.call(_c, `
|
|
47
|
+
(_d = (_c = this.logger).debug) === null || _d === void 0 ? void 0 : _d.call(_c, `RabbitMQ subscriber waited ${delay}ms for ${this.queueName} handler to finish`);
|
|
48
48
|
}
|
|
49
49
|
yield s();
|
|
50
50
|
}
|
|
@@ -141,7 +141,7 @@ class RabbitMqSubscriber {
|
|
|
141
141
|
}
|
|
142
142
|
catch (err) {
|
|
143
143
|
const logPayload = {
|
|
144
|
-
message: "Unexpected error handling
|
|
144
|
+
message: "Unexpected error handling RabbitMQ message",
|
|
145
145
|
error: (0, create_log_error_payload_js_1.createLogErrorPayload)(err),
|
|
146
146
|
extra: {
|
|
147
147
|
queueName,
|
|
@@ -155,7 +155,7 @@ class RabbitMqSubscriber {
|
|
|
155
155
|
}
|
|
156
156
|
catch (err2) {
|
|
157
157
|
const logPayload2 = {
|
|
158
|
-
message: "Unexpected error handling
|
|
158
|
+
message: "Unexpected error handling RabbitMQ message during NACK attempt",
|
|
159
159
|
error: (0, create_log_error_payload_js_1.createLogErrorPayload)(err2),
|
|
160
160
|
extra: {
|
|
161
161
|
queueName,
|
|
@@ -202,14 +202,14 @@ class RabbitMqSubscriber {
|
|
|
202
202
|
try {
|
|
203
203
|
messageResult = yield subscribedMessage.onMessage(json, context);
|
|
204
204
|
logPayload = {
|
|
205
|
-
message: `
|
|
205
|
+
message: `RabbitMQ consumer handled message.`,
|
|
206
206
|
extra: Object.assign({}, context),
|
|
207
207
|
};
|
|
208
208
|
}
|
|
209
209
|
catch (err) {
|
|
210
210
|
messageResult = interfaces_js_1.MessageResult.Retry;
|
|
211
211
|
logPayload = {
|
|
212
|
-
message: `
|
|
212
|
+
message: `RabbitMQ consumer unhandled exception.`,
|
|
213
213
|
error: (0, create_log_error_payload_js_1.createLogErrorPayload)(err),
|
|
214
214
|
extra: Object.assign({}, context),
|
|
215
215
|
};
|
|
@@ -243,12 +243,12 @@ class RabbitMqSubscriber {
|
|
|
243
243
|
},
|
|
244
244
|
}));
|
|
245
245
|
if (ok) {
|
|
246
|
-
(_k = (_j = this.logger).debug) === null || _k === void 0 ? void 0 : _k.call(_j, `
|
|
246
|
+
(_k = (_j = this.logger).debug) === null || _k === void 0 ? void 0 : _k.call(_j, `RabbitMQ retry queue success`);
|
|
247
247
|
(_m = (_l = this.logger).debug) === null || _m === void 0 ? void 0 : _m.call(_l, logPayload);
|
|
248
248
|
channel.ack(msg);
|
|
249
249
|
}
|
|
250
250
|
else {
|
|
251
|
-
(_p = (_o = this.logger).debug) === null || _p === void 0 ? void 0 : _p.call(_o, `
|
|
251
|
+
(_p = (_o = this.logger).debug) === null || _p === void 0 ? void 0 : _p.call(_o, `RabbitMQ retry queue failure - nack-ing message instead`);
|
|
252
252
|
logPayload.message += " Retry publish failed.";
|
|
253
253
|
this.logger.error(logPayload);
|
|
254
254
|
channel.nack(msg, undefined, true);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@palmetto/pubsub",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.3.1",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/palmetto/galaxy"
|
|
@@ -25,12 +25,12 @@
|
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@google-cloud/pubsub": "^5.2.3",
|
|
28
|
-
"@palmetto/trace": "^0.1.
|
|
28
|
+
"@palmetto/trace": "^0.1.1",
|
|
29
29
|
"@types/amqplib": "^0",
|
|
30
30
|
"@types/node": "^24.2.1",
|
|
31
31
|
"amqp-connection-manager": "^4.1.14",
|
|
32
32
|
"amqplib": "^0.10.8",
|
|
33
|
-
"bullmq": "^5.
|
|
33
|
+
"bullmq": "^5.70.2",
|
|
34
34
|
"ts-node": "^10.9.2",
|
|
35
35
|
"typescript": "^5.8.3",
|
|
36
36
|
"vitest": "^3.2.4",
|
|
@@ -51,10 +51,10 @@
|
|
|
51
51
|
},
|
|
52
52
|
"peerDependencies": {
|
|
53
53
|
"@google-cloud/pubsub": "^5.2",
|
|
54
|
-
"@palmetto/trace": "^0.1.
|
|
54
|
+
"@palmetto/trace": "^0.1.1",
|
|
55
55
|
"amqp-connection-manager": "^4.1.14",
|
|
56
56
|
"amqplib": "^0.10.8",
|
|
57
|
-
"bullmq": "^5.
|
|
57
|
+
"bullmq": "^5.70.2",
|
|
58
58
|
"zod": "^4.1"
|
|
59
59
|
}
|
|
60
60
|
}
|
package/src/bullmq/README.md
CHANGED
package/src/rabbitmq/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @palmetto/pubsub
|
|
2
2
|
|
|
3
|
-
The
|
|
3
|
+
The RabbitMQ (AMQP) transport provider for @palmetto/pubsub
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -108,7 +108,7 @@ yarn add @palmetto/pubsub amqp-connection-manager amqplib zod
|
|
|
108
108
|
|
|
109
109
|
## Message failures
|
|
110
110
|
|
|
111
|
-
Message failures in
|
|
111
|
+
Message failures in RabbitMQ subscribers are handled using special queues and exchanges. A retry queue is used to enable retry delays. A dead-letter queue is used to store messages that fail and run out of retries.
|
|
112
112
|
|
|
113
113
|
### Retrying messages
|
|
114
114
|
|
|
@@ -119,7 +119,7 @@ These properties configure message retries:
|
|
|
119
119
|
|
|
120
120
|
#### The retry queue
|
|
121
121
|
|
|
122
|
-
The retry queue is created using the queue name and ends with `.rlq`. The queue is configured with a dead-letter exchange that sends messages back to the original queue. A retry exchange with a default name of the queue ending with `.rlx` is bound to the retry queue. When a `retryDelay` is defined, the original message is re-published into the retry exchange with an `expiration` of the `retryDelay`. When the message is at the head of the retry queue and the expiration has elapsed, then
|
|
122
|
+
The retry queue is created using the queue name and ends with `.rlq`. The queue is configured with a dead-letter exchange that sends messages back to the original queue. A retry exchange with a default name of the queue ending with `.rlx` is bound to the retry queue. When a `retryDelay` is defined, the original message is re-published into the retry exchange with an `expiration` of the `retryDelay`. When the message is at the head of the retry queue and the expiration has elapsed, then RabbitMQ removes the message from the queue and publishes it back to the original queue.
|
|
123
123
|
|
|
124
124
|
It's important to set a `retryDelay` that works for all messages of the queue. The `expiration` cannot be changed after starting. Every message must have the same expiration in order for retries to work correctly. Only the message at the head of the queue is removed at the expiration time. If there are more messages in the queue with earlier expirations, they will not be removed (re-tried) until they are at the head of the queue.
|
|
125
125
|
|
|
@@ -131,7 +131,7 @@ Messages are sent to the dead-letter exchange when the handler returns `MessageR
|
|
|
131
131
|
|
|
132
132
|
## Queue and Exchange Configuration
|
|
133
133
|
|
|
134
|
-
The simplest way to configure PubSub
|
|
134
|
+
The simplest way to configure PubSub RabbitMQ is to pass a single name for the queue and let the framework decide the rest.
|
|
135
135
|
|
|
136
136
|
```ts
|
|
137
137
|
const config: RabbitQueueExchangeConfiguration = {
|