dt-common-device 9.2.3 → 9.2.5
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/audit/PushAudit.js
CHANGED
|
@@ -10,8 +10,7 @@ const typedi_1 = __importDefault(require("typedi"));
|
|
|
10
10
|
const ExcludeAudits_1 = require("./ExcludeAudits");
|
|
11
11
|
async function pushAudit(data) {
|
|
12
12
|
const audit = await typedi_1.default.get(AuditUtils_1.AuditUtils).buildAuditProperties(data.auditData);
|
|
13
|
-
if (ExcludeAudits_1.excludeEvents.includes(data.auditType)
|
|
14
|
-
!ExcludeAudits_1.propertyIdsToPush.includes(data.auditData.propertyId)) {
|
|
13
|
+
if (ExcludeAudits_1.excludeEvents.includes(data.auditType)) {
|
|
15
14
|
console.log("Audit event excluded:", data.auditType);
|
|
16
15
|
}
|
|
17
16
|
else {
|
|
@@ -72,6 +72,7 @@ let HybridHttpQueue = (() => {
|
|
|
72
72
|
const earliestRequest = recentRequests[0];
|
|
73
73
|
const nextAvailableTime = earliestRequest + windowMs;
|
|
74
74
|
delay = Math.max(nextAvailableTime - now, 1000); // At least 1s delay
|
|
75
|
+
console.log(`[${new Date().toISOString()}] [HybridHttpQueue] Rate limit exceeded, calculated delay: ${delay}ms for job`);
|
|
75
76
|
}
|
|
76
77
|
// Create job data
|
|
77
78
|
const jobData = {
|
|
@@ -82,26 +83,57 @@ let HybridHttpQueue = (() => {
|
|
|
82
83
|
options,
|
|
83
84
|
timestamp: Date.now(),
|
|
84
85
|
};
|
|
86
|
+
console.log(`[${new Date().toISOString()}] [HybridHttpQueue] Adding job to queue - ${method} ${url} -> ${provider} [${connectionId}], delay: ${delay}ms`);
|
|
85
87
|
// Add job to BullMQ queue with delay
|
|
86
88
|
const jobId = await queueUtils_1.QueueUtils.addJobToQueue(queueKey, jobData, delay, this.queues);
|
|
89
|
+
console.log(`[${new Date().toISOString()}] [HybridHttpQueue] Job added to queue - JobId: ${jobId}, QueueKey: ${queueKey}`);
|
|
87
90
|
// Initialize worker if not exists
|
|
91
|
+
console.log(`[${new Date().toISOString()}] [HybridHttpQueue] Initializing worker for queue: ${queueKey}`);
|
|
88
92
|
queueUtils_1.QueueUtils.getOrCreateWorker(queueKey, this.workers, this.processHttpRequest.bind(this), this.jobResults);
|
|
93
|
+
// Verify worker was created
|
|
94
|
+
if (this.workers.has(queueKey)) {
|
|
95
|
+
console.log(`[${new Date().toISOString()}] [HybridHttpQueue] Worker confirmed for queue: ${queueKey}`);
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
console.log(`[${new Date().toISOString()}] [HybridHttpQueue] WARNING: Worker NOT found for queue: ${queueKey}`);
|
|
99
|
+
}
|
|
89
100
|
(0, config_1.getConfig)().LOGGER.info(`Request queued: ${method} ${url} -> ${provider} [${connectionId}]. Job ID: ${jobId}, Delay: ${delay}ms`);
|
|
90
101
|
// Wait for job completion and return result
|
|
91
|
-
//
|
|
92
|
-
return queueUtils_1.QueueUtils.waitForJobCompletion(jobId, queueKey,
|
|
102
|
+
// Simple: delay + windowMs + HTTP buffer timeout
|
|
103
|
+
return queueUtils_1.QueueUtils.waitForJobCompletion(jobId, queueKey, delay, windowMs);
|
|
93
104
|
}
|
|
94
105
|
async processHttpRequest(job) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
106
|
+
// Log immediately when worker picks up the job
|
|
107
|
+
const startTime = Date.now();
|
|
108
|
+
console.log(`[${new Date().toISOString()}] [Worker] processHttpRequest CALLED - JobId: ${job?.id}, QueueName: ${job?.queueName}, JobName: ${job?.name}, JobData: ${JSON.stringify(job?.data || {})}`);
|
|
109
|
+
try {
|
|
110
|
+
if (!job?.data) {
|
|
111
|
+
throw new Error(`Job ${job?.id} has no data`);
|
|
112
|
+
}
|
|
113
|
+
const { connectionId, provider, url, method, options } = job.data;
|
|
114
|
+
if (!connectionId || !provider || !url || !method) {
|
|
115
|
+
throw new Error(`Missing required job data fields. ConnectionId: ${connectionId}, Provider: ${provider}, URL: ${url}, Method: ${method}`);
|
|
116
|
+
}
|
|
117
|
+
console.log(`[${new Date().toISOString()}] [Worker] Processing job - JobId: ${job.id}, ${method} ${url} -> ${provider} [${connectionId}]`);
|
|
118
|
+
// Check rate limit before processing
|
|
119
|
+
const allowed = await rateLimit_utils_1.RateLimitUtils.isRateLimitAllowed(connectionId, provider, this.rateLimitConfigs);
|
|
120
|
+
if (!allowed) {
|
|
121
|
+
// This shouldn't happen since we calculate delay, but handle it gracefully
|
|
122
|
+
console.log(`[${new Date().toISOString()}] [Worker] Job ${job.id} still rate limited, waiting for window to expire...`);
|
|
123
|
+
(0, config_1.getConfig)().LOGGER.warn(`Job ${job.id} still rate limited after delay, waiting for window to expire...`);
|
|
124
|
+
await queueUtils_1.QueueUtils.waitForRateLimitExpiry(connectionId, provider, this.rateLimitConfigs);
|
|
125
|
+
console.log(`[${new Date().toISOString()}] [Worker] Rate limit wait completed for job ${job.id}, proceeding with HTTP request`);
|
|
126
|
+
}
|
|
127
|
+
// Execute the HTTP request
|
|
128
|
+
console.log(`[${new Date().toISOString()}] [Worker] Executing HTTP request for job ${job.id}`);
|
|
129
|
+
const result = await queueUtils_1.QueueUtils.executeHttpRequest(url, method, options, connectionId, provider);
|
|
130
|
+
console.log(`[${new Date().toISOString()}] [Worker] HTTP request completed successfully for job ${job.id}`);
|
|
131
|
+
return result;
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
console.log(`[${new Date().toISOString()}] [Worker] ERROR in processHttpRequest for job ${job?.id}: ${error.message}, Stack: ${error.stack}`);
|
|
135
|
+
throw error;
|
|
102
136
|
}
|
|
103
|
-
// Execute the HTTP request
|
|
104
|
-
return queueUtils_1.QueueUtils.executeHttpRequest(url, method, options, connectionId, provider);
|
|
105
137
|
}
|
|
106
138
|
async request(options) {
|
|
107
139
|
const { method, url, body, params, headers, queueOptions } = options;
|
|
@@ -8,5 +8,5 @@ export declare class QueueUtils {
|
|
|
8
8
|
static waitForRateLimitExpiry(connectionId: string, provider: string, rateLimitConfigs: Map<string, IRateLimitConfig>): Promise<void>;
|
|
9
9
|
static executeHttpRequest(url: string, method: string, options: HttpCallOption, connectionId: string, provider: string): Promise<any>;
|
|
10
10
|
static addJobToQueue(queueKey: string, jobData: any, delay: number, queues: Map<string, any>): Promise<string>;
|
|
11
|
-
static waitForJobCompletion(jobId: string, queueKey: string,
|
|
11
|
+
static waitForJobCompletion(jobId: string, queueKey: string, jobDelay?: number, windowMs?: number): Promise<any>;
|
|
12
12
|
}
|
|
@@ -25,37 +25,110 @@ class QueueUtils {
|
|
|
25
25
|
.get(queueKey));
|
|
26
26
|
}
|
|
27
27
|
static getOrCreateWorker(queueKey, workers, processFunction, jobResults) {
|
|
28
|
-
if (workers.has(queueKey))
|
|
29
|
-
|
|
28
|
+
if (workers.has(queueKey)) {
|
|
29
|
+
const existingWorker = workers.get(queueKey);
|
|
30
|
+
console.log(`[${new Date().toISOString()}] [getOrCreateWorker] Worker already exists for queue: ${queueKey}, checking if it's running...`);
|
|
31
|
+
// Check if worker is still connected/running
|
|
32
|
+
// If worker is closed or errored, recreate it
|
|
33
|
+
if (existingWorker && typeof existingWorker.isRunning === "function") {
|
|
34
|
+
const isRunning = existingWorker.isRunning();
|
|
35
|
+
console.log(`[${new Date().toISOString()}] [getOrCreateWorker] Existing worker running status: ${isRunning}`);
|
|
36
|
+
if (!isRunning) {
|
|
37
|
+
console.log(`[${new Date().toISOString()}] [getOrCreateWorker] Worker not running, closing and recreating...`);
|
|
38
|
+
try {
|
|
39
|
+
existingWorker.close();
|
|
40
|
+
}
|
|
41
|
+
catch (e) {
|
|
42
|
+
// Ignore errors when closing
|
|
43
|
+
}
|
|
44
|
+
workers.delete(queueKey);
|
|
45
|
+
// Continue to create new worker below
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
return; // Worker is running, keep using it
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
// Worker object exists but might be stale, try to use it
|
|
53
|
+
console.log(`[${new Date().toISOString()}] [getOrCreateWorker] Existing worker found but cannot verify status, keeping it`);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
console.log(`[${new Date().toISOString()}] [getOrCreateWorker] Creating new worker for queue: ${queueKey}`);
|
|
30
58
|
const { Worker } = require("bullmq");
|
|
31
|
-
|
|
59
|
+
// Wrap the process function to catch any errors during execution
|
|
60
|
+
const wrappedProcessFunction = async (job) => {
|
|
61
|
+
const wrapperStartTime = Date.now();
|
|
62
|
+
console.log(`[${new Date().toISOString()}] [Worker Wrapper] Worker picked up job - JobId: ${job?.id}, QueueKey: ${queueKey}, JobName: ${job?.name}, Delay: ${job?.opts?.delay || 0}ms`);
|
|
63
|
+
try {
|
|
64
|
+
const result = await processFunction(job);
|
|
65
|
+
const processingTime = Date.now() - wrapperStartTime;
|
|
66
|
+
console.log(`[${new Date().toISOString()}] [Worker Wrapper] Job processed successfully - JobId: ${job?.id}, ProcessingTime: ${processingTime}ms, ResultType: ${typeof result}, HasResult: ${result !== undefined && result !== null}`);
|
|
67
|
+
return result;
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
const processingTime = Date.now() - wrapperStartTime;
|
|
71
|
+
console.log(`[${new Date().toISOString()}] [Worker Wrapper] Error processing job - JobId: ${job?.id}, Error: ${error.message}, Stack: ${error.stack}, ProcessingTime: ${processingTime}ms`);
|
|
72
|
+
throw error;
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
const worker = new Worker(queueKey, wrappedProcessFunction, {
|
|
32
76
|
connection: (0, redis_1.getRedisClient)(),
|
|
33
77
|
concurrency: 1,
|
|
34
|
-
removeOnComplete:
|
|
35
|
-
removeOnFail:
|
|
78
|
+
removeOnComplete: { count: 100, age: 3600 }, // Keep completed jobs for debugging
|
|
79
|
+
removeOnFail: { count: 100, age: 3600 },
|
|
36
80
|
lockDuration: 300000,
|
|
37
|
-
stalledInterval:
|
|
81
|
+
stalledInterval: 30000, // Check for stalled jobs more frequently
|
|
38
82
|
});
|
|
83
|
+
console.log(`[${new Date().toISOString()}] [getOrCreateWorker] Worker instance created for queue: ${queueKey}`);
|
|
39
84
|
// Event handlers for job tracking
|
|
85
|
+
worker.on("active", (job) => {
|
|
86
|
+
console.log(`[${new Date().toISOString()}] [Worker Event] Job active - JobId: ${job.id}, QueueKey: ${queueKey}, JobName: ${job.name}, Data: ${JSON.stringify(job.data || {})}`);
|
|
87
|
+
});
|
|
88
|
+
worker.on("waiting", (jobId) => {
|
|
89
|
+
console.log(`[${new Date().toISOString()}] [Worker Event] Job waiting - JobId: ${jobId}, QueueKey: ${queueKey}`);
|
|
90
|
+
});
|
|
91
|
+
worker.on("delayed", (job) => {
|
|
92
|
+
console.log(`[${new Date().toISOString()}] [Worker Event] Job delayed - JobId: ${job.id}, QueueKey: ${queueKey}, Delay: ${job.opts?.delay || 0}ms`);
|
|
93
|
+
});
|
|
40
94
|
worker.on("completed", (job) => {
|
|
95
|
+
console.log(`[${new Date().toISOString()}] [Worker Event] Job completed - JobId: ${job.id}, QueueKey: ${queueKey}, ReturnValueType: ${typeof job.returnvalue}, HasReturnValue: ${job.returnvalue !== undefined}`);
|
|
41
96
|
(0, config_1.getConfig)().LOGGER.info(`HTTP request completed: ${job.id} [${queueKey}]`);
|
|
42
97
|
const result = job.returnvalue;
|
|
43
|
-
|
|
98
|
+
const jobResult = {
|
|
44
99
|
result,
|
|
45
100
|
resolved: true,
|
|
46
101
|
timestamp: Date.now(),
|
|
47
|
-
}
|
|
102
|
+
};
|
|
103
|
+
console.log(`[${new Date().toISOString()}] [Worker Event] Storing job result - JobId: ${job.id}, ResultType: ${typeof result}, Resolved: true`);
|
|
104
|
+
jobResults.set(job.id, jobResult);
|
|
105
|
+
console.log(`[${new Date().toISOString()}] [Worker Event] Job result stored in jobResults - JobId: ${job.id}, StoredResult: ${JSON.stringify(jobResult)}`);
|
|
48
106
|
});
|
|
49
107
|
worker.on("failed", (job, err) => {
|
|
108
|
+
console.log(`[${new Date().toISOString()}] [Worker Event] Job failed - JobId: ${job?.id}, QueueKey: ${queueKey}, Error: ${err.message}`);
|
|
50
109
|
(0, config_1.getConfig)().LOGGER.error(`HTTP request failed: ${job?.id} [${queueKey}], Error: ${err.message}`);
|
|
51
110
|
jobResults.set(job.id, {
|
|
52
111
|
error: err.message,
|
|
53
112
|
resolved: true,
|
|
54
113
|
timestamp: Date.now(),
|
|
55
114
|
});
|
|
115
|
+
console.log(`[${new Date().toISOString()}] [Worker Event] Job error stored in jobResults - JobId: ${job?.id}`);
|
|
116
|
+
});
|
|
117
|
+
worker.on("error", (err) => {
|
|
118
|
+
console.log(`[${new Date().toISOString()}] [Worker Event] Worker error - QueueKey: ${queueKey}, Error: ${err.message}, Stack: ${err.stack}`);
|
|
119
|
+
(0, config_1.getConfig)().LOGGER.error(`Worker error for ${queueKey}: ${err.message}`);
|
|
120
|
+
});
|
|
121
|
+
worker.on("ready", () => {
|
|
122
|
+
console.log(`[${new Date().toISOString()}] [Worker Event] Worker ready - QueueKey: ${queueKey}`);
|
|
123
|
+
});
|
|
124
|
+
worker.on("closing", () => {
|
|
125
|
+
console.log(`[${new Date().toISOString()}] [Worker Event] Worker closing - QueueKey: ${queueKey}`);
|
|
126
|
+
});
|
|
127
|
+
worker.on("closed", () => {
|
|
128
|
+
console.log(`[${new Date().toISOString()}] [Worker Event] Worker closed - QueueKey: ${queueKey}`);
|
|
56
129
|
});
|
|
57
|
-
worker.on("error", (err) => (0, config_1.getConfig)().LOGGER.error(`Worker error for ${queueKey}: ${err.message}`));
|
|
58
130
|
workers.set(queueKey, worker);
|
|
131
|
+
console.log(`[${new Date().toISOString()}] [getOrCreateWorker] Worker initialized and stored for queue: ${queueKey}`);
|
|
59
132
|
(0, config_1.getConfig)().LOGGER.info(`Worker initialized for queue: ${queueKey}`);
|
|
60
133
|
}
|
|
61
134
|
static async waitForRateLimitExpiry(connectionId, provider, rateLimitConfigs) {
|
|
@@ -63,6 +136,7 @@ class QueueUtils {
|
|
|
63
136
|
const config = rateLimitConfigs.get(provider);
|
|
64
137
|
if (!config)
|
|
65
138
|
return;
|
|
139
|
+
console.log(`[${new Date().toISOString()}] [waitForRateLimitExpiry] Starting wait for ${provider} [${connectionId}]`);
|
|
66
140
|
while (true) {
|
|
67
141
|
const timestamps = await rateLimit_utils_1.RateLimitUtils.getRawRequestTimestamps(key);
|
|
68
142
|
const now = Date.now();
|
|
@@ -70,18 +144,21 @@ class QueueUtils {
|
|
|
70
144
|
const recentRequests = timestamps.filter((t) => t > windowStart);
|
|
71
145
|
if (recentRequests.length < config.maxRequests) {
|
|
72
146
|
// Rate limit not exceeded, we can proceed
|
|
147
|
+
console.log(`[${new Date().toISOString()}] [waitForRateLimitExpiry] Rate limit cleared, proceeding`);
|
|
73
148
|
break;
|
|
74
149
|
}
|
|
75
150
|
// Calculate when the earliest request will expire
|
|
76
151
|
const earliestRequest = recentRequests[0];
|
|
77
152
|
const nextAvailableTime = earliestRequest + config.windowMs;
|
|
78
153
|
const delay = Math.max(nextAvailableTime - now, 1000); // At least 1 second
|
|
154
|
+
console.log(`[${new Date().toISOString()}] [waitForRateLimitExpiry] Rate limit exceeded, waiting ${delay}ms. Requests in window: ${recentRequests.length}/${config.maxRequests}`);
|
|
79
155
|
(0, config_1.getConfig)().LOGGER.info(`Rate limit exceeded for ${provider} [${connectionId}]. Waiting ${delay}ms until next allowed request. Current requests in window: ${recentRequests.length}/${config.maxRequests}`);
|
|
80
156
|
// Wait for the calculated delay
|
|
81
157
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
82
158
|
}
|
|
83
159
|
}
|
|
84
160
|
static async executeHttpRequest(url, method, options, connectionId, provider) {
|
|
161
|
+
console.log(`[${new Date().toISOString()}] [executeHttpRequest] Starting HTTP request - ${method} ${url} -> ${provider} [${connectionId}]`);
|
|
85
162
|
(0, config_1.getConfig)().LOGGER.info(`Executing: ${method} ${url} -> ${provider} [${connectionId}]`);
|
|
86
163
|
try {
|
|
87
164
|
// Record the request first
|
|
@@ -95,11 +172,13 @@ class QueueUtils {
|
|
|
95
172
|
...(options.body && { data: options.body }),
|
|
96
173
|
...(options.params && { params: options.params }),
|
|
97
174
|
});
|
|
175
|
+
console.log(`[${new Date().toISOString()}] [executeHttpRequest] HTTP request successful - ${method} ${url} for ${provider} [${connectionId}]`);
|
|
98
176
|
(0, config_1.getConfig)().LOGGER.info(`HTTP request successful: ${method} ${url} for ${provider} [${connectionId}]`);
|
|
99
177
|
// Return only the response data
|
|
100
178
|
return response.data;
|
|
101
179
|
}
|
|
102
180
|
catch (error) {
|
|
181
|
+
console.log(`[${new Date().toISOString()}] [executeHttpRequest] HTTP request failed - ${method} ${url} for ${provider} [${connectionId}], Error: ${error.message}`);
|
|
103
182
|
(0, config_1.getConfig)().LOGGER.error(`HTTP request failed: ${error.message}`);
|
|
104
183
|
await (0, dt_audit_library_1.publishAudit)({
|
|
105
184
|
eventType: "http.request.error",
|
|
@@ -119,62 +198,77 @@ class QueueUtils {
|
|
|
119
198
|
}
|
|
120
199
|
}
|
|
121
200
|
static async addJobToQueue(queueKey, jobData, delay, queues) {
|
|
201
|
+
console.log(`[${new Date().toISOString()}] [addJobToQueue] Adding job to BullMQ queue - QueueKey: ${queueKey}, Delay: ${delay}ms`);
|
|
122
202
|
const queue = this.getOrCreateQueue(queueKey, queues);
|
|
123
203
|
const job = await queue.add("http-request", jobData, {
|
|
124
204
|
delay,
|
|
125
205
|
attempts: 1,
|
|
126
|
-
removeOnComplete: { age: 300, count:
|
|
127
|
-
removeOnFail: { age: 300, count:
|
|
206
|
+
removeOnComplete: { age: 300, count: 100 },
|
|
207
|
+
removeOnFail: { age: 300, count: 100 },
|
|
128
208
|
});
|
|
209
|
+
console.log(`[${new Date().toISOString()}] [addJobToQueue] Job added to BullMQ - JobId: ${job.id}, QueueKey: ${queueKey}, Delay: ${delay}ms`);
|
|
210
|
+
// Log queue state for debugging
|
|
211
|
+
try {
|
|
212
|
+
const [waiting, delayed, active] = await Promise.all([
|
|
213
|
+
queue.getWaitingCount(),
|
|
214
|
+
queue.getDelayedCount(),
|
|
215
|
+
queue.getActiveCount(),
|
|
216
|
+
]);
|
|
217
|
+
console.log(`[${new Date().toISOString()}] [addJobToQueue] Queue state - QueueKey: ${queueKey}, Waiting: ${waiting}, Delayed: ${delayed}, Active: ${active}`);
|
|
218
|
+
}
|
|
219
|
+
catch (e) {
|
|
220
|
+
// Ignore errors getting queue state
|
|
221
|
+
}
|
|
129
222
|
return job.id;
|
|
130
223
|
}
|
|
131
|
-
static async waitForJobCompletion(jobId, queueKey,
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
// Use 50ms for first 10 checks, then 100ms for remaining
|
|
144
|
-
// Max checks should cover the total timeout
|
|
145
|
-
const maxChecks = Math.ceil((totalTimeout - 500) / 100 + 10);
|
|
146
|
-
(0, config_1.getConfig)().LOGGER.info(`Waiting for job ${jobId}: delay=${jobDelay}ms, totalTimeout=${totalTimeout}ms, maxChecks=${maxChecks}`);
|
|
147
|
-
const checkJob = async () => {
|
|
148
|
-
if (++checkCount >= maxChecks) {
|
|
149
|
-
clearTimeout(timeoutId);
|
|
150
|
-
clearTimeout(backupTimeoutId);
|
|
151
|
-
return reject(new Error(`Job timeout: Request took too long (waited ${totalTimeout}ms, delay was ${jobDelay}ms)`));
|
|
152
|
-
}
|
|
224
|
+
static async waitForJobCompletion(jobId, queueKey, jobDelay = 0, windowMs = 60000) {
|
|
225
|
+
// Simple: delay (wait) + windowMs (execute) + HTTP timeout buffer
|
|
226
|
+
const httpTimeout = 60000;
|
|
227
|
+
const totalTimeout = jobDelay + windowMs + httpTimeout;
|
|
228
|
+
console.log(`[${new Date().toISOString()}] [waitForJobCompletion] Waiting for job ${jobId} - delay: ${jobDelay}ms, timeout: ${totalTimeout}ms`);
|
|
229
|
+
const startTime = Date.now();
|
|
230
|
+
const { Queue } = require("bullmq");
|
|
231
|
+
const queue = new Queue(queueKey, {
|
|
232
|
+
connection: (0, redis_1.getRedisClient)(),
|
|
233
|
+
});
|
|
234
|
+
return new Promise(async (resolve, reject) => {
|
|
235
|
+
const checkInterval = setInterval(async () => {
|
|
153
236
|
try {
|
|
154
|
-
const
|
|
155
|
-
if (
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
237
|
+
const job = await queue.getJob(jobId);
|
|
238
|
+
if (!job) {
|
|
239
|
+
const elapsed = Date.now() - startTime;
|
|
240
|
+
if (elapsed > totalTimeout) {
|
|
241
|
+
clearInterval(checkInterval);
|
|
242
|
+
await queue.close();
|
|
243
|
+
return reject(new Error(`Job ${jobId} not found and timeout exceeded`));
|
|
244
|
+
}
|
|
245
|
+
return; // Job not found yet, keep checking
|
|
246
|
+
}
|
|
247
|
+
const state = await job.getState();
|
|
248
|
+
if (state === "completed") {
|
|
249
|
+
console.log(`[${new Date().toISOString()}] [waitForJobCompletion] Job ${jobId} completed`);
|
|
250
|
+
clearInterval(checkInterval);
|
|
251
|
+
const result = job.returnvalue;
|
|
252
|
+
await queue.close();
|
|
253
|
+
return resolve(result);
|
|
254
|
+
}
|
|
255
|
+
if (state === "failed") {
|
|
256
|
+
console.log(`[${new Date().toISOString()}] [waitForJobCompletion] Job ${jobId} failed: ${job.failedReason}`);
|
|
257
|
+
clearInterval(checkInterval);
|
|
258
|
+
await queue.close();
|
|
259
|
+
return reject(new Error(job.failedReason || "Job failed"));
|
|
161
260
|
}
|
|
162
|
-
// Continue checking
|
|
163
|
-
timeoutId = setTimeout(checkJob, checkCount < 10 ? 50 : 100);
|
|
164
261
|
}
|
|
165
262
|
catch (error) {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
reject(
|
|
263
|
+
clearInterval(checkInterval);
|
|
264
|
+
await queue.close();
|
|
265
|
+
reject(error);
|
|
169
266
|
}
|
|
170
|
-
};
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
// Backup timeout with the calculated total timeout
|
|
176
|
-
backupTimeoutId = setTimeout(() => {
|
|
177
|
-
clearTimeout(timeoutId);
|
|
267
|
+
}, 500); // Check every 500ms
|
|
268
|
+
// Timeout
|
|
269
|
+
setTimeout(() => {
|
|
270
|
+
clearInterval(checkInterval);
|
|
271
|
+
queue.close();
|
|
178
272
|
reject(new Error(`Request timeout: Maximum wait time exceeded (${totalTimeout}ms). Job delay was ${jobDelay}ms.`));
|
|
179
273
|
}, totalTimeout);
|
|
180
274
|
});
|
|
@@ -76,7 +76,7 @@ class RateLimitUtils {
|
|
|
76
76
|
maxTimeoutWindowMs: 120000,
|
|
77
77
|
});
|
|
78
78
|
configs.set(constants_1.CONNECTION_PROVIDERS.SMARTTHINGS, {
|
|
79
|
-
maxRequests:
|
|
79
|
+
maxRequests: 30,
|
|
80
80
|
windowMs: 60000, // 1 minute
|
|
81
81
|
provider: constants_1.CONNECTION_PROVIDERS.SMARTTHINGS,
|
|
82
82
|
maxTimeoutWindowMs: 120000,
|