@diia-inhouse/redis 2.30.21 → 3.1.1

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.
Files changed (52) hide show
  1. package/dist/index.d.ts +10 -0
  2. package/dist/index.js +9 -20
  3. package/dist/interfaces/deps.d.ts +11 -0
  4. package/dist/interfaces/index.d.ts +4 -0
  5. package/dist/interfaces/index.js +3 -21
  6. package/dist/interfaces/mutex.d.ts +16 -0
  7. package/dist/interfaces/mutex.js +2 -6
  8. package/dist/interfaces/pubsub.d.ts +19 -0
  9. package/dist/interfaces/redis.d.ts +28 -0
  10. package/dist/interfaces/redis.js +12 -13
  11. package/dist/interfaces/store.d.ts +32 -0
  12. package/dist/services/index.d.ts +4 -0
  13. package/dist/services/index.js +5 -21
  14. package/dist/services/mutex.d.ts +19 -0
  15. package/dist/services/mutex.js +52 -44
  16. package/dist/services/providers/pubsub.js +96 -89
  17. package/dist/services/pubsub.d.ts +19 -0
  18. package/dist/services/pubsub.js +38 -43
  19. package/dist/services/redis.d.ts +10 -0
  20. package/dist/services/redis.js +84 -65
  21. package/dist/services/store.d.ts +47 -0
  22. package/dist/services/store.js +170 -183
  23. package/package.json +41 -32
  24. package/dist/index.js.map +0 -1
  25. package/dist/interfaces/deps.js +0 -3
  26. package/dist/interfaces/deps.js.map +0 -1
  27. package/dist/interfaces/index.js.map +0 -1
  28. package/dist/interfaces/mutex.js.map +0 -1
  29. package/dist/interfaces/pubsub.js +0 -3
  30. package/dist/interfaces/pubsub.js.map +0 -1
  31. package/dist/interfaces/redis.js.map +0 -1
  32. package/dist/interfaces/store.js +0 -3
  33. package/dist/interfaces/store.js.map +0 -1
  34. package/dist/services/index.js.map +0 -1
  35. package/dist/services/mutex.js.map +0 -1
  36. package/dist/services/providers/pubsub.js.map +0 -1
  37. package/dist/services/pubsub.js.map +0 -1
  38. package/dist/services/redis.js.map +0 -1
  39. package/dist/services/store.js.map +0 -1
  40. package/dist/types/index.d.ts +0 -3
  41. package/dist/types/interfaces/deps.d.ts +0 -6
  42. package/dist/types/interfaces/index.d.ts +0 -4
  43. package/dist/types/interfaces/mutex.d.ts +0 -13
  44. package/dist/types/interfaces/pubsub.d.ts +0 -15
  45. package/dist/types/interfaces/redis.d.ts +0 -24
  46. package/dist/types/interfaces/store.d.ts +0 -30
  47. package/dist/types/services/index.d.ts +0 -4
  48. package/dist/types/services/mutex.d.ts +0 -13
  49. package/dist/types/services/providers/pubsub.d.ts +0 -17
  50. package/dist/types/services/pubsub.d.ts +0 -15
  51. package/dist/types/services/redis.d.ts +0 -6
  52. package/dist/types/services/store.d.ts +0 -43
