@sprout-idws/sprout-redis 1.0.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/dist/cache/cache-store.interface.d.ts +14 -0
- package/dist/cache/cache-store.interface.d.ts.map +1 -0
- package/dist/cache/cache-store.interface.js +5 -0
- package/dist/cache/cache-store.interface.js.map +1 -0
- package/dist/cache/cache.constants.d.ts +4 -0
- package/dist/cache/cache.constants.d.ts.map +1 -0
- package/dist/cache/cache.constants.js +7 -0
- package/dist/cache/cache.constants.js.map +1 -0
- package/dist/cache/cache.manager.d.ts +17 -0
- package/dist/cache/cache.manager.d.ts.map +1 -0
- package/dist/cache/cache.manager.js +59 -0
- package/dist/cache/cache.manager.js.map +1 -0
- package/dist/cache/cache.module.d.ts +3 -0
- package/dist/cache/cache.module.d.ts.map +1 -0
- package/dist/cache/cache.module.js +46 -0
- package/dist/cache/cache.module.js.map +1 -0
- package/dist/cache/index.d.ts +6 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +17 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cache/stores/in-memory-cache.store.d.ts +15 -0
- package/dist/cache/stores/in-memory-cache.store.d.ts.map +1 -0
- package/dist/cache/stores/in-memory-cache.store.js +44 -0
- package/dist/cache/stores/in-memory-cache.store.js.map +1 -0
- package/dist/cache/stores/redis-cache.store.d.ts +12 -0
- package/dist/cache/stores/redis-cache.store.d.ts.map +1 -0
- package/dist/cache/stores/redis-cache.store.js +48 -0
- package/dist/cache/stores/redis-cache.store.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +36 -0
- package/dist/index.js.map +1 -0
- package/dist/lock/redis-lock.service.d.ts +15 -0
- package/dist/lock/redis-lock.service.d.ts.map +1 -0
- package/dist/lock/redis-lock.service.js +97 -0
- package/dist/lock/redis-lock.service.js.map +1 -0
- package/dist/redis-base.module.d.ts +9 -0
- package/dist/redis-base.module.d.ts.map +1 -0
- package/dist/redis-base.module.js +88 -0
- package/dist/redis-base.module.js.map +1 -0
- package/dist/redis-stream-consumer.module.d.ts +3 -0
- package/dist/redis-stream-consumer.module.d.ts.map +1 -0
- package/dist/redis-stream-consumer.module.js +36 -0
- package/dist/redis-stream-consumer.module.js.map +1 -0
- package/dist/stream/lua/ack-delete.lua +6 -0
- package/dist/stream/lua/delayed-retry.lua +11 -0
- package/dist/stream/lua/move-to-dlq.lua +27 -0
- package/dist/stream/lua/republish-delayed-messages.lua +30 -0
- package/dist/stream/lua/republish-inactive-consumer-messages.lua +52 -0
- package/dist/stream/lua-scripts.loader.d.ts +11 -0
- package/dist/stream/lua-scripts.loader.d.ts.map +1 -0
- package/dist/stream/lua-scripts.loader.js +39 -0
- package/dist/stream/lua-scripts.loader.js.map +1 -0
- package/dist/stream/periodic-executor.service.d.ts +30 -0
- package/dist/stream/periodic-executor.service.d.ts.map +1 -0
- package/dist/stream/periodic-executor.service.js +130 -0
- package/dist/stream/periodic-executor.service.js.map +1 -0
- package/dist/stream/redis-stream.service.d.ts +47 -0
- package/dist/stream/redis-stream.service.d.ts.map +1 -0
- package/dist/stream/redis-stream.service.js +200 -0
- package/dist/stream/redis-stream.service.js.map +1 -0
- package/dist/stream/stream-consumer-monitor.service.d.ts +19 -0
- package/dist/stream/stream-consumer-monitor.service.d.ts.map +1 -0
- package/dist/stream/stream-consumer-monitor.service.js +85 -0
- package/dist/stream/stream-consumer-monitor.service.js.map +1 -0
- package/dist/stream/stream-consumer.service.d.ts +25 -0
- package/dist/stream/stream-consumer.service.d.ts.map +1 -0
- package/dist/stream/stream-consumer.service.js +78 -0
- package/dist/stream/stream-consumer.service.js.map +1 -0
- package/dist/stream/stream-message-handler.service.d.ts +28 -0
- package/dist/stream/stream-message-handler.service.d.ts.map +1 -0
- package/dist/stream/stream-message-handler.service.js +145 -0
- package/dist/stream/stream-message-handler.service.js.map +1 -0
- package/dist/stream/stream-publisher.service.d.ts +9 -0
- package/dist/stream/stream-publisher.service.d.ts.map +1 -0
- package/dist/stream/stream-publisher.service.js +39 -0
- package/dist/stream/stream-publisher.service.js.map +1 -0
- package/dist/stream/stream-retry.service.d.ts +25 -0
- package/dist/stream/stream-retry.service.d.ts.map +1 -0
- package/dist/stream/stream-retry.service.js +74 -0
- package/dist/stream/stream-retry.service.js.map +1 -0
- package/package.json +67 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
15
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
16
|
+
};
|
|
17
|
+
var RedisBaseModule_1;
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.RedisBaseModule = void 0;
|
|
20
|
+
const common_1 = require("@nestjs/common");
|
|
21
|
+
const config_1 = require("@nestjs/config");
|
|
22
|
+
const sprout_context_1 = require("@sprout-idws/sprout-context");
|
|
23
|
+
const ioredis_1 = __importDefault(require("ioredis"));
|
|
24
|
+
const redis_lock_service_1 = require("./lock/redis-lock.service");
|
|
25
|
+
const redis_stream_service_1 = require("./stream/redis-stream.service");
|
|
26
|
+
const stream_publisher_service_1 = require("./stream/stream-publisher.service");
|
|
27
|
+
const periodic_executor_service_1 = require("./stream/periodic-executor.service");
|
|
28
|
+
let RedisBaseModule = RedisBaseModule_1 = class RedisBaseModule {
|
|
29
|
+
constructor(redis) {
|
|
30
|
+
this.redis = redis;
|
|
31
|
+
this.logger = new common_1.Logger(RedisBaseModule_1.name);
|
|
32
|
+
}
|
|
33
|
+
async onModuleDestroy() {
|
|
34
|
+
try {
|
|
35
|
+
if (this.redis.status === 'ready') {
|
|
36
|
+
await this.redis.quit();
|
|
37
|
+
this.logger.log('Redis cache connection closed gracefully');
|
|
38
|
+
}
|
|
39
|
+
else if (this.redis.status === 'connecting') {
|
|
40
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
41
|
+
this.redis.disconnect();
|
|
42
|
+
this.logger.log('Redis cache connection disconnected');
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
this.logger.log('Redis cache connection already closed');
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
const err = error;
|
|
50
|
+
this.logger.warn('Redis cleanup warning:', err.message);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
exports.RedisBaseModule = RedisBaseModule;
|
|
55
|
+
exports.RedisBaseModule = RedisBaseModule = RedisBaseModule_1 = __decorate([
|
|
56
|
+
(0, common_1.Global)(),
|
|
57
|
+
(0, common_1.Module)({
|
|
58
|
+
imports: [config_1.ConfigModule, sprout_context_1.ContextModule],
|
|
59
|
+
providers: [
|
|
60
|
+
{
|
|
61
|
+
provide: 'REDIS_CLIENT',
|
|
62
|
+
useFactory: (configService) => {
|
|
63
|
+
return new ioredis_1.default({
|
|
64
|
+
host: configService.get('REDIS_HOST', 'localhost'),
|
|
65
|
+
port: configService.get('REDIS_PORT', 6379),
|
|
66
|
+
password: configService.get('REDIS_PASSWORD'),
|
|
67
|
+
db: configService.get('REDIS_DB', 0),
|
|
68
|
+
});
|
|
69
|
+
},
|
|
70
|
+
inject: [config_1.ConfigService],
|
|
71
|
+
},
|
|
72
|
+
redis_lock_service_1.RedisLockService,
|
|
73
|
+
redis_stream_service_1.RedisStreamService,
|
|
74
|
+
stream_publisher_service_1.StreamPublisherService,
|
|
75
|
+
periodic_executor_service_1.PeriodicExecutorService,
|
|
76
|
+
],
|
|
77
|
+
exports: [
|
|
78
|
+
'REDIS_CLIENT',
|
|
79
|
+
redis_lock_service_1.RedisLockService,
|
|
80
|
+
redis_stream_service_1.RedisStreamService,
|
|
81
|
+
stream_publisher_service_1.StreamPublisherService,
|
|
82
|
+
periodic_executor_service_1.PeriodicExecutorService,
|
|
83
|
+
],
|
|
84
|
+
}),
|
|
85
|
+
__param(0, (0, common_1.Inject)('REDIS_CLIENT')),
|
|
86
|
+
__metadata("design:paramtypes", [ioredis_1.default])
|
|
87
|
+
], RedisBaseModule);
|
|
88
|
+
//# sourceMappingURL=redis-base.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis-base.module.js","sourceRoot":"","sources":["../src/redis-base.module.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;AAAA,2CAAiF;AACjF,2CAA6D;AAC7D,gEAA4D;AAC5D,sDAA4B;AAC5B,kEAA6D;AAC7D,wEAAmE;AACnE,gFAA2E;AAC3E,kFAA6E;AA+BtE,IAAM,eAAe,uBAArB,MAAM,eAAe;IAG1B,YAAoC,KAA6B;QAAZ,UAAK,GAAL,KAAK,CAAO;QAFhD,WAAM,GAAG,IAAI,eAAM,CAAC,iBAAe,CAAC,IAAI,CAAC,CAAC;IAES,CAAC;IAErE,KAAK,CAAC,eAAe;QACnB,IAAI,CAAC;YACH,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;gBAClC,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;gBACxB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC;YAC9D,CAAC;iBAAM,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,YAAY,EAAE,CAAC;gBAC9C,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;gBACzD,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;gBACxB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;YACzD,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC;YAC3D,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,GAAG,GAAG,KAAc,CAAC;YAC3B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,wBAAwB,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;CACF,CAAA;AAtBY,0CAAe;0BAAf,eAAe;IA7B3B,IAAA,eAAM,GAAE;IACR,IAAA,eAAM,EAAC;QACN,OAAO,EAAE,CAAC,qBAAY,EAAE,8BAAa,CAAC;QACtC,SAAS,EAAE;YACT;gBACE,OAAO,EAAE,cAAc;gBACvB,UAAU,EAAE,CAAC,aAA4B,EAAE,EAAE;oBAC3C,OAAO,IAAI,iBAAK,CAAC;wBACf,IAAI,EAAE,aAAa,CAAC,GAAG,CAAC,YAAY,EAAE,WAAW,CAAC;wBAClD,IAAI,EAAE,aAAa,CAAC,GAAG,CAAC,YAAY,EAAE,IAAI,CAAC;wBAC3C,QAAQ,EAAE,aAAa,CAAC,GAAG,CAAC,gBAAgB,CAAC;wBAC7C,EAAE,EAAE,aAAa,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;qBACrC,CAAC,CAAC;gBACL,CAAC;gBACD,MAAM,EAAE,CAAC,sBAAa,CAAC;aACxB;YACD,qCAAgB;YAChB,yCAAkB;YAClB,iDAAsB;YACtB,mDAAuB;SACxB;QACD,OAAO,EAAE;YACP,cAAc;YACd,qCAAgB;YAChB,yCAAkB;YAClB,iDAAsB;YACtB,mDAAuB;SACxB;KACF,CAAC;IAIa,WAAA,IAAA,eAAM,EAAC,cAAc,CAAC,CAAA;qCAAyB,iBAAK;GAHtD,eAAe,CAsB3B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis-stream-consumer.module.d.ts","sourceRoot":"","sources":["../src/redis-stream-consumer.module.ts"],"names":[],"mappings":"AAOA,qBAea,yBAAyB;CAAG"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.RedisStreamConsumerModule = void 0;
|
|
10
|
+
const common_1 = require("@nestjs/common");
|
|
11
|
+
const redis_base_module_1 = require("./redis-base.module");
|
|
12
|
+
const stream_consumer_service_1 = require("./stream/stream-consumer.service");
|
|
13
|
+
const stream_message_handler_service_1 = require("./stream/stream-message-handler.service");
|
|
14
|
+
const stream_retry_service_1 = require("./stream/stream-retry.service");
|
|
15
|
+
const stream_consumer_monitor_service_1 = require("./stream/stream-consumer-monitor.service");
|
|
16
|
+
let RedisStreamConsumerModule = class RedisStreamConsumerModule {
|
|
17
|
+
};
|
|
18
|
+
exports.RedisStreamConsumerModule = RedisStreamConsumerModule;
|
|
19
|
+
exports.RedisStreamConsumerModule = RedisStreamConsumerModule = __decorate([
|
|
20
|
+
(0, common_1.Module)({
|
|
21
|
+
imports: [redis_base_module_1.RedisBaseModule],
|
|
22
|
+
providers: [
|
|
23
|
+
stream_consumer_service_1.StreamConsumerService,
|
|
24
|
+
stream_message_handler_service_1.StreamMessageHandlerService,
|
|
25
|
+
stream_retry_service_1.StreamRetryService,
|
|
26
|
+
stream_consumer_monitor_service_1.StreamConsumerMonitorService,
|
|
27
|
+
],
|
|
28
|
+
exports: [
|
|
29
|
+
stream_consumer_service_1.StreamConsumerService,
|
|
30
|
+
stream_message_handler_service_1.StreamMessageHandlerService,
|
|
31
|
+
stream_retry_service_1.StreamRetryService,
|
|
32
|
+
stream_consumer_monitor_service_1.StreamConsumerMonitorService,
|
|
33
|
+
],
|
|
34
|
+
})
|
|
35
|
+
], RedisStreamConsumerModule);
|
|
36
|
+
//# sourceMappingURL=redis-stream-consumer.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis-stream-consumer.module.js","sourceRoot":"","sources":["../src/redis-stream-consumer.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,2DAAsD;AACtD,8EAAyE;AACzE,4FAAsF;AACtF,wEAAmE;AACnE,8FAAwF;AAiBjF,IAAM,yBAAyB,GAA/B,MAAM,yBAAyB;CAAG,CAAA;AAA5B,8DAAyB;oCAAzB,yBAAyB;IAfrC,IAAA,eAAM,EAAC;QACN,OAAO,EAAE,CAAC,mCAAe,CAAC;QAC1B,SAAS,EAAE;YACT,+CAAqB;YACrB,4DAA2B;YAC3B,yCAAkB;YAClB,8DAA4B;SAC7B;QACD,OAAO,EAAE;YACP,+CAAqB;YACrB,4DAA2B;YAC3B,yCAAkB;YAClB,8DAA4B;SAC7B;KACF,CAAC;GACW,yBAAyB,CAAG"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
local streamName = KEYS[1]
|
|
2
|
+
local delayedQueueKey = KEYS[2]
|
|
3
|
+
local groupName = ARGV[1]
|
|
4
|
+
local messageId = ARGV[2]
|
|
5
|
+
local score = tonumber(ARGV[3])
|
|
6
|
+
local member = ARGV[4]
|
|
7
|
+
|
|
8
|
+
redis.call('XACK', streamName, groupName, messageId)
|
|
9
|
+
redis.call('XDEL', streamName, messageId)
|
|
10
|
+
return redis.call('ZADD', delayedQueueKey, score, member)
|
|
11
|
+
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
local streamName = KEYS[1]
|
|
2
|
+
local dlqStream = ARGV[1]
|
|
3
|
+
local groupName = ARGV[2]
|
|
4
|
+
local messageId = ARGV[3]
|
|
5
|
+
|
|
6
|
+
local message = redis.call('XRANGE', streamName, messageId, messageId)
|
|
7
|
+
|
|
8
|
+
if #message == 0 then
|
|
9
|
+
return 0
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
local messageFields = message[1][2]
|
|
13
|
+
local messageContent = nil
|
|
14
|
+
|
|
15
|
+
for i = 1, #messageFields, 2 do
|
|
16
|
+
if messageFields[i] == 'message' then
|
|
17
|
+
messageContent = messageFields[i + 1]
|
|
18
|
+
break
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
if messageContent then
|
|
23
|
+
redis.call('XADD', dlqStream, '*', 'message', messageContent)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
redis.call('XACK', streamName, groupName, messageId)
|
|
27
|
+
return redis.call('XDEL', streamName, messageId)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
local queueKey = KEYS[1]
|
|
2
|
+
local currentTime = tonumber(ARGV[1])
|
|
3
|
+
local limit = tonumber(ARGV[2])
|
|
4
|
+
|
|
5
|
+
local messages = redis.call('ZRANGEBYSCORE', queueKey, '-inf', currentTime, 'LIMIT', 0, limit)
|
|
6
|
+
|
|
7
|
+
if #messages == 0 then
|
|
8
|
+
return 0
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
redis.call('ZREM', queueKey, unpack(messages))
|
|
12
|
+
|
|
13
|
+
local republishedCount = 0
|
|
14
|
+
local cjson = cjson
|
|
15
|
+
|
|
16
|
+
for i = 1, #messages do
|
|
17
|
+
local messageData = messages[i]
|
|
18
|
+
local success, message = pcall(cjson.decode, messageData)
|
|
19
|
+
|
|
20
|
+
if success and message and message.metadata and message.metadata.streamName then
|
|
21
|
+
local streamName = message.metadata.streamName
|
|
22
|
+
local messageJson = cjson.encode(message)
|
|
23
|
+
|
|
24
|
+
redis.call('XADD', streamName, '*', 'message', messageJson)
|
|
25
|
+
republishedCount = republishedCount + 1
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
return republishedCount
|
|
30
|
+
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
local streamName = KEYS[1]
|
|
2
|
+
local groupName = ARGV[1]
|
|
3
|
+
local inactiveConsumerName = ARGV[2]
|
|
4
|
+
local maxCount = 10000
|
|
5
|
+
|
|
6
|
+
local pendingMessages = redis.call('XPENDING', streamName, groupName, '-', '+', maxCount)
|
|
7
|
+
|
|
8
|
+
if #pendingMessages == 0 then
|
|
9
|
+
return 0
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
local messageIds = {}
|
|
13
|
+
for i = 1, #pendingMessages do
|
|
14
|
+
local messageId = pendingMessages[i][1]
|
|
15
|
+
local consumerName = pendingMessages[i][2]
|
|
16
|
+
|
|
17
|
+
if consumerName == inactiveConsumerName then
|
|
18
|
+
table.insert(messageIds, messageId)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
if #messageIds == 0 then
|
|
23
|
+
return 0
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
local republishedCount = 0
|
|
27
|
+
|
|
28
|
+
for i = 1, #messageIds do
|
|
29
|
+
local messageId = messageIds[i]
|
|
30
|
+
local message = redis.call('XRANGE', streamName, messageId, messageId)
|
|
31
|
+
|
|
32
|
+
if #message > 0 then
|
|
33
|
+
local messageFields = message[1][2]
|
|
34
|
+
local messageContent = nil
|
|
35
|
+
|
|
36
|
+
for j = 1, #messageFields, 2 do
|
|
37
|
+
if messageFields[j] == 'message' then
|
|
38
|
+
messageContent = messageFields[j + 1]
|
|
39
|
+
break
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
if messageContent then
|
|
44
|
+
redis.call('XACK', streamName, groupName, messageId)
|
|
45
|
+
redis.call('XDEL', streamName, messageId)
|
|
46
|
+
redis.call('XADD', streamName, '*', 'message', messageContent)
|
|
47
|
+
republishedCount = republishedCount + 1
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
return republishedCount
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
declare const LUA_SCRIPT_NAMES: readonly ["move-to-dlq.lua", "ack-delete.lua", "delayed-retry.lua", "republish-delayed-messages.lua", "republish-inactive-consumer-messages.lua"];
|
|
2
|
+
export type LuaScriptName = (typeof LUA_SCRIPT_NAMES)[number];
|
|
3
|
+
export declare class LuaScriptsLoader {
|
|
4
|
+
private readonly logger;
|
|
5
|
+
private readonly scripts;
|
|
6
|
+
constructor();
|
|
7
|
+
private loadScripts;
|
|
8
|
+
getScript(scriptName: LuaScriptName): string;
|
|
9
|
+
}
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=lua-scripts.loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lua-scripts.loader.d.ts","sourceRoot":"","sources":["../../src/stream/lua-scripts.loader.ts"],"names":[],"mappings":"AAIA,QAAA,MAAM,gBAAgB,mJAMZ,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE9D,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqC;IAC5D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyC;;IAMjE,OAAO,CAAC,WAAW;IAYnB,SAAS,CAAC,UAAU,EAAE,aAAa,GAAG,MAAM;CAO7C"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LuaScriptsLoader = void 0;
|
|
4
|
+
const fs_1 = require("fs");
|
|
5
|
+
const path_1 = require("path");
|
|
6
|
+
const common_1 = require("@nestjs/common");
|
|
7
|
+
const LUA_SCRIPT_NAMES = [
|
|
8
|
+
'move-to-dlq.lua',
|
|
9
|
+
'ack-delete.lua',
|
|
10
|
+
'delayed-retry.lua',
|
|
11
|
+
'republish-delayed-messages.lua',
|
|
12
|
+
'republish-inactive-consumer-messages.lua',
|
|
13
|
+
];
|
|
14
|
+
class LuaScriptsLoader {
|
|
15
|
+
constructor() {
|
|
16
|
+
this.logger = new common_1.Logger(LuaScriptsLoader.name);
|
|
17
|
+
this.scripts = new Map();
|
|
18
|
+
this.loadScripts();
|
|
19
|
+
}
|
|
20
|
+
loadScripts() {
|
|
21
|
+
const luaDir = (0, path_1.join)(__dirname, 'lua');
|
|
22
|
+
const scriptNames = LUA_SCRIPT_NAMES;
|
|
23
|
+
for (const scriptName of scriptNames) {
|
|
24
|
+
const scriptPath = (0, path_1.join)(luaDir, scriptName);
|
|
25
|
+
const scriptContent = (0, fs_1.readFileSync)(scriptPath, 'utf-8');
|
|
26
|
+
this.scripts.set(scriptName, scriptContent);
|
|
27
|
+
this.logger.debug(`Loaded Lua script: ${scriptName}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
getScript(scriptName) {
|
|
31
|
+
const script = this.scripts.get(scriptName);
|
|
32
|
+
if (!script) {
|
|
33
|
+
throw new Error(`Lua script ${scriptName} not found`);
|
|
34
|
+
}
|
|
35
|
+
return script;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
exports.LuaScriptsLoader = LuaScriptsLoader;
|
|
39
|
+
//# sourceMappingURL=lua-scripts.loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lua-scripts.loader.js","sourceRoot":"","sources":["../../src/stream/lua-scripts.loader.ts"],"names":[],"mappings":";;;AAAA,2BAAkC;AAClC,+BAA4B;AAC5B,2CAAwC;AAExC,MAAM,gBAAgB,GAAG;IACvB,iBAAiB;IACjB,gBAAgB;IAChB,mBAAmB;IACnB,gCAAgC;IAChC,0CAA0C;CAClC,CAAC;AAIX,MAAa,gBAAgB;IAI3B;QAHiB,WAAM,GAAG,IAAI,eAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAC3C,YAAO,GAA+B,IAAI,GAAG,EAAE,CAAC;QAG/D,IAAI,CAAC,WAAW,EAAE,CAAC;IACrB,CAAC;IAEO,WAAW;QACjB,MAAM,MAAM,GAAG,IAAA,WAAI,EAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QACtC,MAAM,WAAW,GAA6B,gBAAgB,CAAC;QAE/D,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;YACrC,MAAM,UAAU,GAAG,IAAA,WAAI,EAAC,MAAM,EAAE,UAAU,CAAC,CAAC;YAC5C,MAAM,aAAa,GAAG,IAAA,iBAAY,EAAC,UAAU,EAAE,OAAO,CAAC,CAAC;YACxD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;YAC5C,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,sBAAsB,UAAU,EAAE,CAAC,CAAC;QACxD,CAAC;IACH,CAAC;IAED,SAAS,CAAC,UAAyB;QACjC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAC5C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,cAAc,UAAU,YAAY,CAAC,CAAC;QACxD,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;CACF;AA3BD,4CA2BC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Logger, OnModuleDestroy } from '@nestjs/common';
|
|
2
|
+
export interface PeriodicExecutorConfig {
|
|
3
|
+
intervalMs: number;
|
|
4
|
+
name: string;
|
|
5
|
+
}
|
|
6
|
+
export declare class PeriodicExecutorService implements OnModuleDestroy {
|
|
7
|
+
private readonly logger;
|
|
8
|
+
private readonly activeExecutors;
|
|
9
|
+
constructor();
|
|
10
|
+
startExecutor(config: PeriodicExecutorConfig, task: () => Promise<void>): Promise<PeriodicExecutorInstance>;
|
|
11
|
+
shutdownAllExecutors(): Promise<void>;
|
|
12
|
+
onModuleDestroy(): Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
export declare class PeriodicExecutorInstance {
|
|
15
|
+
private readonly config;
|
|
16
|
+
private readonly task;
|
|
17
|
+
private readonly logger;
|
|
18
|
+
private isRunning;
|
|
19
|
+
private isExecutingTask;
|
|
20
|
+
private intervalId;
|
|
21
|
+
private stopPromise;
|
|
22
|
+
constructor(config: PeriodicExecutorConfig, task: () => Promise<void>, logger: Logger);
|
|
23
|
+
start(): Promise<void>;
|
|
24
|
+
shutdown(): Promise<void>;
|
|
25
|
+
private executeTask;
|
|
26
|
+
private waitForExecutionComplete;
|
|
27
|
+
get isActive(): boolean;
|
|
28
|
+
get isCurrentlyExecuting(): boolean;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=periodic-executor.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"periodic-executor.service.d.ts","sourceRoot":"","sources":["../../src/stream/periodic-executor.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,MAAM,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAErE,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,qBACa,uBAAwB,YAAW,eAAe;IAC7D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA4C;IACnE,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA+C;;IAIzE,aAAa,CACjB,MAAM,EAAE,sBAAsB,EAC9B,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GACxB,OAAO,CAAC,wBAAwB,CAAC;IAiB9B,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC;IAarC,eAAe;CAItB;AAED,qBAAa,wBAAwB;IAOjC,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,MAAM;IARzB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,UAAU,CAA+B;IACjD,OAAO,CAAC,WAAW,CAA8B;gBAG9B,MAAM,EAAE,sBAAsB,EAC9B,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,EACzB,MAAM,EAAE,MAAM;IAG3B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAiBtB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;YA+BjB,WAAW;YA0BX,wBAAwB;IAatC,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED,IAAI,oBAAoB,IAAI,OAAO,CAElC;CACF"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var PeriodicExecutorService_1;
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.PeriodicExecutorInstance = exports.PeriodicExecutorService = void 0;
|
|
14
|
+
const common_1 = require("@nestjs/common");
|
|
15
|
+
let PeriodicExecutorService = PeriodicExecutorService_1 = class PeriodicExecutorService {
|
|
16
|
+
constructor() {
|
|
17
|
+
this.logger = new common_1.Logger(PeriodicExecutorService_1.name);
|
|
18
|
+
this.activeExecutors = new Map();
|
|
19
|
+
}
|
|
20
|
+
async startExecutor(config, task) {
|
|
21
|
+
if (this.activeExecutors.has(config.name)) {
|
|
22
|
+
this.logger.warn(`Periodic executor ${config.name} already exists`);
|
|
23
|
+
return this.activeExecutors.get(config.name);
|
|
24
|
+
}
|
|
25
|
+
const executor = new PeriodicExecutorInstance(config, task, this.logger);
|
|
26
|
+
this.activeExecutors.set(config.name, executor);
|
|
27
|
+
await executor.start();
|
|
28
|
+
this.logger.log(`Periodic executor ${config.name} started with interval ${config.intervalMs}ms`);
|
|
29
|
+
return executor;
|
|
30
|
+
}
|
|
31
|
+
async shutdownAllExecutors() {
|
|
32
|
+
this.logger.log(`Shutting down ${this.activeExecutors.size} active executors...`);
|
|
33
|
+
const shutdownPromises = Array.from(this.activeExecutors.values()).map((executor) => executor.shutdown());
|
|
34
|
+
await Promise.allSettled(shutdownPromises);
|
|
35
|
+
this.activeExecutors.clear();
|
|
36
|
+
this.logger.log('All executors shutdown completed');
|
|
37
|
+
}
|
|
38
|
+
async onModuleDestroy() {
|
|
39
|
+
this.logger.log('PeriodicExecutorService shutting down...');
|
|
40
|
+
await this.shutdownAllExecutors();
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
exports.PeriodicExecutorService = PeriodicExecutorService;
|
|
44
|
+
exports.PeriodicExecutorService = PeriodicExecutorService = PeriodicExecutorService_1 = __decorate([
|
|
45
|
+
(0, common_1.Injectable)(),
|
|
46
|
+
__metadata("design:paramtypes", [])
|
|
47
|
+
], PeriodicExecutorService);
|
|
48
|
+
class PeriodicExecutorInstance {
|
|
49
|
+
constructor(config, task, logger) {
|
|
50
|
+
this.config = config;
|
|
51
|
+
this.task = task;
|
|
52
|
+
this.logger = logger;
|
|
53
|
+
this.isRunning = false;
|
|
54
|
+
this.isExecutingTask = false;
|
|
55
|
+
this.intervalId = null;
|
|
56
|
+
this.stopPromise = null;
|
|
57
|
+
}
|
|
58
|
+
async start() {
|
|
59
|
+
if (this.isRunning) {
|
|
60
|
+
this.logger.warn(`Periodic executor ${this.config.name} is already running`);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
this.isRunning = true;
|
|
64
|
+
this.stopPromise = null;
|
|
65
|
+
this.logger.log(`Starting periodic executor ${this.config.name} with interval ${this.config.intervalMs}ms`);
|
|
66
|
+
this.intervalId = setInterval(async () => {
|
|
67
|
+
await this.executeTask();
|
|
68
|
+
}, this.config.intervalMs);
|
|
69
|
+
}
|
|
70
|
+
async shutdown() {
|
|
71
|
+
if (this.stopPromise) {
|
|
72
|
+
return this.stopPromise;
|
|
73
|
+
}
|
|
74
|
+
this.stopPromise = (async () => {
|
|
75
|
+
if (!this.isRunning) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
this.logger.log(`Stopping periodic executor ${this.config.name}...`);
|
|
79
|
+
this.isRunning = false;
|
|
80
|
+
if (this.intervalId) {
|
|
81
|
+
clearInterval(this.intervalId);
|
|
82
|
+
this.intervalId = null;
|
|
83
|
+
}
|
|
84
|
+
if (this.isExecutingTask) {
|
|
85
|
+
this.logger.log(`Periodic executor ${this.config.name} is executing, waiting for completion...`);
|
|
86
|
+
await this.waitForExecutionComplete();
|
|
87
|
+
}
|
|
88
|
+
this.logger.log(`Periodic executor ${this.config.name} stopped`);
|
|
89
|
+
})();
|
|
90
|
+
return this.stopPromise;
|
|
91
|
+
}
|
|
92
|
+
async executeTask() {
|
|
93
|
+
if (!this.isRunning) {
|
|
94
|
+
this.logger.debug(`Periodic executor ${this.config.name} execution skipped - executor is not running`);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if (this.isExecutingTask) {
|
|
98
|
+
this.logger.debug(`Periodic executor ${this.config.name} execution skipped - previous execution still running`);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
this.isExecutingTask = true;
|
|
102
|
+
try {
|
|
103
|
+
await this.task();
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
this.logger.error(`Error in periodic executor ${this.config.name} task execution:`, error);
|
|
107
|
+
}
|
|
108
|
+
finally {
|
|
109
|
+
this.isExecutingTask = false;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
async waitForExecutionComplete() {
|
|
113
|
+
const maxWaitTime = 30000;
|
|
114
|
+
const startTime = Date.now();
|
|
115
|
+
while (this.isExecutingTask && Date.now() - startTime < maxWaitTime) {
|
|
116
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
117
|
+
}
|
|
118
|
+
if (this.isExecutingTask) {
|
|
119
|
+
this.logger.warn(`Periodic executor ${this.config.name} execution timeout reached`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
get isActive() {
|
|
123
|
+
return this.isRunning;
|
|
124
|
+
}
|
|
125
|
+
get isCurrentlyExecuting() {
|
|
126
|
+
return this.isExecutingTask;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
exports.PeriodicExecutorInstance = PeriodicExecutorInstance;
|
|
130
|
+
//# sourceMappingURL=periodic-executor.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"periodic-executor.service.js","sourceRoot":"","sources":["../../src/stream/periodic-executor.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { ContextService } from '@sprout-idws/sprout-context';
|
|
2
|
+
import Redis from 'ioredis';
|
|
3
|
+
export interface StreamMessage {
|
|
4
|
+
id?: string;
|
|
5
|
+
originalMessageId?: string;
|
|
6
|
+
data: object;
|
|
7
|
+
context?: string;
|
|
8
|
+
metadata: {
|
|
9
|
+
timestamp: number;
|
|
10
|
+
streamName: string;
|
|
11
|
+
retryCount?: number;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export declare class RedisStreamService {
|
|
15
|
+
private readonly redis;
|
|
16
|
+
private readonly contextService;
|
|
17
|
+
private readonly logger;
|
|
18
|
+
private readonly luaScriptsLoader;
|
|
19
|
+
constructor(redis: Redis, contextService: ContextService);
|
|
20
|
+
publishToStream(streamName: string, message: StreamMessage): Promise<string>;
|
|
21
|
+
createConsumerGroup(streamName: string, groupName: string, startId?: string): Promise<void>;
|
|
22
|
+
readFromConsumerGroup({ streamName, groupName, consumerName, count, blockTime, }: {
|
|
23
|
+
streamName: string;
|
|
24
|
+
groupName: string;
|
|
25
|
+
consumerName: string;
|
|
26
|
+
count?: number;
|
|
27
|
+
blockTime?: number;
|
|
28
|
+
}): Promise<StreamMessage[]>;
|
|
29
|
+
sendToDlq(streamName: string, groupName: string, messageId: string): Promise<void>;
|
|
30
|
+
ackDelete(streamName: string, groupName: string, messageId: string): Promise<void>;
|
|
31
|
+
delayedRetry(streamName: string, groupName: string, messageId: string, delayedQueueKey: string, score: number, member: string): Promise<void>;
|
|
32
|
+
getAllStreams(pattern?: string): Promise<string[]>;
|
|
33
|
+
getConsumerGroups(streamName: string): Promise<Array<{
|
|
34
|
+
name: string;
|
|
35
|
+
}>>;
|
|
36
|
+
deleteConsumer(streamName: string, groupName: string, consumerName: string): Promise<void>;
|
|
37
|
+
republishDelayedMessages(queueKey: string, currentTime: number, limit?: number): Promise<number>;
|
|
38
|
+
getConsumers(streamName: string, groupName: string): Promise<Array<{
|
|
39
|
+
name: string;
|
|
40
|
+
pending: number;
|
|
41
|
+
idle: number;
|
|
42
|
+
}>>;
|
|
43
|
+
republishInactiveConsumerMessages(streamName: string, groupName: string, inactiveConsumerName: string): Promise<{
|
|
44
|
+
republishedCount: number;
|
|
45
|
+
}>;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=redis-stream.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis-stream.service.d.ts","sourceRoot":"","sources":["../../src/stream/redis-stream.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,KAAK,MAAM,SAAS,CAAC;AAG5B,MAAM,WAAW,aAAa;IAC5B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE;QACR,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC;CACH;AAED,qBACa,kBAAkB;IAKH,OAAO,CAAC,QAAQ,CAAC,KAAK;IAC9C,OAAO,CAAC,QAAQ,CAAC,cAAc;IALjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuC;IAC9D,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAmB;gBAGT,KAAK,EAAE,KAAK,EACpC,cAAc,EAAE,cAAc;IAK3C,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC;IAM5E,mBAAmB,CACvB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,MAAY,GACpB,OAAO,CAAC,IAAI,CAAC;IAYV,qBAAqB,CAAC,EAC1B,UAAU,EACV,SAAS,EACT,YAAY,EACZ,KAAU,EACV,SAAgB,GACjB,EAAE;QACD,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,EAAE,MAAM,CAAC;QACrB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IA4CtB,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOlF,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMlF,YAAY,CAChB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,eAAe,EAAE,MAAM,EACvB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC;IAeV,aAAa,CAAC,OAAO,GAAE,MAAY,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAwBvD,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IA0CvE,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI1F,wBAAwB,CAC5B,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,KAAK,GAAE,MAAa,GACnB,OAAO,CAAC,MAAM,CAAC;IAqBZ,YAAY,CAChB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IA+C5D,iCAAiC,CACrC,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,oBAAoB,EAAE,MAAM,GAC3B,OAAO,CAAC;QAAE,gBAAgB,EAAE,MAAM,CAAA;KAAE,CAAC;CAQzC"}
|