@jetit/publisher 1.1.2 → 1.2.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/package.json
CHANGED
package/src/lib/redis/streams.js
CHANGED
|
@@ -43,6 +43,7 @@ class Streams {
|
|
|
43
43
|
var _a;
|
|
44
44
|
this.eventsListened = [];
|
|
45
45
|
this.instanceId = `${serviceName}:${(0, id_1.generateID)('HEX', 'FE')}`;
|
|
46
|
+
console.log(this.instanceId);
|
|
46
47
|
this.consumerGroupName = `cg-${serviceName}`;
|
|
47
48
|
const cleanUpInterval = (_a = parseInt(process.env['CLEANUP_INTERVAL'] || `${1000 * 60 * 60}`, 10)) !== null && _a !== void 0 ? _a : 1000 * 60 * 60;
|
|
48
49
|
setTimeout(() => this.runClear(cleanUpInterval), 3000);
|
|
@@ -52,7 +53,7 @@ class Streams {
|
|
|
52
53
|
}
|
|
53
54
|
runClear(cleanUpInterval) {
|
|
54
55
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
55
|
-
console.log('Running Publisher Clearance');
|
|
56
|
+
console.log('Running Publisher Clearance', this.eventsListened);
|
|
56
57
|
this.clearDuplicationCheckKeys();
|
|
57
58
|
for (const eventName of this.eventsListened) {
|
|
58
59
|
process.nextTick(() => tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
@@ -277,17 +278,18 @@ class Streams {
|
|
|
277
278
|
const [, streamMessages] = result[0];
|
|
278
279
|
if (!streamMessages)
|
|
279
280
|
return;
|
|
280
|
-
console.log(`Unprocessed events:
|
|
281
|
-
const transaction = this.redisGroups.multi({ pipeline: true });
|
|
281
|
+
console.log(`Unprocessed events: ${streamMessages.length}`);
|
|
282
282
|
for (const [id, data] of streamMessages) {
|
|
283
|
+
const transaction = this.redisGroups.multi({ pipeline: true });
|
|
283
284
|
const eventData = JSON.parse(data[1]);
|
|
284
285
|
// Republishing the events
|
|
285
286
|
transaction.xadd(streamName, '*', 'data', JSON.stringify(eventData));
|
|
286
287
|
transaction.publish(eventName, '');
|
|
287
288
|
transaction.xack(streamName, this.consumerGroupName, id);
|
|
289
|
+
yield transaction.exec().catch(publisherErrorHandler);
|
|
288
290
|
console.log(`Event ${eventName} with ID: ${id} published`);
|
|
291
|
+
yield transaction.exec();
|
|
289
292
|
}
|
|
290
|
-
yield transaction.exec();
|
|
291
293
|
}
|
|
292
294
|
});
|
|
293
295
|
}
|
|
@@ -314,23 +316,26 @@ class Streams {
|
|
|
314
316
|
const [, minId, maxId, consumers] = pendingMessages;
|
|
315
317
|
if (!consumers || consumers.length === 0)
|
|
316
318
|
return;
|
|
317
|
-
const transaction = this.redisGroups.multi({ pipeline: true });
|
|
318
319
|
for (const [consumer, pendingCount] of consumers) {
|
|
320
|
+
const transaction = this.redisGroups.multi({ pipeline: true });
|
|
319
321
|
if (parseInt(pendingCount) > 0) {
|
|
320
322
|
const pending = (yield this.redisGroups.xpending(streamName, this.consumerGroupName, minId, maxId, Number(pendingCount), consumer));
|
|
321
323
|
for (const [messageId] of pending) {
|
|
322
324
|
const claimedMessage = (yield this.redisGroups.xclaim(streamName, this.consumerGroupName, this.instanceId, idleTimeout, messageId));
|
|
323
325
|
if (claimedMessage) {
|
|
326
|
+
console.log({ claimedMessage: JSON.stringify(claimedMessage) });
|
|
324
327
|
const [, data] = claimedMessage[0];
|
|
325
328
|
const eventData = JSON.parse(data[1]);
|
|
329
|
+
const transaction = this.redisGroups.multi();
|
|
326
330
|
transaction.xadd(streamName, '*', 'data', JSON.stringify(eventData));
|
|
327
331
|
transaction.publish(eventName, '');
|
|
328
332
|
transaction.xack(streamName, this.consumerGroupName, messageId);
|
|
333
|
+
yield transaction.exec().catch(publisherErrorHandler);
|
|
329
334
|
}
|
|
330
335
|
}
|
|
331
336
|
}
|
|
337
|
+
yield transaction.exec();
|
|
332
338
|
}
|
|
333
|
-
yield transaction.exec();
|
|
334
339
|
});
|
|
335
340
|
}
|
|
336
341
|
/**
|
|
@@ -355,7 +360,7 @@ class Streams {
|
|
|
355
360
|
*/
|
|
356
361
|
close() {
|
|
357
362
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
358
|
-
this.clearSubscribedEvents();
|
|
363
|
+
yield this.clearSubscribedEvents();
|
|
359
364
|
if (this.redisPublisher) {
|
|
360
365
|
yield this.redisPublisher.quit();
|
|
361
366
|
}
|
|
@@ -373,8 +378,17 @@ class Streams {
|
|
|
373
378
|
clearSubscribedEvents() {
|
|
374
379
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
375
380
|
console.log(`${this.eventsListened.length} events to be cleared`);
|
|
381
|
+
let x = this.eventsListened.length;
|
|
376
382
|
for (const eventName of this.eventsListened) {
|
|
383
|
+
console.log(`${eventName} is being cleared in publisher`);
|
|
377
384
|
yield this.redisGroups.srem(`${eventName}`, this.consumerGroupName);
|
|
385
|
+
console.log(`${eventName} is removed from ${this.consumerGroupName}`);
|
|
386
|
+
// Releasing all claims based on info from: https://redis.io/commands/xgroup-delconsumer/
|
|
387
|
+
yield this.releaseAllClaims(eventName);
|
|
388
|
+
console.log(`${eventName} removes all claims`);
|
|
389
|
+
yield this.redisGroups.xgroup('DELCONSUMER', eventName, this.consumerGroupName, this.instanceId);
|
|
390
|
+
console.log(`${eventName} is deleted as a consumer from ${this.consumerGroupName}, ${this.instanceId}`);
|
|
391
|
+
console.log(x--);
|
|
378
392
|
}
|
|
379
393
|
});
|
|
380
394
|
}
|
|
@@ -383,13 +397,32 @@ class Streams {
|
|
|
383
397
|
yield this.redisGroups.sadd(`${eventName}`, this.consumerGroupName);
|
|
384
398
|
});
|
|
385
399
|
}
|
|
400
|
+
releaseAllClaims(eventName) {
|
|
401
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
402
|
+
/**
|
|
403
|
+
* Retrieve the pending messages for the consumer. Note this only fetches the last
|
|
404
|
+
* 10000 events assigned to this consumer. This function has been modified to make sure
|
|
405
|
+
* that there is a temp instance that claims all this messages
|
|
406
|
+
*/
|
|
407
|
+
const pendingMessages = (yield this.redisGroups.xpending(eventName, this.consumerGroupName, '-', '+', 10000, this.instanceId));
|
|
408
|
+
if (pendingMessages && pendingMessages.length > 0) {
|
|
409
|
+
console.log(`${pendingMessages.length} messages to clean up.`);
|
|
410
|
+
const transaction = this.redisGroups.multi({ pipeline: true });
|
|
411
|
+
const tempConsumerId = `${this.instanceId}-temp`;
|
|
412
|
+
for (const [messageId] of pendingMessages) {
|
|
413
|
+
transaction.xclaim(eventName, this.consumerGroupName, tempConsumerId, 10, messageId);
|
|
414
|
+
}
|
|
415
|
+
yield transaction.exec();
|
|
416
|
+
}
|
|
417
|
+
});
|
|
418
|
+
}
|
|
386
419
|
cleanupAcknowledgedMessages(eventName, interval = 60 * 60 * 1000) {
|
|
387
420
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
388
421
|
const streamName = `${eventName}:${this.consumerGroupName}`;
|
|
389
422
|
const cleanupThreshold = Date.now() - interval;
|
|
390
423
|
const acknowledgedMessages = yield this.redisGroups.zrangebyscore(`ack:${streamName}`, '-inf', cleanupThreshold);
|
|
391
424
|
if (acknowledgedMessages && acknowledgedMessages.length > 0) {
|
|
392
|
-
const transaction = this.redisGroups.
|
|
425
|
+
const transaction = this.redisGroups.pipeline();
|
|
393
426
|
// Remove acknowledged messages from the stream
|
|
394
427
|
for (const messageId of acknowledgedMessages) {
|
|
395
428
|
transaction.xdel(streamName, messageId);
|