@mamindom/common 1.0.119 → 1.0.120
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/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/rmq/bootstrap-dlx.d.ts +33 -0
- package/dist/rmq/bootstrap-dlx.js +97 -0
- package/dist/rmq/index.d.ts +1 -0
- package/dist/rmq/index.js +17 -0
- package/package.json +6 -1
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -17,4 +17,5 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
17
17
|
__exportStar(require("./enum"), exports);
|
|
18
18
|
__exportStar(require("./grpc"), exports);
|
|
19
19
|
__exportStar(require("./rbac"), exports);
|
|
20
|
+
__exportStar(require("./rmq"), exports);
|
|
20
21
|
__exportStar(require("./utils"), exports);
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convention: dead-letter exchange and queue names are derived from the
|
|
3
|
+
* primary queue name. `cart_queue` → `cart.dlx` + `cart.dlq`. The `_queue`
|
|
4
|
+
* or `-queue` suffix is stripped; if absent, the whole name is used.
|
|
5
|
+
*
|
|
6
|
+
* Keeping this as a pure function (instead of env vars) prevents the class
|
|
7
|
+
* of bugs where producer and consumer disagree on DLX naming and trigger
|
|
8
|
+
* PRECONDITION_FAILED on queue declare.
|
|
9
|
+
*/
|
|
10
|
+
export declare function dlxNameFor(queue: string): string;
|
|
11
|
+
export declare function dlqNameFor(queue: string): string;
|
|
12
|
+
/**
|
|
13
|
+
* queueOptions.arguments needed for a queue that should dead-letter into its
|
|
14
|
+
* conventional DLX. Use in `app.connectMicroservice(...)` and in every
|
|
15
|
+
* `ClientsModule.registerAsync` that declares the same queue, so producer
|
|
16
|
+
* and consumer declares stay equivalent.
|
|
17
|
+
*/
|
|
18
|
+
export declare function rmqQueueDlxArguments(queue: string): {
|
|
19
|
+
'x-dead-letter-exchange': string;
|
|
20
|
+
};
|
|
21
|
+
export interface BootstrapRmqDlxOptions {
|
|
22
|
+
url: string;
|
|
23
|
+
queue: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Idempotently declares the DLX trio for the given queue: fanout exchange +
|
|
27
|
+
* DLQ queue + binding. Run once at service bootstrap, before connecting RMQ
|
|
28
|
+
* microservice. Safe to repeat — RabbitMQ no-ops on identical re-declares.
|
|
29
|
+
*
|
|
30
|
+
* Why fanout: dead-lettered messages keep their original routing key, but
|
|
31
|
+
* we want every message into the DLX to land in the DLQ regardless of key.
|
|
32
|
+
*/
|
|
33
|
+
export declare function bootstrapRmqDlx(opts: BootstrapRmqDlxOptions): Promise<void>;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.dlxNameFor = dlxNameFor;
|
|
37
|
+
exports.dlqNameFor = dlqNameFor;
|
|
38
|
+
exports.rmqQueueDlxArguments = rmqQueueDlxArguments;
|
|
39
|
+
exports.bootstrapRmqDlx = bootstrapRmqDlx;
|
|
40
|
+
const common_1 = require("@nestjs/common");
|
|
41
|
+
const amqp = __importStar(require("amqplib"));
|
|
42
|
+
/**
|
|
43
|
+
* Convention: dead-letter exchange and queue names are derived from the
|
|
44
|
+
* primary queue name. `cart_queue` → `cart.dlx` + `cart.dlq`. The `_queue`
|
|
45
|
+
* or `-queue` suffix is stripped; if absent, the whole name is used.
|
|
46
|
+
*
|
|
47
|
+
* Keeping this as a pure function (instead of env vars) prevents the class
|
|
48
|
+
* of bugs where producer and consumer disagree on DLX naming and trigger
|
|
49
|
+
* PRECONDITION_FAILED on queue declare.
|
|
50
|
+
*/
|
|
51
|
+
function dlxNameFor(queue) {
|
|
52
|
+
return `${stripQueueSuffix(queue)}.dlx`;
|
|
53
|
+
}
|
|
54
|
+
function dlqNameFor(queue) {
|
|
55
|
+
return `${stripQueueSuffix(queue)}.dlq`;
|
|
56
|
+
}
|
|
57
|
+
function stripQueueSuffix(queue) {
|
|
58
|
+
return queue.replace(/[_-]queue$/, '');
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* queueOptions.arguments needed for a queue that should dead-letter into its
|
|
62
|
+
* conventional DLX. Use in `app.connectMicroservice(...)` and in every
|
|
63
|
+
* `ClientsModule.registerAsync` that declares the same queue, so producer
|
|
64
|
+
* and consumer declares stay equivalent.
|
|
65
|
+
*/
|
|
66
|
+
function rmqQueueDlxArguments(queue) {
|
|
67
|
+
return { 'x-dead-letter-exchange': dlxNameFor(queue) };
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Idempotently declares the DLX trio for the given queue: fanout exchange +
|
|
71
|
+
* DLQ queue + binding. Run once at service bootstrap, before connecting RMQ
|
|
72
|
+
* microservice. Safe to repeat — RabbitMQ no-ops on identical re-declares.
|
|
73
|
+
*
|
|
74
|
+
* Why fanout: dead-lettered messages keep their original routing key, but
|
|
75
|
+
* we want every message into the DLX to land in the DLQ regardless of key.
|
|
76
|
+
*/
|
|
77
|
+
async function bootstrapRmqDlx(opts) {
|
|
78
|
+
const logger = new common_1.Logger('RmqDlxBootstrap');
|
|
79
|
+
const dlx = dlxNameFor(opts.queue);
|
|
80
|
+
const dlq = dlqNameFor(opts.queue);
|
|
81
|
+
const connection = await amqp.connect(opts.url);
|
|
82
|
+
try {
|
|
83
|
+
const channel = await connection.createChannel();
|
|
84
|
+
try {
|
|
85
|
+
await channel.assertExchange(dlx, 'fanout', { durable: true });
|
|
86
|
+
await channel.assertQueue(dlq, { durable: true });
|
|
87
|
+
await channel.bindQueue(dlq, dlx, '');
|
|
88
|
+
logger.log(`DLX ready for ${opts.queue}: ${dlx} → ${dlq}`);
|
|
89
|
+
}
|
|
90
|
+
finally {
|
|
91
|
+
await channel.close();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
finally {
|
|
95
|
+
await connection.close();
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './bootstrap-dlx';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./bootstrap-dlx"), exports);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mamindom/common",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.120",
|
|
4
4
|
"type": "commonjs",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -16,7 +16,9 @@
|
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
18
|
"@mamindom/core": "^1.0.4",
|
|
19
|
+
"@types/amqplib": "^0.10.5",
|
|
19
20
|
"@types/node": "^25.3.5",
|
|
21
|
+
"amqplib": "^0.10.9",
|
|
20
22
|
"prettier": "^3.8.1",
|
|
21
23
|
"typescript": "^5.9.3"
|
|
22
24
|
},
|
|
@@ -25,5 +27,8 @@
|
|
|
25
27
|
"@nestjs/common": "^11.1.16",
|
|
26
28
|
"@nestjs/config": "^4.0.3",
|
|
27
29
|
"@nestjs/microservices": "^11.1.16"
|
|
30
|
+
},
|
|
31
|
+
"peerDependencies": {
|
|
32
|
+
"amqplib": "^0.10.0"
|
|
28
33
|
}
|
|
29
34
|
}
|