@@ -0,0 +1,10 @@
1
+ import { RedisConfig, RedisMode, RedisOptions, RedisStatus, RedisStatusValue, StoreStatus } from "./interfaces/redis.js";
2
+ import { MessageHandler, PubSubServiceProvider, PubSubStatus, PubSubStatusResult } from "./interfaces/pubsub.js";
3
+ import { Lock, LockOptions, MutexStatusResult, RedlockMutex } from "./interfaces/mutex.js";
4
+ import { SetValueOptions, StoreStatusResult, TaggedStoreValue, TagsConfig, ThrottleResult } from "./interfaces/store.js";
5
+ import { PubSubService } from "./services/pubsub.js";
6
+ import { RedisService } from "./services/redis.js";
7
+ import { StoreService } from "./services/store.js";
8
+ import { RedlockService } from "./services/mutex.js";
9
+ import { RedisDeps } from "./interfaces/deps.js";
10
+ export { Lock, LockOptions, MessageHandler, MutexStatusResult, PubSubService, PubSubServiceProvider, PubSubStatus, PubSubStatusResult, RedisConfig, RedisDeps, RedisMode, RedisOptions, RedisService, RedisStatus, RedisStatusValue, RedlockMutex, RedlockService, SetValueOptions, StoreService, StoreStatus, StoreStatusResult, TaggedStoreValue, TagsConfig, ThrottleResult };
package/dist/index.js CHANGED
@@ -1,20 +1,9 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
- };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./interfaces"), exports);
18
- __exportStar(require("./interfaces/deps"), exports);
19
- __exportStar(require("./services"), exports);
20
- //# sourceMappingURL=index.js.map
1
+ import { RedisMode, RedisStatusValue } from "./interfaces/redis.js";
2
+ import { RedlockMutex } from "./interfaces/mutex.js";
3
+ import "./interfaces/index.js";
4
+ import { RedisService } from "./services/redis.js";
5
+ import { PubSubService } from "./services/pubsub.js";
6
+ import { StoreService } from "./services/store.js";
7
+ import { RedlockService } from "./services/mutex.js";
8
+ import "./services/index.js";
9
+ export { PubSubService, RedisMode, RedisService, RedisStatusValue, RedlockMutex, RedlockService, StoreService };
@@ -0,0 +1,11 @@
1
+ import { PubSubService } from "../services/pubsub.js";
2
+ import { StoreService } from "../services/store.js";
3
+ import { RedlockService } from "../services/mutex.js";
4
+ //#region src/interfaces/deps.d.ts
5
+ type RedisDeps = {
6
+ pubsub?: PubSubService;
7
+ redlock?: RedlockService;
8
+ store?: StoreService;
9
+ };
10
+ //#endregion
11
+ export { RedisDeps };
@@ -0,0 +1,4 @@
1
+ import { RedisConfig, RedisMode, RedisOptions, RedisStatus, RedisStatusValue, StoreStatus } from "./redis.js";
2
+ import { MessageHandler, PubSubServiceProvider, PubSubStatus, PubSubStatusResult } from "./pubsub.js";
3
+ import { Lock, LockOptions, MutexStatusResult, RedlockMutex } from "./mutex.js";
4
+ import { SetValueOptions, StoreStatusResult, TaggedStoreValue, TagsConfig, ThrottleResult } from "./store.js";
@@ -1,21 +1,3 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
- };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./pubsub"), exports);
18
- __exportStar(require("./redis"), exports);
19
- __exportStar(require("./mutex"), exports);
20
- __exportStar(require("./store"), exports);
21
- //# sourceMappingURL=index.js.map
1
+ import "./redis.js";
2
+ import "./mutex.js";
3
+ export {};
@@ -0,0 +1,16 @@
1
+ import { RedlockMutex, RedlockMutex as RedlockMutex$1 } from "redis-semaphore";
2
+
3
+ //#region src/interfaces/mutex.d.ts
4
+ type Lock = RedlockMutex;
5
+ type MutexStatusResult = {
6
+ mutex: string;
7
+ };
8
+ type LockOptions = {
9
+ /**
10
+ * Time in milliseconds between acquire attempts if resource locked
11
+ * @defaultValue 500
12
+ */
13
+ retryInterval?: number;
14
+ };
15
+ //#endregion
16
+ export { Lock, LockOptions, MutexStatusResult, RedlockMutex$1 as RedlockMutex };
@@ -1,6 +1,2 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RedlockMutex = void 0;
4
- var redis_semaphore_1 = require("redis-semaphore");
5
- Object.defineProperty(exports, "RedlockMutex", { enumerable: true, get: function () { return redis_semaphore_1.RedlockMutex; } });
6
- //# sourceMappingURL=mutex.js.map
1
+ import { RedlockMutex as RedlockMutex$1 } from "redis-semaphore";
2
+ export { RedlockMutex$1 as RedlockMutex };
@@ -0,0 +1,19 @@
1
+ import { RedisStatus } from "./redis.js";
2
+
3
+ //#region src/interfaces/pubsub.d.ts
4
+ interface PubSubStatus {
5
+ pub: RedisStatus;
6
+ sub: RedisStatus;
7
+ }
8
+ type PubSubStatusResult = {
9
+ pubsub: PubSubStatus;
10
+ };
11
+ type MessageHandler = (message: string) => Promise<unknown>;
12
+ interface PubSubServiceProvider {
13
+ unsubscribe(channel: string): Promise<unknown>;
14
+ publish(channel: string, data: unknown): Promise<number>;
15
+ onceChannelMessage(channel: string, handler: MessageHandler): Promise<void>;
16
+ getStatus(): PubSubStatus;
17
+ }
18
+ //#endregion
19
+ export { MessageHandler, PubSubServiceProvider, PubSubStatus, PubSubStatusResult };
@@ -0,0 +1,28 @@
1
+ import { RedisOptions } from "ioredis";
2
+
3
+ //#region src/interfaces/redis.d.ts
4
+ declare enum RedisMode {
5
+ ReadWrite = "READ-WRITE",
6
+ ReadOnly = "READ-ONLY"
7
+ }
8
+ interface RedisOptions$1 extends RedisOptions {
9
+ maxRetryAttempts?: number;
10
+ initialRetryDelay?: number;
11
+ maxRetryDelay?: number;
12
+ redisMode?: RedisMode;
13
+ }
14
+ declare enum RedisStatusValue {
15
+ Ready = "ready"
16
+ }
17
+ type RedisStatus = RedisStatusValue | string;
18
+ interface RedisConfig {
19
+ readWrite: RedisOptions$1;
20
+ readOnly: RedisOptions$1;
21
+ enablePubsub?: boolean;
22
+ }
23
+ interface StoreStatus {
24
+ readWrite: RedisStatus;
25
+ readOnly: RedisStatus;
26
+ }
27
+ //#endregion
28
+ export { RedisConfig, RedisMode, RedisOptions$1 as RedisOptions, RedisStatus, RedisStatusValue, StoreStatus };
@@ -1,13 +1,12 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RedisStatusValue = exports.RedisMode = void 0;
4
- var RedisMode;
5
- (function (RedisMode) {
6
- RedisMode["ReadWrite"] = "READ-WRITE";
7
- RedisMode["ReadOnly"] = "READ-ONLY";
8
- })(RedisMode || (exports.RedisMode = RedisMode = {}));
9
- var RedisStatusValue;
10
- (function (RedisStatusValue) {
11
- RedisStatusValue["Ready"] = "ready";
12
- })(RedisStatusValue || (exports.RedisStatusValue = RedisStatusValue = {}));
13
- //# sourceMappingURL=redis.js.map
1
+ //#region src/interfaces/redis.ts
2
+ let RedisMode = /* @__PURE__ */ function(RedisMode) {
3
+ RedisMode["ReadWrite"] = "READ-WRITE";
4
+ RedisMode["ReadOnly"] = "READ-ONLY";
5
+ return RedisMode;
6
+ }({});
7
+ let RedisStatusValue = /* @__PURE__ */ function(RedisStatusValue) {
8
+ RedisStatusValue["Ready"] = "ready";
9
+ return RedisStatusValue;
10
+ }({});
11
+ //#endregion
12
+ export { RedisMode, RedisStatusValue };
@@ -0,0 +1,32 @@
1
+ import { StoreStatus } from "./redis.js";
2
+
3
+ //#region src/interfaces/store.d.ts
4
+ type TagsConfig = { [tag in string]?: number };
5
+ interface TaggedStoreValue {
6
+ data: string;
7
+ timestamp: number;
8
+ tags: string[];
9
+ }
10
+ interface SetValueOptions {
11
+ /**
12
+ * Time to live in milliseconds.
13
+ * If not set, the key will be permanent.
14
+ */
15
+ ttl?: number;
16
+ /**
17
+ * Tags associated with the value.
18
+ */
19
+ tags?: string[];
20
+ }
21
+ interface ThrottleResult {
22
+ limited: boolean;
23
+ totalLimit: number;
24
+ remaining: number;
25
+ retryAfterSec: number;
26
+ resetAfterSec: number;
27
+ }
28
+ type StoreStatusResult = {
29
+ store: StoreStatus;
30
+ };
31
+ //#endregion
32
+ export { SetValueOptions, StoreStatusResult, TaggedStoreValue, TagsConfig, ThrottleResult };
@@ -0,0 +1,4 @@
1
+ import { PubSubService } from "./pubsub.js";
2
+ import { RedisService } from "./redis.js";
3
+ import { StoreService } from "./store.js";
4
+ import { RedlockService } from "./mutex.js";
@@ -1,21 +1,5 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
- };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./pubsub"), exports);
18
- __exportStar(require("./redis"), exports);
19
- __exportStar(require("./store"), exports);
20
- __exportStar(require("./mutex"), exports);
21
- //# sourceMappingURL=index.js.map
1
+ import "./redis.js";
2
+ import "./pubsub.js";
3
+ import "./store.js";
4
+ import "./mutex.js";
5
+ export {};
@@ -0,0 +1,19 @@
1
+ import { RedisConfig } from "../interfaces/redis.js";
2
+ import { LockOptions, MutexStatusResult } from "../interfaces/mutex.js";
3
+ import { RedlockMutex } from "redis-semaphore";
4
+ import { HealthCheckResult, Logger, OnDestroy, OnHealthCheck } from "@diia-inhouse/types";
5
+
6
+ //#region src/services/mutex.d.ts
7
+ declare class RedlockService implements OnHealthCheck, OnDestroy {
8
+ private readonly storeConfig;
9
+ private readonly logger;
10
+ private clientRW;
11
+ constructor(storeConfig: RedisConfig, logger: Logger);
12
+ onHealthCheck(): Promise<HealthCheckResult<MutexStatusResult>>;
13
+ onDestroy(): Promise<void>;
14
+ lock(resource: string, ttl?: number, {
15
+ retryInterval
16
+ }?: LockOptions): Promise<RedlockMutex>;
17
+ }
18
+ //#endregion
19
+ export { RedlockService };
@@ -1,44 +1,52 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RedlockService = void 0;
4
- const redis_semaphore_1 = require("redis-semaphore");
5
- const types_1 = require("@diia-inhouse/types");
6
- const redis_1 = require("../interfaces/redis");
7
- const redis_2 = require("./redis");
8
- class RedlockService {
9
- storeConfig;
10
- logger;
11
- clientRW;
12
- constructor(storeConfig, logger) {
13
- this.storeConfig = storeConfig;
14
- this.logger = logger;
15
- const { readWrite } = this.storeConfig;
16
- this.clientRW = redis_2.RedisService.createClient({ ...readWrite, redisMode: redis_1.RedisMode.ReadWrite }, this.logger);
17
- this.clientRW.on('connect', () => {
18
- const { host, port, sentinels } = readWrite;
19
- this.logger.info('Redis REDLOCK READ-WRITE connection open', { host, port, sentinels });
20
- });
21
- this.clientRW.on('error', (err) => {
22
- this.logger.error('Redis REDLOCK READ-WRITE connection error ', { err });
23
- });
24
- }
25
- async onHealthCheck() {
26
- const cacheStatus = this.clientRW.status;
27
- const status = cacheStatus === redis_1.RedisStatusValue.Ready ? types_1.HttpStatusCode.OK : types_1.HttpStatusCode.SERVICE_UNAVAILABLE;
28
- return {
29
- status,
30
- details: { mutex: cacheStatus },
31
- };
32
- }
33
- async onDestroy() {
34
- await this.clientRW.quit();
35
- }
36
- async lock(resource, ttl = 60000, { retryInterval = 500 } = {}) {
37
- this.logger.info(`Start LOCK resource [${resource}] for ttl [${ttl}]ms`);
38
- const mutex = new redis_semaphore_1.RedlockMutex([this.clientRW], resource, { lockTimeout: ttl, acquireTimeout: ttl * 2, retryInterval });
39
- await mutex.acquire();
40
- return mutex;
41
- }
42
- }
43
- exports.RedlockService = RedlockService;
44
- //# sourceMappingURL=mutex.js.map
1
+ import "../interfaces/redis.js";
2
+ import { RedisService } from "./redis.js";
3
+ import { RedlockMutex } from "redis-semaphore";
4
+ import { HttpStatusCode } from "@diia-inhouse/types";
5
+ //#region src/services/mutex.ts
6
+ var RedlockService = class {
7
+ storeConfig;
8
+ logger;
9
+ clientRW;
10
+ constructor(storeConfig, logger) {
11
+ this.storeConfig = storeConfig;
12
+ this.logger = logger;
13
+ const { readWrite } = this.storeConfig;
14
+ this.clientRW = RedisService.createClient({
15
+ ...readWrite,
16
+ redisMode: "READ-WRITE"
17
+ }, this.logger);
18
+ this.clientRW.on("connect", () => {
19
+ const { host, port, sentinels } = readWrite;
20
+ this.logger.info("Redis REDLOCK READ-WRITE connection open", {
21
+ host,
22
+ port,
23
+ sentinels
24
+ });
25
+ });
26
+ this.clientRW.on("error", (err) => {
27
+ this.logger.error("Redis REDLOCK READ-WRITE connection error ", { err });
28
+ });
29
+ }
30
+ async onHealthCheck() {
31
+ const cacheStatus = this.clientRW.status;
32
+ return {
33
+ status: cacheStatus === "ready" ? HttpStatusCode.OK : HttpStatusCode.SERVICE_UNAVAILABLE,
34
+ details: { mutex: cacheStatus }
35
+ };
36
+ }
37
+ async onDestroy() {
38
+ await this.clientRW.quit();
39
+ }
40
+ async lock(resource, ttl = 6e4, { retryInterval = 500 } = {}) {
41
+ this.logger.info(`Start LOCK resource [${resource}] for ttl [${ttl}]ms`);
42
+ const mutex = new RedlockMutex([this.clientRW], resource, {
43
+ lockTimeout: ttl,
44
+ acquireTimeout: ttl * 2,
45
+ retryInterval
46
+ });
47
+ await mutex.acquire();
48
+ return mutex;
49
+ }
50
+ };
51
+ //#endregion
52
+ export { RedlockService };
@@ -1,89 +1,96 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.PubSubProvider = void 0;
4
- const redis_1 = require("../../interfaces/redis");
5
- const redis_2 = require("../redis");
6
- class PubSubProvider {
7
- logger;
8
- pub;
9
- sub;
10
- oneTimeHandlerByChannel = {};
11
- handlerByChannel = {};
12
- constructor({ readWrite }, logger) {
13
- this.logger = logger;
14
- this.pub = redis_2.RedisService.createClient({ ...readWrite, redisMode: redis_1.RedisMode.ReadWrite }, this.logger);
15
- this.sub = redis_2.RedisService.createClient({ ...readWrite, redisMode: redis_1.RedisMode.ReadWrite, autoResubscribe: true }, this.logger);
16
- this.pub.on('connect', () => {
17
- const { host, port, sentinels } = readWrite;
18
- this.logger.info('Redis READ-WRITE pub connection open', { host, port, sentinels });
19
- });
20
- this.pub.on('error', (err) => {
21
- this.logger.error('Redis READ-WRITE pub connection error ', { err });
22
- });
23
- this.sub.on('connect', () => {
24
- const { host, port, sentinels } = readWrite;
25
- this.logger.info('Redis READ-WRITE sub connection open', { host, port, sentinels });
26
- });
27
- this.sub.on('error', (err) => {
28
- this.logger.error('Redis READ-WRITE sub connection error ', { err });
29
- });
30
- this.sub.on('message', async (channel, message) => {
31
- const oneTimeHandler = this.oneTimeHandlerByChannel[channel];
32
- if (oneTimeHandler) {
33
- delete this.oneTimeHandlerByChannel[channel];
34
- await this.sub.unsubscribe(channel);
35
- try {
36
- await oneTimeHandler(message);
37
- }
38
- catch (err) {
39
- this.logger.error(`Failed to handle message from the channel ${channel}`, { err });
40
- }
41
- return;
42
- }
43
- const handlerByChannel = this.handlerByChannel[channel];
44
- if (handlerByChannel) {
45
- try {
46
- await handlerByChannel(message);
47
- }
48
- catch (err) {
49
- this.logger.error(`Failed to handle message from the channel ${channel}`, { err });
50
- }
51
- return;
52
- }
53
- this.logger.error(`Could not find a message handler for the channel ${channel}`);
54
- });
55
- }
56
- async unsubscribe(channel) {
57
- delete this.oneTimeHandlerByChannel[channel];
58
- delete this.handlerByChannel[channel];
59
- return await this.sub.unsubscribe(channel);
60
- }
61
- async publish(channel, data) {
62
- return await this.pub.publish(channel, JSON.stringify(data));
63
- }
64
- async onChannelMessage(channel, handler) {
65
- if (Object.keys(this.handlerByChannel).includes(channel)) {
66
- throw new Error(`Handler already exists by the provided channel ${channel}`);
67
- }
68
- this.handlerByChannel[channel] = handler;
69
- await this.sub.subscribe(channel);
70
- }
71
- async onceChannelMessage(channel, handler) {
72
- if (Object.keys(this.oneTimeHandlerByChannel).includes(channel)) {
73
- throw new Error(`Handler already exists by the provided channel ${channel}`);
74
- }
75
- this.oneTimeHandlerByChannel[channel] = handler;
76
- await this.sub.subscribe(channel);
77
- }
78
- async quit() {
79
- await Promise.all([this.pub.quit(), this.sub.quit()]);
80
- }
81
- getStatus() {
82
- return {
83
- pub: this.pub.status,
84
- sub: this.sub.status,
85
- };
86
- }
87
- }
88
- exports.PubSubProvider = PubSubProvider;
89
- //# sourceMappingURL=pubsub.js.map
1
+ import "../../interfaces/redis.js";
2
+ import { RedisService } from "../redis.js";
3
+ //#region src/services/providers/pubsub.ts
4
+ var PubSubProvider = class {
5
+ logger;
6
+ pub;
7
+ sub;
8
+ oneTimeHandlerByChannel = {};
9
+ handlerByChannel = {};
10
+ constructor({ readWrite }, logger) {
11
+ this.logger = logger;
12
+ this.pub = RedisService.createClient({
13
+ ...readWrite,
14
+ redisMode: "READ-WRITE"
15
+ }, this.logger);
16
+ this.sub = RedisService.createClient({
17
+ ...readWrite,
18
+ redisMode: "READ-WRITE",
19
+ autoResubscribe: true
20
+ }, this.logger);
21
+ this.pub.on("connect", () => {
22
+ const { host, port, sentinels } = readWrite;
23
+ this.logger.info("Redis READ-WRITE pub connection open", {
24
+ host,
25
+ port,
26
+ sentinels
27
+ });
28
+ });
29
+ this.pub.on("error", (err) => {
30
+ this.logger.error("Redis READ-WRITE pub connection error ", { err });
31
+ });
32
+ this.sub.on("connect", () => {
33
+ const { host, port, sentinels } = readWrite;
34
+ this.logger.info("Redis READ-WRITE sub connection open", {
35
+ host,
36
+ port,
37
+ sentinels
38
+ });
39
+ });
40
+ this.sub.on("error", (err) => {
41
+ this.logger.error("Redis READ-WRITE sub connection error ", { err });
42
+ });
43
+ this.sub.on("message", async (channel, message) => {
44
+ const oneTimeHandler = this.oneTimeHandlerByChannel[channel];
45
+ if (oneTimeHandler) {
46
+ delete this.oneTimeHandlerByChannel[channel];
47
+ await this.sub.unsubscribe(channel);
48
+ try {
49
+ await oneTimeHandler(message);
50
+ } catch (err) {
51
+ this.logger.error(`Failed to handle message from the channel ${channel}`, { err });
52
+ }
53
+ return;
54
+ }
55
+ const handlerByChannel = this.handlerByChannel[channel];
56
+ if (handlerByChannel) {
57
+ try {
58
+ await handlerByChannel(message);
59
+ } catch (err) {
60
+ this.logger.error(`Failed to handle message from the channel ${channel}`, { err });
61
+ }
62
+ return;
63
+ }
64
+ this.logger.error(`Could not find a message handler for the channel ${channel}`);
65
+ });
66
+ }
67
+ async unsubscribe(channel) {
68
+ delete this.oneTimeHandlerByChannel[channel];
69
+ delete this.handlerByChannel[channel];
70
+ return await this.sub.unsubscribe(channel);
71
+ }
72
+ async publish(channel, data) {
73
+ return await this.pub.publish(channel, JSON.stringify(data));
74
+ }
75
+ async onChannelMessage(channel, handler) {
76
+ if (Object.keys(this.handlerByChannel).includes(channel)) throw new Error(`Handler already exists by the provided channel ${channel}`);
77
+ this.handlerByChannel[channel] = handler;
78
+ await this.sub.subscribe(channel);
79
+ }
80
+ async onceChannelMessage(channel, handler) {
81
+ if (Object.keys(this.oneTimeHandlerByChannel).includes(channel)) throw new Error(`Handler already exists by the provided channel ${channel}`);
82
+ this.oneTimeHandlerByChannel[channel] = handler;
83
+ await this.sub.subscribe(channel);
84
+ }
85
+ async quit() {
86
+ await Promise.all([this.pub.quit(), this.sub.quit()]);
87
+ }
88
+ getStatus() {
89
+ return {
90
+ pub: this.pub.status,
91
+ sub: this.sub.status
92
+ };
93
+ }
94
+ };
95
+ //#endregion
96
+ export { PubSubProvider };
@@ -0,0 +1,19 @@
1
+ import { RedisConfig } from "../interfaces/redis.js";
2
+ import { MessageHandler, PubSubStatusResult } from "../interfaces/pubsub.js";
3
+ import { HealthCheckResult, Logger, OnDestroy, OnHealthCheck } from "@diia-inhouse/types";
4
+
5
+ //#region src/services/pubsub.d.ts
6
+ declare class PubSubService implements OnHealthCheck, OnDestroy {
7
+ private readonly redisConfig;
8
+ private readonly logger;
9
+ private readonly provider;
10
+ constructor(redisConfig: RedisConfig, logger: Logger);
11
+ onHealthCheck(): Promise<HealthCheckResult<PubSubStatusResult>>;
12
+ onDestroy(): Promise<void>;
13
+ unsubscribe(channel: string): Promise<unknown>;
14
+ publish(channel: string, data: unknown): Promise<number>;
15
+ onceChannelMessage(channel: string, handler: MessageHandler): Promise<void>;
16
+ onChannelMessage(channel: string, handler: MessageHandler): Promise<void>;
17
+ }
18
+ //#endregion
19
+ export { PubSubService };