@jetit/publisher 6.0.2 → 6.0.3
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/README.md +2 -1
- package/package.json +1 -1
- package/src/lib/redis/streams.js +15 -4
- package/src/lib/redis/types.d.ts +1 -0
package/README.md
CHANGED
|
@@ -127,6 +127,7 @@ const config: Partial<IStreamsConfig> = {
|
|
|
127
127
|
},
|
|
128
128
|
maxPendingTasks: 1000, // Max concurrent pending retry tasks per event per consumer (default: 1000, 0 = unbounded)
|
|
129
129
|
enableMetrics: true, // Set to false to disable MetricsCollector and its periodic SCAN (default: true)
|
|
130
|
+
recurringCleanupInterval: 10000, // Interval (ms) for the recurring pending-retry timer (default: 10000)
|
|
130
131
|
};
|
|
131
132
|
|
|
132
133
|
const publisher = new Publisher('MyService', config);
|
|
@@ -361,7 +362,7 @@ The Circuit Breaker has three states:
|
|
|
361
362
|
- Circuit Breaker to prevent overwhelming failed services
|
|
362
363
|
- Dead Letter Queue (DLQ) for handling subscription failures
|
|
363
364
|
- **Disable Metrics Collection**: Set `enableMetrics: false` to skip `MetricsCollector` initialization entirely. The collector runs `SCAN *:cg-* COUNT 100` every 60 seconds for queue depth — disabling it eliminates this periodic Redis overhead. Applies to both `Publisher` and `PublisherLite`. When disabled, `getMetrics()` returns `[]` and `getLatestMetrics()` returns `null`.
|
|
364
|
-
- **Pending Retry Task Cap**: Limits the number of concurrent in-flight pending message retry tasks per event per consumer instance. Prevents unbounded memory growth and Redis saturation under sustained load. Configurable via `maxPendingTasks` (default: 1000). Set to `0` to disable the cap (unbounded, pre-6.0.1 behavior). When the cap is reached, a rate-limited warning is logged and skipped messages are retried on the next Pub/Sub
|
|
365
|
+
- **Pending Retry Task Cap**: Limits the number of concurrent in-flight pending message retry tasks per event per consumer instance. Prevents unbounded memory growth and Redis saturation under sustained load. Configurable via `maxPendingTasks` (default: 1000). Set to `0` to disable the cap (unbounded, pre-6.0.1 behavior). When the cap is reached, a rate-limited warning is logged and skipped messages are retried on the next trigger (Pub/Sub notification or the 10-second cleanup timer).
|
|
365
366
|
- **Adaptive Redis Stream ID Generation (Publisher only)**: The default `Publisher` automatically switches to an optimized ID generation strategy using a Lua script when publishing to many consumer groups (>10 by default) or when ID conflicts are detected. This prevents `XADD` errors related to non-monotonic IDs in high-throughput scenarios. Configurable via `optimizationThreshold` and `optimizationDurationMs`. (`PublisherLite` does not include this complex logic).
|
|
366
367
|
|
|
367
368
|
## Cleanup and Graceful Shutdown
|
package/package.json
CHANGED
package/src/lib/redis/streams.js
CHANGED
|
@@ -130,6 +130,7 @@ class Streams {
|
|
|
130
130
|
optimizationThreshold: 20, // Enable optimization for >20 consumer groups
|
|
131
131
|
maxPendingTasks: 1000,
|
|
132
132
|
enableMetrics: true,
|
|
133
|
+
recurringCleanupInterval: 10000, // 10 seconds
|
|
133
134
|
};
|
|
134
135
|
/** Initialise Config properties */
|
|
135
136
|
this.config = { ...this.config, ...this.DEFAULT_STREAMS_CONFIG, ...config };
|
|
@@ -577,10 +578,20 @@ class Streams {
|
|
|
577
578
|
if (!isNewSubscription) {
|
|
578
579
|
return bs.asObservable().pipe((0, rxjs_1.skip)(1));
|
|
579
580
|
}
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
581
|
+
const cleanupInterval = this.config.recurringCleanupInterval ?? 10000; // 10 seconds
|
|
582
|
+
const timer = (0, rxjs_1.interval)(cleanupInterval).subscribe({
|
|
583
|
+
next: async () => {
|
|
584
|
+
try {
|
|
585
|
+
await processMessage(this.redisGroups, '0', new tracker_1.MetricsTracker(), false);
|
|
586
|
+
}
|
|
587
|
+
catch (error) {
|
|
588
|
+
logger_1.PUBLISHER_LOGGER.error('PUBLISHER: Error in running recurring cleanup task:', error);
|
|
589
|
+
}
|
|
590
|
+
},
|
|
591
|
+
error: (error) => {
|
|
592
|
+
logger_1.PUBLISHER_LOGGER.error('PUBLISHER: Fatal error in cleanup timer:', error);
|
|
593
|
+
},
|
|
594
|
+
});
|
|
584
595
|
// Create observable with proper cleanup
|
|
585
596
|
const observable = bs.asObservable().pipe((0, rxjs_1.skip)(1), (0, rxjs_1.finalize)(() => {
|
|
586
597
|
timer.unsubscribe();
|
package/src/lib/redis/types.d.ts
CHANGED
|
@@ -58,6 +58,7 @@ export interface IStreamsConfig {
|
|
|
58
58
|
optimizationThreshold?: number;
|
|
59
59
|
maxPendingTasks?: number;
|
|
60
60
|
enableMetrics?: boolean;
|
|
61
|
+
recurringCleanupInterval?: number;
|
|
61
62
|
}
|
|
62
63
|
export type TEventFilter<T> = (event: EventData<T, string>) => boolean;
|
|
63
64
|
export interface ISubscription<T, TName extends string = string> {
|