@diia-inhouse/redis 2.12.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/LICENCE.md +287 -0
- package/README.md +93 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces/cache.js +3 -0
- package/dist/interfaces/cache.js.map +1 -0
- package/dist/interfaces/deps.js +3 -0
- package/dist/interfaces/deps.js.map +1 -0
- package/dist/interfaces/index.js +22 -0
- package/dist/interfaces/index.js.map +1 -0
- package/dist/interfaces/mutex.js +3 -0
- package/dist/interfaces/mutex.js.map +1 -0
- package/dist/interfaces/pubsub.js +3 -0
- package/dist/interfaces/pubsub.js.map +1 -0
- package/dist/interfaces/redis.js +8 -0
- package/dist/interfaces/redis.js.map +1 -0
- package/dist/interfaces/store.js +12 -0
- package/dist/interfaces/store.js.map +1 -0
- package/dist/services/cache.js +75 -0
- package/dist/services/cache.js.map +1 -0
- package/dist/services/index.js +22 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/mutex.js +44 -0
- package/dist/services/mutex.js.map +1 -0
- package/dist/services/providers/cache.js +56 -0
- package/dist/services/providers/cache.js.map +1 -0
- package/dist/services/providers/pubsub.js +86 -0
- package/dist/services/providers/pubsub.js.map +1 -0
- package/dist/services/pubsub.js +43 -0
- package/dist/services/pubsub.js.map +1 -0
- package/dist/services/redis.js +17 -0
- package/dist/services/redis.js.map +1 -0
- package/dist/services/store.js +135 -0
- package/dist/services/store.js.map +1 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/interfaces/cache.d.ts +14 -0
- package/dist/types/interfaces/deps.d.ts +7 -0
- package/dist/types/interfaces/index.d.ts +5 -0
- package/dist/types/interfaces/mutex.d.ts +5 -0
- package/dist/types/interfaces/pubsub.d.ts +15 -0
- package/dist/types/interfaces/redis.d.ts +15 -0
- package/dist/types/interfaces/store.d.ts +23 -0
- package/dist/types/services/cache.d.ts +24 -0
- package/dist/types/services/index.d.ts +5 -0
- package/dist/types/services/mutex.d.ts +13 -0
- package/dist/types/services/providers/cache.d.ts +17 -0
- package/dist/types/services/providers/pubsub.d.ts +17 -0
- package/dist/types/services/pubsub.d.ts +15 -0
- package/dist/types/services/redis.d.ts +4 -0
- package/dist/types/services/store.d.ts +24 -0
- package/package.json +96 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RedisCacheProvider = void 0;
|
|
4
|
+
const redis_1 = require("../redis");
|
|
5
|
+
class RedisCacheProvider {
|
|
6
|
+
logger;
|
|
7
|
+
clientRW;
|
|
8
|
+
clientRO;
|
|
9
|
+
constructor({ readWrite, readOnly }, logger) {
|
|
10
|
+
this.logger = logger;
|
|
11
|
+
this.clientRW = redis_1.RedisService.createClient(readWrite);
|
|
12
|
+
this.clientRO = redis_1.RedisService.createClient(readOnly);
|
|
13
|
+
this.clientRW.on('connect', () => {
|
|
14
|
+
this.logger.info(`Redis READ-WRITE connection open to ${JSON.stringify(readWrite.sentinels)}`);
|
|
15
|
+
});
|
|
16
|
+
this.clientRW.on('error', (err) => {
|
|
17
|
+
this.logger.error('Redis READ-WRITE connection error ', { err });
|
|
18
|
+
});
|
|
19
|
+
this.clientRO.on('connect', () => {
|
|
20
|
+
this.logger.info(`Redis READ-ONLY connection open to ${JSON.stringify(readOnly.sentinels)}`);
|
|
21
|
+
});
|
|
22
|
+
this.clientRO.on('error', (err) => {
|
|
23
|
+
this.logger.error('Redis READ-ONLY connection error ', { err });
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
async get(key) {
|
|
27
|
+
return await this.clientRO.get(key);
|
|
28
|
+
}
|
|
29
|
+
async set(key, data, expiration) {
|
|
30
|
+
const result = await this.clientRW.set(key, data);
|
|
31
|
+
if (expiration !== -1) {
|
|
32
|
+
await this.clientRW.expire(key, expiration);
|
|
33
|
+
}
|
|
34
|
+
return result;
|
|
35
|
+
}
|
|
36
|
+
async getKeysByPattern(pattern) {
|
|
37
|
+
return await this.clientRO.keys(pattern);
|
|
38
|
+
}
|
|
39
|
+
async getByKeys(keys) {
|
|
40
|
+
return await this.clientRO.mget(keys);
|
|
41
|
+
}
|
|
42
|
+
async remove(...key) {
|
|
43
|
+
return await this.clientRW.del(...key);
|
|
44
|
+
}
|
|
45
|
+
async quit() {
|
|
46
|
+
await Promise.all([this.clientRW.quit(), this.clientRO.quit()]);
|
|
47
|
+
}
|
|
48
|
+
getStatus() {
|
|
49
|
+
return {
|
|
50
|
+
readWrite: this.clientRW.status,
|
|
51
|
+
readOnly: this.clientRO.status,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
exports.RedisCacheProvider = RedisCacheProvider;
|
|
56
|
+
//# sourceMappingURL=cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../../src/services/providers/cache.ts"],"names":[],"mappings":";;;AAMA,oCAAuC;AAEvC,MAAa,kBAAkB;IAQN;IAPb,QAAQ,CAAO;IAEf,QAAQ,CAAO;IAEvB,YACI,EAAE,SAAS,EAAE,QAAQ,EAAe,EAEnB,MAAc;QAAd,WAAM,GAAN,MAAM,CAAQ;QAE/B,IAAI,CAAC,QAAQ,GAAG,oBAAY,CAAC,YAAY,CAAC,SAAS,CAAC,CAAA;QACpD,IAAI,CAAC,QAAQ,GAAG,oBAAY,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAA;QAEnD,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;YAC7B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,uCAAuC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC,CAAA;QAClG,CAAC,CAAC,CAAA;QAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAU,EAAE,EAAE;YACrC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,oCAAoC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAA;QACpE,CAAC,CAAC,CAAA;QAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;YAC7B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,sCAAsC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,CAAA;QAChG,CAAC,CAAC,CAAA;QAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAU,EAAE,EAAE;YACrC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,mCAAmC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAA;QACnE,CAAC,CAAC,CAAA;IACN,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAW;QACjB,OAAO,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IACvC,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAa,EAAE,IAAgB,EAAE,UAAkB;QACzD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;QACjD,IAAI,UAAU,KAAK,CAAC,CAAC,EAAE,CAAC;YACpB,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,UAAU,CAAC,CAAA;QAC/C,CAAC;QAED,OAAO,MAAM,CAAA;IACjB,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,OAAe;QAClC,OAAO,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IAC5C,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,IAAc;QAC1B,OAAO,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACzC,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,GAAG,GAAa;QACzB,OAAO,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,CAAA;IAC1C,CAAC;IAED,KAAK,CAAC,IAAI;QACN,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAA;IACnE,CAAC;IAED,SAAS;QACL,OAAO;YACH,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM;YAC/B,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM;SACjC,CAAA;IACL,CAAC;CACJ;AAjED,gDAiEC"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PubSubProvider = void 0;
|
|
4
|
+
const redis_1 = require("../redis");
|
|
5
|
+
class PubSubProvider {
|
|
6
|
+
logger;
|
|
7
|
+
pub;
|
|
8
|
+
sub;
|
|
9
|
+
oneTimeHandlerByChannel = {};
|
|
10
|
+
handlerByChannel = {};
|
|
11
|
+
constructor({ readWrite, readOnly }, logger) {
|
|
12
|
+
this.logger = logger;
|
|
13
|
+
this.pub = redis_1.RedisService.createClient(readWrite);
|
|
14
|
+
this.sub = redis_1.RedisService.createClient({ ...readOnly, autoResubscribe: true });
|
|
15
|
+
this.pub.on('connect', () => {
|
|
16
|
+
this.logger.info(`Redis READ-WRITE pub connection open to ${JSON.stringify(readWrite.sentinels)}`);
|
|
17
|
+
});
|
|
18
|
+
this.pub.on('error', (err) => {
|
|
19
|
+
this.logger.error('Redis READ-WRITE pub connection error ', { err });
|
|
20
|
+
});
|
|
21
|
+
this.sub.on('connect', () => {
|
|
22
|
+
this.logger.info(`Redis READ-ONLY sub connection open to ${JSON.stringify(readOnly.sentinels)}`);
|
|
23
|
+
});
|
|
24
|
+
this.sub.on('error', (err) => {
|
|
25
|
+
this.logger.error('Redis READ-ONLY sub connection error ', { err });
|
|
26
|
+
});
|
|
27
|
+
this.sub.on('message', async (channel, message) => {
|
|
28
|
+
const oneTimeHandler = this.oneTimeHandlerByChannel[channel];
|
|
29
|
+
if (oneTimeHandler) {
|
|
30
|
+
delete this.oneTimeHandlerByChannel[channel];
|
|
31
|
+
await this.sub.unsubscribe(channel);
|
|
32
|
+
try {
|
|
33
|
+
await oneTimeHandler(message);
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
this.logger.error(`Failed to handle message from the channel ${channel}`, { err });
|
|
37
|
+
}
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const handlerByChannel = this.handlerByChannel[channel];
|
|
41
|
+
if (handlerByChannel) {
|
|
42
|
+
try {
|
|
43
|
+
await handlerByChannel(message);
|
|
44
|
+
}
|
|
45
|
+
catch (err) {
|
|
46
|
+
this.logger.error(`Failed to handle message from the channel ${channel}`, { err });
|
|
47
|
+
}
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
this.logger.error(`Could not find a message handler for the channel ${channel}`);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
async unsubscribe(channel) {
|
|
54
|
+
delete this.oneTimeHandlerByChannel[channel];
|
|
55
|
+
delete this.handlerByChannel[channel];
|
|
56
|
+
return await this.sub.unsubscribe(channel);
|
|
57
|
+
}
|
|
58
|
+
async publish(channel, data) {
|
|
59
|
+
return await this.pub.publish(channel, JSON.stringify(data));
|
|
60
|
+
}
|
|
61
|
+
async onChannelMessage(channel, handler) {
|
|
62
|
+
if (Object.keys(this.handlerByChannel).includes(channel)) {
|
|
63
|
+
throw new Error(`Handler already exists by the provided channel ${channel}`);
|
|
64
|
+
}
|
|
65
|
+
this.handlerByChannel[channel] = handler;
|
|
66
|
+
await this.sub.subscribe(channel);
|
|
67
|
+
}
|
|
68
|
+
async onceChannelMessage(channel, handler) {
|
|
69
|
+
if (Object.keys(this.oneTimeHandlerByChannel).includes(channel)) {
|
|
70
|
+
throw new Error(`Handler already exists by the provided channel ${channel}`);
|
|
71
|
+
}
|
|
72
|
+
this.oneTimeHandlerByChannel[channel] = handler;
|
|
73
|
+
await this.sub.subscribe(channel);
|
|
74
|
+
}
|
|
75
|
+
async quit() {
|
|
76
|
+
await Promise.all([this.pub.quit(), this.sub.quit()]);
|
|
77
|
+
}
|
|
78
|
+
getStatus() {
|
|
79
|
+
return {
|
|
80
|
+
pub: this.pub.status,
|
|
81
|
+
sub: this.sub.status,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
exports.PubSubProvider = PubSubProvider;
|
|
86
|
+
//# sourceMappingURL=pubsub.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pubsub.js","sourceRoot":"","sources":["../../../src/services/providers/pubsub.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PubSubService = void 0;
|
|
4
|
+
const types_1 = require("@diia-inhouse/types");
|
|
5
|
+
const redis_1 = require("../interfaces/redis");
|
|
6
|
+
const pubsub_1 = require("./providers/pubsub");
|
|
7
|
+
class PubSubService {
|
|
8
|
+
redisConfig;
|
|
9
|
+
logger;
|
|
10
|
+
provider;
|
|
11
|
+
constructor(redisConfig, logger) {
|
|
12
|
+
this.redisConfig = redisConfig;
|
|
13
|
+
this.logger = logger;
|
|
14
|
+
this.provider = new pubsub_1.PubSubProvider(this.redisConfig, this.logger);
|
|
15
|
+
}
|
|
16
|
+
async onHealthCheck() {
|
|
17
|
+
const pubSubStatus = this.provider.getStatus();
|
|
18
|
+
const status = Object.values(pubSubStatus).some((s) => s !== redis_1.RedisStatusValue.Ready)
|
|
19
|
+
? types_1.HttpStatusCode.SERVICE_UNAVAILABLE
|
|
20
|
+
: types_1.HttpStatusCode.OK;
|
|
21
|
+
return {
|
|
22
|
+
status,
|
|
23
|
+
details: { pubsub: pubSubStatus },
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
async onDestroy() {
|
|
27
|
+
await this.provider.quit();
|
|
28
|
+
}
|
|
29
|
+
async unsubscribe(channel) {
|
|
30
|
+
return await this.provider.unsubscribe(channel);
|
|
31
|
+
}
|
|
32
|
+
async publish(channel, data) {
|
|
33
|
+
return await this.provider.publish(channel, data);
|
|
34
|
+
}
|
|
35
|
+
onceChannelMessage(channel, handler) {
|
|
36
|
+
return this.provider.onceChannelMessage(channel, handler);
|
|
37
|
+
}
|
|
38
|
+
async onChannelMessage(channel, handler) {
|
|
39
|
+
return await this.provider.onChannelMessage(channel, handler);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
exports.PubSubService = PubSubService;
|
|
43
|
+
//# sourceMappingURL=pubsub.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pubsub.js","sourceRoot":"","sources":["../../src/services/pubsub.ts"],"names":[],"mappings":";;;AAAA,+CAAyG;AAGzG,+CAAmE;AAEnE,+CAAmD;AAEnD,MAAa,aAAa;IAID;IAEA;IALJ,QAAQ,CAAgB;IAEzC,YACqB,WAAwB,EAExB,MAAc;QAFd,gBAAW,GAAX,WAAW,CAAa;QAExB,WAAM,GAAN,MAAM,CAAQ;QAE/B,IAAI,CAAC,QAAQ,GAAG,IAAI,uBAAc,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;IACrE,CAAC;IAED,KAAK,CAAC,aAAa;QACf,MAAM,YAAY,GAAiB,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAA;QAE5D,MAAM,MAAM,GAAmB,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,wBAAgB,CAAC,KAAK,CAAC;YAChG,CAAC,CAAC,sBAAc,CAAC,mBAAmB;YACpC,CAAC,CAAC,sBAAc,CAAC,EAAE,CAAA;QAEvB,OAAO;YACH,MAAM;YACN,OAAO,EAAE,EAAE,MAAM,EAAE,YAAY,EAAE;SACpC,CAAA;IACL,CAAC;IAED,KAAK,CAAC,SAAS;QACX,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAA;IAC9B,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,OAAe;QAC7B,OAAO,MAAM,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,OAAO,CAAC,CAAA;IACnD,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,OAAe,EAAE,IAAa;QACxC,OAAO,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;IACrD,CAAC;IAED,kBAAkB,CAAC,OAAe,EAAE,OAAuB;QACvD,OAAO,IAAI,CAAC,QAAQ,CAAC,kBAAkB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;IAC7D,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,OAAe,EAAE,OAAuB;QAC3D,OAAO,MAAM,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;IACjE,CAAC;CACJ;AA3CD,sCA2CC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.RedisService = void 0;
|
|
7
|
+
const ioredis_1 = __importDefault(require("ioredis"));
|
|
8
|
+
exports.RedisService = {
|
|
9
|
+
createClient(options) {
|
|
10
|
+
const redisOptions = {
|
|
11
|
+
enableAutoPipelining: true,
|
|
12
|
+
...options,
|
|
13
|
+
};
|
|
14
|
+
return new ioredis_1.default(redisOptions);
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=redis.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis.js","sourceRoot":"","sources":["../../src/services/redis.ts"],"names":[],"mappings":";;;;;;AAAA,sDAA6C;AAEhC,QAAA,YAAY,GAAG;IACxB,YAAY,CAAC,OAAqB;QAC9B,MAAM,YAAY,GAAiB;YAC/B,oBAAoB,EAAE,IAAI;YAC1B,GAAG,OAAO;SACb,CAAA;QAED,OAAO,IAAI,iBAAK,CAAC,YAAY,CAAC,CAAA;IAClC,CAAC;CACJ,CAAA"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.StoreService = void 0;
|
|
4
|
+
const errors_1 = require("@diia-inhouse/errors");
|
|
5
|
+
const types_1 = require("@diia-inhouse/types");
|
|
6
|
+
const redis_1 = require("../interfaces/redis");
|
|
7
|
+
const redis_2 = require("./redis");
|
|
8
|
+
class StoreService {
|
|
9
|
+
storeConfig;
|
|
10
|
+
logger;
|
|
11
|
+
clientRW;
|
|
12
|
+
clientRO;
|
|
13
|
+
tagsKey = '_tags';
|
|
14
|
+
constructor(storeConfig, logger) {
|
|
15
|
+
this.storeConfig = storeConfig;
|
|
16
|
+
this.logger = logger;
|
|
17
|
+
const { readWrite, readOnly } = this.storeConfig;
|
|
18
|
+
this.clientRW = redis_2.RedisService.createClient(readWrite);
|
|
19
|
+
this.clientRO = redis_2.RedisService.createClient(readOnly);
|
|
20
|
+
this.clientRW.on('connect', () => {
|
|
21
|
+
this.logger.info(`Store READ-WRITE connection open to ${JSON.stringify(readWrite.sentinels)}`);
|
|
22
|
+
});
|
|
23
|
+
this.clientRW.on('error', (err) => {
|
|
24
|
+
this.logger.info('Store READ-WRITE connection error ', { err });
|
|
25
|
+
this.logger.info(`Store Path ${JSON.stringify(readWrite.sentinels)}`);
|
|
26
|
+
});
|
|
27
|
+
this.clientRO.on('connect', () => {
|
|
28
|
+
this.logger.info(`Store READ-ONLY connection open to ${JSON.stringify(readOnly.sentinels)}`);
|
|
29
|
+
});
|
|
30
|
+
this.clientRO.on('error', (err) => {
|
|
31
|
+
this.logger.info('Store READ-ONLY connection error ', { err });
|
|
32
|
+
this.logger.info(`Store Path ${JSON.stringify(readOnly.sentinels)}`);
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
async onHealthCheck() {
|
|
36
|
+
const storeStatus = {
|
|
37
|
+
readWrite: this.clientRW.status,
|
|
38
|
+
readOnly: this.clientRO.status,
|
|
39
|
+
};
|
|
40
|
+
const status = Object.values(storeStatus).some((s) => s !== redis_1.RedisStatusValue.Ready)
|
|
41
|
+
? types_1.HttpStatusCode.SERVICE_UNAVAILABLE
|
|
42
|
+
: types_1.HttpStatusCode.OK;
|
|
43
|
+
return {
|
|
44
|
+
status,
|
|
45
|
+
details: { store: storeStatus },
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
async onDestroy() {
|
|
49
|
+
await Promise.all([this.clientRW.quit(), this.clientRO.quit()]);
|
|
50
|
+
}
|
|
51
|
+
async get(key) {
|
|
52
|
+
return await this.clientRO.get(key);
|
|
53
|
+
}
|
|
54
|
+
async mget(...keys) {
|
|
55
|
+
return await this.clientRO.mget(keys);
|
|
56
|
+
}
|
|
57
|
+
async getUsingTags(key) {
|
|
58
|
+
const [cachedValue, tagsValue] = await this.clientRO.mget(key, this.tagsKey);
|
|
59
|
+
if (!cachedValue) {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
const tagsConfig = tagsValue ? JSON.parse(tagsValue) : {};
|
|
63
|
+
try {
|
|
64
|
+
const item = JSON.parse(cachedValue);
|
|
65
|
+
if (Array.isArray(item?.tags)) {
|
|
66
|
+
const isValid = this.validate(item, tagsConfig);
|
|
67
|
+
if (isValid) {
|
|
68
|
+
return item.data;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
if (err instanceof Error) {
|
|
75
|
+
this.logger.error('Failed when parse value with tags', { err });
|
|
76
|
+
}
|
|
77
|
+
throw new errors_1.ServiceUnavailableError();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
async set(key, value, options = {}) {
|
|
81
|
+
const { ttl, tags } = options;
|
|
82
|
+
if (tags?.length) {
|
|
83
|
+
value = await this.wrapValueWithMetadata(value, tags);
|
|
84
|
+
}
|
|
85
|
+
if (ttl) {
|
|
86
|
+
return await this.clientRW.set(key, value, 'PX', ttl); // milliseconds
|
|
87
|
+
}
|
|
88
|
+
return await this.clientRW.set(key, value);
|
|
89
|
+
}
|
|
90
|
+
async keys(pattern) {
|
|
91
|
+
return await this.clientRW.keys(pattern);
|
|
92
|
+
}
|
|
93
|
+
async remember(key, closure, options = {}) {
|
|
94
|
+
const cachedValue = await this.get(key);
|
|
95
|
+
if (cachedValue) {
|
|
96
|
+
return cachedValue;
|
|
97
|
+
}
|
|
98
|
+
const result = await closure();
|
|
99
|
+
await this.set(key, result || '', options);
|
|
100
|
+
return result;
|
|
101
|
+
}
|
|
102
|
+
async remove(...keys) {
|
|
103
|
+
return await this.clientRW.del(...keys);
|
|
104
|
+
}
|
|
105
|
+
async bumpTags(tags) {
|
|
106
|
+
const tagsValue = await this.clientRO.get(this.tagsKey);
|
|
107
|
+
const tagsConfig = tagsValue ? JSON.parse(tagsValue) : {};
|
|
108
|
+
const timestamp = Date.now();
|
|
109
|
+
for (const tagKey of tags) {
|
|
110
|
+
tagsConfig[tagKey] = timestamp;
|
|
111
|
+
}
|
|
112
|
+
return await this.clientRW.set(this.tagsKey, JSON.stringify(tagsConfig));
|
|
113
|
+
}
|
|
114
|
+
async flushDb() {
|
|
115
|
+
return await this.clientRW.flushdb();
|
|
116
|
+
}
|
|
117
|
+
validate({ tags, timestamp }, tagsConfig) {
|
|
118
|
+
const tagTimestamps = Object.entries(tagsConfig)
|
|
119
|
+
.filter(([tag]) => tags.includes(tag))
|
|
120
|
+
.map(([, tagTimestamp]) => tagTimestamp);
|
|
121
|
+
return tagTimestamps.every((tagTimestamp) => tagTimestamp <= timestamp);
|
|
122
|
+
}
|
|
123
|
+
async wrapValueWithMetadata(data, tags) {
|
|
124
|
+
const tagsValue = await this.clientRO.get(this.tagsKey);
|
|
125
|
+
const tagsConfig = tagsValue ? JSON.parse(tagsValue) : {};
|
|
126
|
+
const tagTimestamps = Object.entries(tagsConfig)
|
|
127
|
+
.filter(([tag]) => tags.includes(tag))
|
|
128
|
+
.map(([, tagTimestamp]) => tagTimestamp);
|
|
129
|
+
const timestamp = tagTimestamps.length > 0 ? Math.max(...tagTimestamps) : 0;
|
|
130
|
+
const wrappedValue = { data, tags, timestamp };
|
|
131
|
+
return JSON.stringify(wrappedValue);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
exports.StoreService = StoreService;
|
|
135
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/services/store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { RedisKey, RedisValue } from 'ioredis';
|
|
2
|
+
import { CacheStatus } from './redis';
|
|
3
|
+
export interface CacheProvider {
|
|
4
|
+
get(key: RedisKey): Promise<string | null>;
|
|
5
|
+
set(key: RedisKey, data: RedisValue, expiration: number): Promise<string>;
|
|
6
|
+
getKeysByPattern(pattern: string): Promise<string[]>;
|
|
7
|
+
getByKeys(keys: string[]): Promise<(null | string)[]>;
|
|
8
|
+
remove(...key: string[]): Promise<number>;
|
|
9
|
+
getStatus(): CacheStatus;
|
|
10
|
+
quit(): Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
export type CacheStatusResult = {
|
|
13
|
+
cache: CacheStatus;
|
|
14
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { RedisStatus } from './redis';
|
|
2
|
+
export interface PubSubStatus {
|
|
3
|
+
pub: RedisStatus;
|
|
4
|
+
sub: RedisStatus;
|
|
5
|
+
}
|
|
6
|
+
export type PubSubStatusResult = {
|
|
7
|
+
pubsub: PubSubStatus;
|
|
8
|
+
};
|
|
9
|
+
export type MessageHandler = (message: string) => Promise<unknown>;
|
|
10
|
+
export interface PubSubServiceProvider {
|
|
11
|
+
unsubscribe(channel: string): Promise<unknown>;
|
|
12
|
+
publish(channel: string, data: unknown): Promise<number>;
|
|
13
|
+
onceChannelMessage(channel: string, handler: MessageHandler): Promise<void>;
|
|
14
|
+
getStatus(): PubSubStatus;
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { RedisOptions } from 'ioredis';
|
|
2
|
+
export { RedisOptions } from 'ioredis';
|
|
3
|
+
export declare enum RedisStatusValue {
|
|
4
|
+
Ready = "ready"
|
|
5
|
+
}
|
|
6
|
+
export type RedisStatus = RedisStatusValue | string;
|
|
7
|
+
export interface RedisConfig {
|
|
8
|
+
readWrite: RedisOptions;
|
|
9
|
+
readOnly: RedisOptions;
|
|
10
|
+
enablePubsub?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface CacheStatus {
|
|
13
|
+
readWrite: RedisStatus;
|
|
14
|
+
readOnly: RedisStatus;
|
|
15
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { CacheStatus } from './redis';
|
|
2
|
+
export declare enum StoreTag {
|
|
3
|
+
PublicService = "publicService",
|
|
4
|
+
PublicServiceCategory = "publicServiceCategory",
|
|
5
|
+
Faq = "faq",
|
|
6
|
+
ErrorTemplate = "errorTemplate",
|
|
7
|
+
MilitaryBondsName = "militaryBondsName"
|
|
8
|
+
}
|
|
9
|
+
export type TagsConfig = {
|
|
10
|
+
[tag in StoreTag]?: number;
|
|
11
|
+
};
|
|
12
|
+
export interface TaggedStoreValue {
|
|
13
|
+
data: string;
|
|
14
|
+
timestamp: number;
|
|
15
|
+
tags: StoreTag[];
|
|
16
|
+
}
|
|
17
|
+
export interface SetValueOptions {
|
|
18
|
+
ttl?: number;
|
|
19
|
+
tags?: StoreTag[];
|
|
20
|
+
}
|
|
21
|
+
export type StoreStatusResult = {
|
|
22
|
+
store: CacheStatus;
|
|
23
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { RedisKey, RedisValue } from 'ioredis';
|
|
2
|
+
import { EnvService } from '@diia-inhouse/env';
|
|
3
|
+
import { HealthCheckResult, Logger, OnDestroy, OnHealthCheck } from '@diia-inhouse/types';
|
|
4
|
+
import { CacheStatusResult } from '../interfaces/cache';
|
|
5
|
+
import { RedisConfig } from '../interfaces/redis';
|
|
6
|
+
/**
|
|
7
|
+
* @deprecated StoreService class should be used instead of this one
|
|
8
|
+
*/
|
|
9
|
+
export declare class CacheService implements OnHealthCheck, OnDestroy {
|
|
10
|
+
private readonly redisConfig;
|
|
11
|
+
private readonly envService;
|
|
12
|
+
private readonly logger;
|
|
13
|
+
private readonly defaultExpiration;
|
|
14
|
+
private readonly provider;
|
|
15
|
+
constructor(redisConfig: RedisConfig, envService: EnvService, logger: Logger);
|
|
16
|
+
onHealthCheck(): Promise<HealthCheckResult<CacheStatusResult>>;
|
|
17
|
+
onDestroy(): Promise<void>;
|
|
18
|
+
get(key: RedisKey): Promise<string | null>;
|
|
19
|
+
set(key: RedisKey, data: RedisValue, expiration?: number): Promise<string>;
|
|
20
|
+
getKeysByPattern(pattern: string): Promise<string[]>;
|
|
21
|
+
getByKeys(keys: string[]): Promise<(string | null)[]>;
|
|
22
|
+
remove(key: string): Promise<number>;
|
|
23
|
+
private addPrefix;
|
|
24
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { RedlockMutex } from 'redis-semaphore';
|
|
2
|
+
import { HealthCheckResult, Logger, OnDestroy, OnHealthCheck } from '@diia-inhouse/types';
|
|
3
|
+
import { MutexStatusResult } from '../interfaces';
|
|
4
|
+
import { RedisConfig } from '../interfaces/redis';
|
|
5
|
+
export declare class RedlockService implements OnHealthCheck, OnDestroy {
|
|
6
|
+
private readonly storeConfig;
|
|
7
|
+
private readonly logger;
|
|
8
|
+
private clientRW;
|
|
9
|
+
constructor(storeConfig: RedisConfig, logger: Logger);
|
|
10
|
+
onHealthCheck(): Promise<HealthCheckResult<MutexStatusResult>>;
|
|
11
|
+
onDestroy(): Promise<void>;
|
|
12
|
+
lock(resource: string, ttl?: number): Promise<RedlockMutex>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { RedisKey, RedisValue } from 'ioredis';
|
|
2
|
+
import { Logger } from '@diia-inhouse/types';
|
|
3
|
+
import { CacheProvider } from '../../interfaces/cache';
|
|
4
|
+
import { CacheStatus, RedisConfig } from '../../interfaces/redis';
|
|
5
|
+
export declare class RedisCacheProvider implements CacheProvider {
|
|
6
|
+
private readonly logger;
|
|
7
|
+
private clientRW;
|
|
8
|
+
private clientRO;
|
|
9
|
+
constructor({ readWrite, readOnly }: RedisConfig, logger: Logger);
|
|
10
|
+
get(key: string): Promise<string | null>;
|
|
11
|
+
set(key: RedisKey, data: RedisValue, expiration: number): Promise<string>;
|
|
12
|
+
getKeysByPattern(pattern: string): Promise<string[]>;
|
|
13
|
+
getByKeys(keys: string[]): Promise<(string | null)[]>;
|
|
14
|
+
remove(...key: string[]): Promise<number>;
|
|
15
|
+
quit(): Promise<void>;
|
|
16
|
+
getStatus(): CacheStatus;
|
|
17
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Logger } from '@diia-inhouse/types';
|
|
2
|
+
import { MessageHandler, PubSubServiceProvider, PubSubStatus } from '../../interfaces/pubsub';
|
|
3
|
+
import { RedisConfig } from '../../interfaces/redis';
|
|
4
|
+
export declare class PubSubProvider implements PubSubServiceProvider {
|
|
5
|
+
private readonly logger;
|
|
6
|
+
private pub;
|
|
7
|
+
private sub;
|
|
8
|
+
private readonly oneTimeHandlerByChannel;
|
|
9
|
+
private readonly handlerByChannel;
|
|
10
|
+
constructor({ readWrite, readOnly }: RedisConfig, logger: Logger);
|
|
11
|
+
unsubscribe(channel: string): Promise<unknown>;
|
|
12
|
+
publish(channel: string, data: unknown): Promise<number>;
|
|
13
|
+
onChannelMessage(channel: string, handler: MessageHandler): Promise<void>;
|
|
14
|
+
onceChannelMessage(channel: string, handler: MessageHandler): Promise<void>;
|
|
15
|
+
quit(): Promise<void>;
|
|
16
|
+
getStatus(): PubSubStatus;
|
|
17
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { HealthCheckResult, Logger, OnDestroy, OnHealthCheck } from '@diia-inhouse/types';
|
|
2
|
+
import { MessageHandler, PubSubStatusResult } from '../interfaces/pubsub';
|
|
3
|
+
import { RedisConfig } from '../interfaces/redis';
|
|
4
|
+
export declare class PubSubService implements OnHealthCheck, OnDestroy {
|
|
5
|
+
private readonly redisConfig;
|
|
6
|
+
private readonly logger;
|
|
7
|
+
private readonly provider;
|
|
8
|
+
constructor(redisConfig: RedisConfig, logger: Logger);
|
|
9
|
+
onHealthCheck(): Promise<HealthCheckResult<PubSubStatusResult>>;
|
|
10
|
+
onDestroy(): Promise<void>;
|
|
11
|
+
unsubscribe(channel: string): Promise<unknown>;
|
|
12
|
+
publish(channel: string, data: unknown): Promise<number>;
|
|
13
|
+
onceChannelMessage(channel: string, handler: MessageHandler): Promise<void>;
|
|
14
|
+
onChannelMessage(channel: string, handler: MessageHandler): Promise<void>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { HealthCheckResult, Logger, OnDestroy, OnHealthCheck } from '@diia-inhouse/types';
|
|
2
|
+
import { RedisConfig } from '../interfaces/redis';
|
|
3
|
+
import { SetValueOptions, StoreStatusResult, StoreTag } from '../interfaces/store';
|
|
4
|
+
export declare class StoreService implements OnHealthCheck, OnDestroy {
|
|
5
|
+
private readonly storeConfig;
|
|
6
|
+
private readonly logger;
|
|
7
|
+
private clientRW;
|
|
8
|
+
private clientRO;
|
|
9
|
+
private tagsKey;
|
|
10
|
+
constructor(storeConfig: RedisConfig, logger: Logger);
|
|
11
|
+
onHealthCheck(): Promise<HealthCheckResult<StoreStatusResult>>;
|
|
12
|
+
onDestroy(): Promise<void>;
|
|
13
|
+
get(key: string): Promise<string | null>;
|
|
14
|
+
mget(...keys: string[]): Promise<(string | null)[]>;
|
|
15
|
+
getUsingTags(key: string): Promise<string | null>;
|
|
16
|
+
set(key: string, value: string, options?: SetValueOptions): Promise<'OK' | null>;
|
|
17
|
+
keys(pattern: string): Promise<string[]>;
|
|
18
|
+
remember(key: string, closure: () => Promise<string | null>, options?: SetValueOptions): Promise<string | null>;
|
|
19
|
+
remove(...keys: string[]): Promise<number>;
|
|
20
|
+
bumpTags(tags: StoreTag[]): Promise<'OK' | null>;
|
|
21
|
+
flushDb(): Promise<'OK'>;
|
|
22
|
+
private validate;
|
|
23
|
+
private wrapValueWithMetadata;
|
|
24
|
+
}
|