dt-common-device 7.6.9 → 7.6.11
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 +2 -0
- package/dist/pms/webhookQueue/interfaces/IWebhookQueue.d.ts +1 -49
- package/dist/pms/webhookQueue/interfaces/index.d.ts +0 -1
- package/dist/pms/webhookQueue/interfaces/index.js +0 -1
- package/dist/pms/webhookQueue/services/WebhookQueueService.d.ts +12 -23
- package/dist/pms/webhookQueue/services/WebhookQueueService.js +32 -206
- package/dist/pms/webhookQueue/services/index.d.ts +0 -3
- package/dist/pms/webhookQueue/services/index.js +0 -3
- package/dist/pms/webhookQueue/types/webhook.types.d.ts +0 -21
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -59,3 +59,5 @@ var config_1 = require("./config/config");
|
|
|
59
59
|
Object.defineProperty(exports, "initialize", { enumerable: true, get: function () { return config_1.initialize; } });
|
|
60
60
|
Object.defineProperty(exports, "getConfig", { enumerable: true, get: function () { return config_1.getConfig; } });
|
|
61
61
|
Object.defineProperty(exports, "shutdown", { enumerable: true, get: function () { return config_1.shutdown; } });
|
|
62
|
+
//Export PMS Webhook Queue
|
|
63
|
+
__exportStar(require("./pms/index"), exports);
|
|
@@ -1,55 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IWebhookQueueOptions } from "../types/webhook.types";
|
|
2
2
|
export interface IWebhookQueue {
|
|
3
3
|
/**
|
|
4
4
|
* Add a webhook to the appropriate queue based on propertyId and pmsType
|
|
5
5
|
*/
|
|
6
6
|
addWebhookToQueue(propertyId: string, pmsType: string, webhookData: any, options?: IWebhookQueueOptions): Promise<string>;
|
|
7
|
-
/**
|
|
8
|
-
* Get the status of a specific webhook queue
|
|
9
|
-
*/
|
|
10
|
-
getQueueStatus(propertyId: string, pmsType: string): Promise<IWebhookQueueStatus>;
|
|
11
|
-
/**
|
|
12
|
-
* Get status of all webhook queues for a property
|
|
13
|
-
*/
|
|
14
|
-
getAllPropertyQueueStatuses(propertyId: string): Promise<Record<string, IWebhookQueueStatus>>;
|
|
15
|
-
/**
|
|
16
|
-
* Get detailed metrics for a specific queue
|
|
17
|
-
*/
|
|
18
|
-
getQueueMetrics(propertyId: string, pmsType: string): Promise<IWebhookQueueMetrics>;
|
|
19
|
-
/**
|
|
20
|
-
* Clean up completed and failed jobs from a specific queue
|
|
21
|
-
*/
|
|
22
|
-
cleanupQueue(propertyId: string, pmsType: string): Promise<void>;
|
|
23
|
-
/**
|
|
24
|
-
* Pause a specific queue
|
|
25
|
-
*/
|
|
26
|
-
pauseQueue(propertyId: string, pmsType: string): Promise<void>;
|
|
27
|
-
/**
|
|
28
|
-
* Resume a paused queue
|
|
29
|
-
*/
|
|
30
|
-
resumeQueue(propertyId: string, pmsType: string): Promise<void>;
|
|
31
|
-
/**
|
|
32
|
-
* Get all active queues
|
|
33
|
-
*/
|
|
34
|
-
getActiveQueues(): Promise<string[]>;
|
|
35
|
-
/**
|
|
36
|
-
* Shutdown all queues and workers
|
|
37
|
-
*/
|
|
38
|
-
shutdown(): Promise<void>;
|
|
39
|
-
/**
|
|
40
|
-
* Check if a queue exists
|
|
41
|
-
*/
|
|
42
|
-
queueExists(propertyId: string, pmsType: string): Promise<boolean>;
|
|
43
|
-
/**
|
|
44
|
-
* Get queue configuration
|
|
45
|
-
*/
|
|
46
|
-
getQueueConfig(propertyId: string, pmsType: string): Promise<any>;
|
|
47
|
-
/**
|
|
48
|
-
* Update queue configuration
|
|
49
|
-
*/
|
|
50
|
-
updateQueueConfig(propertyId: string, pmsType: string, config: Partial<any>): Promise<void>;
|
|
51
|
-
/**
|
|
52
|
-
* Set webhook processor function for a specific queue
|
|
53
|
-
*/
|
|
54
|
-
setWebhookProcessor(propertyId: string, pmsType: string, processor: (webhookData: any, pmsType: string) => Promise<any>): Promise<void>;
|
|
55
7
|
}
|
|
@@ -1,27 +1,16 @@
|
|
|
1
|
-
import { IWebhookQueue } from "../interfaces";
|
|
2
|
-
import {
|
|
1
|
+
import { IWebhookQueue } from "../interfaces/IWebhookQueue";
|
|
2
|
+
import { IWebhookQueueOptions } from "../types/webhook.types";
|
|
3
3
|
export declare class WebhookQueueService implements IWebhookQueue {
|
|
4
|
-
private
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
getQueueStatus(propertyId: string, pmsType: string): Promise<IWebhookQueueStatus>;
|
|
11
|
-
getAllPropertyQueueStatuses(propertyId: string): Promise<Record<string, IWebhookQueueStatus>>;
|
|
12
|
-
getQueueMetrics(propertyId: string, pmsType: string): Promise<IWebhookQueueMetrics>;
|
|
13
|
-
cleanupQueue(propertyId: string, pmsType: string): Promise<void>;
|
|
14
|
-
pauseQueue(propertyId: string, pmsType: string): Promise<void>;
|
|
15
|
-
resumeQueue(propertyId: string, pmsType: string): Promise<void>;
|
|
16
|
-
getActiveQueues(): Promise<string[]>;
|
|
17
|
-
shutdown(): Promise<void>;
|
|
18
|
-
queueExists(propertyId: string, pmsType: string): Promise<boolean>;
|
|
19
|
-
getQueueConfig(propertyId: string, pmsType: string): Promise<any>;
|
|
20
|
-
updateQueueConfig(propertyId: string, pmsType: string, config: Partial<any>): Promise<void>;
|
|
4
|
+
private readonly webhookQueues;
|
|
5
|
+
/**
|
|
6
|
+
* Generate queue name based on propertyId and pmsType
|
|
7
|
+
* Format: propertyId_pmsType_webhook
|
|
8
|
+
*/
|
|
9
|
+
private generateQueueName;
|
|
21
10
|
/**
|
|
22
|
-
*
|
|
11
|
+
* Add a webhook to the appropriate queue based on propertyId and pmsType
|
|
12
|
+
* Creates queue if it doesn't exist
|
|
23
13
|
*/
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
private getOrCreateQueue;
|
|
14
|
+
addWebhookToQueue(propertyId: string, pmsType: string, webhookData: any, options?: IWebhookQueueOptions): Promise<string>;
|
|
15
|
+
static getOrCreateQueue(queueKey: string, queues: Map<string, any>): any;
|
|
27
16
|
}
|
|
@@ -39,226 +39,52 @@ var __setFunctionName = (this && this.__setFunctionName) || function (f, name, p
|
|
|
39
39
|
};
|
|
40
40
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
41
|
exports.WebhookQueueService = void 0;
|
|
42
|
-
const bullmq_1 = require("bullmq");
|
|
43
|
-
const ioredis_1 = require("ioredis");
|
|
44
42
|
const typedi_1 = require("typedi");
|
|
45
|
-
const
|
|
43
|
+
const redis_1 = require("../../../db/redis");
|
|
46
44
|
let WebhookQueueService = (() => {
|
|
47
45
|
let _classDecorators = [(0, typedi_1.Service)()];
|
|
48
46
|
let _classDescriptor;
|
|
49
47
|
let _classExtraInitializers = [];
|
|
50
48
|
let _classThis;
|
|
51
49
|
var WebhookQueueService = _classThis = class {
|
|
52
|
-
constructor(
|
|
53
|
-
this.webhookQueues = new Map();
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
...config,
|
|
62
|
-
};
|
|
63
|
-
this.redisConnection = new ioredis_1.Redis({
|
|
64
|
-
host: this.config.redisHost,
|
|
65
|
-
port: this.config.redisPort,
|
|
66
|
-
maxRetriesPerRequest: null,
|
|
67
|
-
enableReadyCheck: false,
|
|
68
|
-
});
|
|
50
|
+
constructor() {
|
|
51
|
+
this.webhookQueues = new Map(); // BullMQ Queue instances
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Generate queue name based on propertyId and pmsType
|
|
55
|
+
* Format: propertyId_pmsType_webhook
|
|
56
|
+
*/
|
|
57
|
+
generateQueueName(propertyId, pmsType) {
|
|
58
|
+
return `${propertyId}_${pmsType}_webhook`;
|
|
69
59
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
60
|
+
/**
|
|
61
|
+
* Add a webhook to the appropriate queue based on propertyId and pmsType
|
|
62
|
+
* Creates queue if it doesn't exist
|
|
63
|
+
*/
|
|
64
|
+
async addWebhookToQueue(propertyId, pmsType, webhookData, options) {
|
|
65
|
+
const queueName = this.generateQueueName(propertyId, pmsType);
|
|
66
|
+
// Get or create queue using the static method
|
|
67
|
+
const queue = WebhookQueueService.getOrCreateQueue(queueName, this.webhookQueues);
|
|
68
|
+
// Add job to queue immediately with 5 minute TTL
|
|
69
|
+
const job = await queue.add("webhook-job", {
|
|
74
70
|
propertyId,
|
|
75
71
|
pmsType,
|
|
76
72
|
webhookData,
|
|
77
73
|
timestamp: new Date().toISOString(),
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
attempts: options.attempts || this.config.maxRetries,
|
|
84
|
-
backoff: options.backoff || {
|
|
85
|
-
type: "exponential",
|
|
86
|
-
delay: this.config.backoffDelay,
|
|
87
|
-
},
|
|
88
|
-
removeOnComplete: this.config.removeOnComplete,
|
|
89
|
-
removeOnFail: this.config.removeOnFail,
|
|
90
|
-
timeout: this.config.jobTimeout,
|
|
91
|
-
};
|
|
92
|
-
const job = await queue.add("process_webhook", jobData, jobOptions);
|
|
74
|
+
}, {
|
|
75
|
+
removeOnComplete: { age: 5 * 60 }, // Remove after 5 minutes
|
|
76
|
+
removeOnFail: { age: 5 * 60 }, // Remove failed jobs after 5 minutes
|
|
77
|
+
attempts: 1, // Only try once
|
|
78
|
+
});
|
|
93
79
|
return job.id;
|
|
94
80
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
completed: 0,
|
|
103
|
-
failed: 0,
|
|
104
|
-
delayed: 0,
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
const [waiting, active, completed, failed, delayed] = await Promise.all([
|
|
108
|
-
queue.getWaiting(),
|
|
109
|
-
queue.getActive(),
|
|
110
|
-
queue.getCompleted(),
|
|
111
|
-
queue.getFailed(),
|
|
112
|
-
queue.getDelayed(),
|
|
113
|
-
]);
|
|
114
|
-
return {
|
|
115
|
-
waiting: waiting.length,
|
|
116
|
-
active: active.length,
|
|
117
|
-
completed: completed.length,
|
|
118
|
-
failed: failed.length,
|
|
119
|
-
delayed: delayed.length,
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
async getAllPropertyQueueStatuses(propertyId) {
|
|
123
|
-
const pmsTypes = ["CLOUDBEDS", "HOTELKEY", "STAYNTOUCH"];
|
|
124
|
-
const statuses = {};
|
|
125
|
-
for (const pmsType of pmsTypes) {
|
|
126
|
-
statuses[pmsType] = await this.getQueueStatus(propertyId, pmsType);
|
|
127
|
-
}
|
|
128
|
-
return statuses;
|
|
129
|
-
}
|
|
130
|
-
async getQueueMetrics(propertyId, pmsType) {
|
|
131
|
-
const queueName = this.getQueueName(propertyId, pmsType);
|
|
132
|
-
const queue = this.webhookQueues.get(queueName);
|
|
133
|
-
if (!queue) {
|
|
134
|
-
return {
|
|
135
|
-
totalProcessed: 0,
|
|
136
|
-
totalFailed: 0,
|
|
137
|
-
averageProcessingTime: 0,
|
|
138
|
-
queueName,
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
const [completed, failed] = await Promise.all([
|
|
142
|
-
queue.getCompleted(),
|
|
143
|
-
queue.getFailed(),
|
|
144
|
-
]);
|
|
145
|
-
const totalProcessed = completed.length;
|
|
146
|
-
const totalFailed = failed.length;
|
|
147
|
-
// Calculate average processing time from completed jobs
|
|
148
|
-
let totalProcessingTime = 0;
|
|
149
|
-
let processedWithTime = 0;
|
|
150
|
-
for (const job of completed) {
|
|
151
|
-
if (job.processedOn && job.timestamp) {
|
|
152
|
-
totalProcessingTime += job.processedOn - job.timestamp;
|
|
153
|
-
processedWithTime++;
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
const averageProcessingTime = processedWithTime > 0 ? totalProcessingTime / processedWithTime : 0;
|
|
157
|
-
const lastProcessedAt = completed.length > 0
|
|
158
|
-
? new Date(completed[0].processedOn || 0).toISOString()
|
|
159
|
-
: undefined;
|
|
160
|
-
return {
|
|
161
|
-
totalProcessed,
|
|
162
|
-
totalFailed,
|
|
163
|
-
averageProcessingTime,
|
|
164
|
-
lastProcessedAt,
|
|
165
|
-
queueName,
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
async cleanupQueue(propertyId, pmsType) {
|
|
169
|
-
const queueName = this.getQueueName(propertyId, pmsType);
|
|
170
|
-
const queue = this.webhookQueues.get(queueName);
|
|
171
|
-
if (queue) {
|
|
172
|
-
// BullMQ v5: clean(grace, limit, type)
|
|
173
|
-
await queue.clean(3600000, 1000, "completed"); // Clean completed jobs older than 1 hour
|
|
174
|
-
await queue.clean(7200000, 1000, "failed"); // Clean failed jobs older than 2 hours
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
async pauseQueue(propertyId, pmsType) {
|
|
178
|
-
const queueName = this.getQueueName(propertyId, pmsType);
|
|
179
|
-
const queue = this.webhookQueues.get(queueName);
|
|
180
|
-
if (queue) {
|
|
181
|
-
await queue.pause();
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
async resumeQueue(propertyId, pmsType) {
|
|
185
|
-
const queueName = this.getQueueName(propertyId, pmsType);
|
|
186
|
-
const queue = this.webhookQueues.get(queueName);
|
|
187
|
-
if (queue) {
|
|
188
|
-
await queue.resume();
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
async getActiveQueues() {
|
|
192
|
-
return Array.from(this.webhookQueues.keys());
|
|
193
|
-
}
|
|
194
|
-
async shutdown() {
|
|
195
|
-
// Stop all workers
|
|
196
|
-
for (const worker of this.workers.values()) {
|
|
197
|
-
await worker.stopProcessing();
|
|
198
|
-
}
|
|
199
|
-
// Close all queues
|
|
200
|
-
for (const queue of this.webhookQueues.values()) {
|
|
201
|
-
await queue.close();
|
|
202
|
-
}
|
|
203
|
-
// Close Redis connection
|
|
204
|
-
await this.redisConnection.quit();
|
|
205
|
-
this.webhookQueues.clear();
|
|
206
|
-
this.workers.clear();
|
|
207
|
-
}
|
|
208
|
-
async queueExists(propertyId, pmsType) {
|
|
209
|
-
const queueName = this.getQueueName(propertyId, pmsType);
|
|
210
|
-
return this.webhookQueues.has(queueName);
|
|
211
|
-
}
|
|
212
|
-
async getQueueConfig(propertyId, pmsType) {
|
|
213
|
-
const queueName = this.getQueueName(propertyId, pmsType);
|
|
214
|
-
const queue = this.webhookQueues.get(queueName);
|
|
215
|
-
if (!queue) {
|
|
216
|
-
return null;
|
|
217
|
-
}
|
|
218
|
-
return {
|
|
219
|
-
name: queue.name,
|
|
220
|
-
client: queue.client,
|
|
221
|
-
opts: queue.opts,
|
|
222
|
-
};
|
|
223
|
-
}
|
|
224
|
-
async updateQueueConfig(propertyId, pmsType, config) {
|
|
225
|
-
// Note: BullMQ doesn't support runtime config updates
|
|
226
|
-
// This would require recreating the queue
|
|
227
|
-
throw new Error("Queue configuration updates not supported at runtime");
|
|
228
|
-
}
|
|
229
|
-
/**
|
|
230
|
-
* Set webhook processor function for a specific queue
|
|
231
|
-
*/
|
|
232
|
-
async setWebhookProcessor(propertyId, pmsType, processor) {
|
|
233
|
-
const queueName = this.getQueueName(propertyId, pmsType);
|
|
234
|
-
let worker = this.workers.get(queueName);
|
|
235
|
-
if (!worker) {
|
|
236
|
-
worker = new WebhookWorker_1.WebhookWorker(this.redisConnection);
|
|
237
|
-
this.workers.set(queueName, worker);
|
|
238
|
-
}
|
|
239
|
-
worker.setWebhookProcessor(processor);
|
|
240
|
-
await worker.startProcessing(queueName);
|
|
241
|
-
}
|
|
242
|
-
getQueueName(propertyId, pmsType) {
|
|
243
|
-
return `${propertyId}_${pmsType}_webhook`;
|
|
244
|
-
}
|
|
245
|
-
async getOrCreateQueue(queueName) {
|
|
246
|
-
if (!this.webhookQueues.has(queueName)) {
|
|
247
|
-
const queue = new bullmq_1.Queue(queueName, {
|
|
248
|
-
connection: this.redisConnection,
|
|
249
|
-
defaultJobOptions: {
|
|
250
|
-
removeOnComplete: this.config.removeOnComplete,
|
|
251
|
-
removeOnFail: this.config.removeOnFail,
|
|
252
|
-
attempts: this.config.maxRetries,
|
|
253
|
-
backoff: {
|
|
254
|
-
type: "exponential",
|
|
255
|
-
delay: this.config.backoffDelay,
|
|
256
|
-
},
|
|
257
|
-
},
|
|
258
|
-
});
|
|
259
|
-
this.webhookQueues.set(queueName, queue);
|
|
260
|
-
}
|
|
261
|
-
return this.webhookQueues.get(queueName);
|
|
81
|
+
static getOrCreateQueue(queueKey, queues) {
|
|
82
|
+
return (queues.get(queueKey) ??
|
|
83
|
+
queues
|
|
84
|
+
.set(queueKey, new (require("bullmq").Queue)(queueKey, {
|
|
85
|
+
connection: (0, redis_1.getRedisClient)(),
|
|
86
|
+
}))
|
|
87
|
+
.get(queueKey));
|
|
262
88
|
}
|
|
263
89
|
};
|
|
264
90
|
__setFunctionName(_classThis, "WebhookQueueService");
|
|
@@ -14,7 +14,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./WebhookQueueFactory"), exports);
|
|
18
|
-
__exportStar(require("./WebhookQueueIntegration"), exports);
|
|
19
17
|
__exportStar(require("./WebhookQueueService"), exports);
|
|
20
|
-
__exportStar(require("./WebhookWorker"), exports);
|
|
@@ -36,25 +36,4 @@ export interface IWebhookQueueOptions {
|
|
|
36
36
|
delay: number;
|
|
37
37
|
};
|
|
38
38
|
}
|
|
39
|
-
export interface IWebhookProcessingResult {
|
|
40
|
-
success: boolean;
|
|
41
|
-
propertyId: string;
|
|
42
|
-
pmsType: string;
|
|
43
|
-
timestamp: string;
|
|
44
|
-
error?: string;
|
|
45
|
-
processingTime?: number;
|
|
46
|
-
}
|
|
47
|
-
export interface IWebhookQueueMetrics {
|
|
48
|
-
totalProcessed: number;
|
|
49
|
-
totalFailed: number;
|
|
50
|
-
averageProcessingTime: number;
|
|
51
|
-
lastProcessedAt?: string;
|
|
52
|
-
queueName: string;
|
|
53
|
-
}
|
|
54
39
|
export type PMS_TYPE = "CLOUDBEDS" | "HOTELKEY" | "STAYNTOUCH";
|
|
55
|
-
export interface IWebhookPayload {
|
|
56
|
-
eventType?: string;
|
|
57
|
-
propertyId?: string;
|
|
58
|
-
reservationId?: string;
|
|
59
|
-
[key: string]: any;
|
|
60
|
-
}
|