@diia-inhouse/redis 2.30.21 → 3.1.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/index.d.ts +10 -0
- package/dist/index.js +9 -20
- package/dist/interfaces/deps.d.ts +11 -0
- package/dist/interfaces/index.d.ts +4 -0
- package/dist/interfaces/index.js +3 -21
- package/dist/interfaces/mutex.d.ts +16 -0
- package/dist/interfaces/mutex.js +2 -6
- package/dist/interfaces/pubsub.d.ts +19 -0
- package/dist/interfaces/redis.d.ts +28 -0
- package/dist/interfaces/redis.js +12 -13
- package/dist/interfaces/store.d.ts +32 -0
- package/dist/services/index.d.ts +4 -0
- package/dist/services/index.js +5 -21
- package/dist/services/mutex.d.ts +19 -0
- package/dist/services/mutex.js +52 -44
- package/dist/services/providers/pubsub.js +96 -89
- package/dist/services/pubsub.d.ts +19 -0
- package/dist/services/pubsub.js +38 -43
- package/dist/services/redis.d.ts +10 -0
- package/dist/services/redis.js +84 -65
- package/dist/services/store.d.ts +47 -0
- package/dist/services/store.js +170 -183
- package/package.json +41 -32
- package/dist/index.js.map +0 -1
- package/dist/interfaces/deps.js +0 -3
- package/dist/interfaces/deps.js.map +0 -1
- package/dist/interfaces/index.js.map +0 -1
- package/dist/interfaces/mutex.js.map +0 -1
- package/dist/interfaces/pubsub.js +0 -3
- package/dist/interfaces/pubsub.js.map +0 -1
- package/dist/interfaces/redis.js.map +0 -1
- package/dist/interfaces/store.js +0 -3
- package/dist/interfaces/store.js.map +0 -1
- package/dist/services/index.js.map +0 -1
- package/dist/services/mutex.js.map +0 -1
- package/dist/services/providers/pubsub.js.map +0 -1
- package/dist/services/pubsub.js.map +0 -1
- package/dist/services/redis.js.map +0 -1
- package/dist/services/store.js.map +0 -1
- package/dist/types/index.d.ts +0 -3
- package/dist/types/interfaces/deps.d.ts +0 -6
- package/dist/types/interfaces/index.d.ts +0 -4
- package/dist/types/interfaces/mutex.d.ts +0 -13
- package/dist/types/interfaces/pubsub.d.ts +0 -15
- package/dist/types/interfaces/redis.d.ts +0 -24
- package/dist/types/interfaces/store.d.ts +0 -30
- package/dist/types/services/index.d.ts +0 -4
- package/dist/types/services/mutex.d.ts +0 -13
- package/dist/types/services/providers/pubsub.d.ts +0 -17
- package/dist/types/services/pubsub.d.ts +0 -15
- package/dist/types/services/redis.d.ts +0 -6
- package/dist/types/services/store.d.ts +0 -43
package/dist/services/pubsub.js
CHANGED
|
@@ -1,43 +1,38 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
return await this.provider.onChannelMessage(channel, handler);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
exports.PubSubService = PubSubService;
|
|
43
|
-
//# sourceMappingURL=pubsub.js.map
|
|
1
|
+
import "../interfaces/redis.js";
|
|
2
|
+
import { PubSubProvider } from "./providers/pubsub.js";
|
|
3
|
+
import { HttpStatusCode } from "@diia-inhouse/types";
|
|
4
|
+
//#region src/services/pubsub.ts
|
|
5
|
+
var PubSubService = class {
|
|
6
|
+
redisConfig;
|
|
7
|
+
logger;
|
|
8
|
+
provider;
|
|
9
|
+
constructor(redisConfig, logger) {
|
|
10
|
+
this.redisConfig = redisConfig;
|
|
11
|
+
this.logger = logger;
|
|
12
|
+
this.provider = new PubSubProvider(this.redisConfig, this.logger);
|
|
13
|
+
}
|
|
14
|
+
async onHealthCheck() {
|
|
15
|
+
const pubSubStatus = this.provider.getStatus();
|
|
16
|
+
return {
|
|
17
|
+
status: Object.values(pubSubStatus).some((s) => s !== "ready") ? HttpStatusCode.SERVICE_UNAVAILABLE : HttpStatusCode.OK,
|
|
18
|
+
details: { pubsub: pubSubStatus }
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
async onDestroy() {
|
|
22
|
+
await this.provider.quit();
|
|
23
|
+
}
|
|
24
|
+
async unsubscribe(channel) {
|
|
25
|
+
return await this.provider.unsubscribe(channel);
|
|
26
|
+
}
|
|
27
|
+
async publish(channel, data) {
|
|
28
|
+
return await this.provider.publish(channel, data);
|
|
29
|
+
}
|
|
30
|
+
onceChannelMessage(channel, handler) {
|
|
31
|
+
return this.provider.onceChannelMessage(channel, handler);
|
|
32
|
+
}
|
|
33
|
+
async onChannelMessage(channel, handler) {
|
|
34
|
+
return await this.provider.onChannelMessage(channel, handler);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
//#endregion
|
|
38
|
+
export { PubSubService };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { RedisOptions as RedisOptions$1 } from "../interfaces/redis.js";
|
|
2
|
+
import { Logger } from "@diia-inhouse/types";
|
|
3
|
+
import { Redis } from "ioredis";
|
|
4
|
+
|
|
5
|
+
//#region src/services/redis.d.ts
|
|
6
|
+
declare const RedisService: {
|
|
7
|
+
createClient(extendedRedisOptions: RedisOptions$1, logger: Logger): Redis;
|
|
8
|
+
};
|
|
9
|
+
//#endregion
|
|
10
|
+
export { RedisService };
|
package/dist/services/redis.js
CHANGED
|
@@ -1,65 +1,84 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
1
|
+
import { DurationMs } from "@diia-inhouse/types";
|
|
2
|
+
import { Redis } from "ioredis";
|
|
3
|
+
//#region src/services/redis.ts
|
|
4
|
+
const RedisService = { createClient(extendedRedisOptions, logger) {
|
|
5
|
+
const { maxRetryAttempts = 10, initialRetryDelay = DurationMs.Second, maxRetryDelay = DurationMs.Second * 10, ...options } = extendedRedisOptions;
|
|
6
|
+
const { host, port, redisMode } = options;
|
|
7
|
+
const client = new Redis({
|
|
8
|
+
keepAlive: DurationMs.Second * 10,
|
|
9
|
+
enableAutoPipelining: true,
|
|
10
|
+
reconnectOnError: (err) => {
|
|
11
|
+
logger.error("Redis error detected due:", {
|
|
12
|
+
err,
|
|
13
|
+
host,
|
|
14
|
+
port,
|
|
15
|
+
redisMode
|
|
16
|
+
});
|
|
17
|
+
if (err.message.includes("READONLY")) {
|
|
18
|
+
logger.warn("Redis encountered READONLY error, forcing reconnect", {
|
|
19
|
+
host,
|
|
20
|
+
port,
|
|
21
|
+
redisMode
|
|
22
|
+
});
|
|
23
|
+
return 2;
|
|
24
|
+
}
|
|
25
|
+
return false;
|
|
26
|
+
},
|
|
27
|
+
retryStrategy: (attempts) => {
|
|
28
|
+
if (attempts > maxRetryAttempts) {
|
|
29
|
+
logger.error(`Redis connection failed after ${maxRetryAttempts} attempts. Shutting down connection attempts.`, {
|
|
30
|
+
host,
|
|
31
|
+
port,
|
|
32
|
+
redisMode
|
|
33
|
+
});
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
const delay = Math.min(initialRetryDelay * Math.pow(2, attempts - 1), maxRetryDelay);
|
|
37
|
+
logger.debug(`Redis connection attempt ${attempts} failed. Retrying in ${delay}ms...`, {
|
|
38
|
+
host,
|
|
39
|
+
port,
|
|
40
|
+
redisMode
|
|
41
|
+
});
|
|
42
|
+
return delay;
|
|
43
|
+
},
|
|
44
|
+
...options
|
|
45
|
+
});
|
|
46
|
+
client.on("ready", () => {
|
|
47
|
+
logger.debug("Redis client is ready to accept commands", {
|
|
48
|
+
host,
|
|
49
|
+
port,
|
|
50
|
+
redisMode
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
client.on("close", () => {
|
|
54
|
+
logger.debug("Redis connection closed", {
|
|
55
|
+
host,
|
|
56
|
+
port,
|
|
57
|
+
redisMode
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
client.on("reconnecting", (timeToReconnect) => {
|
|
61
|
+
logger.debug(`Redis client is reconnecting in ${timeToReconnect}ms`, {
|
|
62
|
+
host,
|
|
63
|
+
port,
|
|
64
|
+
redisMode
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
client.on("end", () => {
|
|
68
|
+
logger.debug("Redis connection ended, no more reconnection attempts will be made", {
|
|
69
|
+
host,
|
|
70
|
+
port,
|
|
71
|
+
redisMode
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
client.on("wait", () => {
|
|
75
|
+
logger.debug("Redis client is waiting to reconnect", {
|
|
76
|
+
host,
|
|
77
|
+
port,
|
|
78
|
+
redisMode
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
return client;
|
|
82
|
+
} };
|
|
83
|
+
//#endregion
|
|
84
|
+
export { RedisService };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { RedisConfig } from "../interfaces/redis.js";
|
|
2
|
+
import { SetValueOptions, StoreStatusResult, ThrottleResult } from "../interfaces/store.js";
|
|
3
|
+
import { HealthCheckResult, Logger, OnDestroy, OnHealthCheck } from "@diia-inhouse/types";
|
|
4
|
+
|
|
5
|
+
//#region src/services/store.d.ts
|
|
6
|
+
declare class StoreService implements OnHealthCheck, OnDestroy {
|
|
7
|
+
private readonly storeConfig;
|
|
8
|
+
private readonly logger;
|
|
9
|
+
private clientRW;
|
|
10
|
+
private clientRO;
|
|
11
|
+
private tagsKey;
|
|
12
|
+
constructor(storeConfig: RedisConfig, logger: Logger);
|
|
13
|
+
onHealthCheck(): Promise<HealthCheckResult<StoreStatusResult>>;
|
|
14
|
+
onDestroy(): Promise<void>;
|
|
15
|
+
get(key: string): Promise<string | null>;
|
|
16
|
+
mget(...keys: string[]): Promise<(string | null)[]>;
|
|
17
|
+
hget(key: string, field: string): Promise<string | null>;
|
|
18
|
+
hlen(key: string): Promise<number | null>;
|
|
19
|
+
hgetall(key: string): Promise<Record<string, string> | null>;
|
|
20
|
+
hvals(key: string): Promise<string[]>;
|
|
21
|
+
hscan(key: string, cursor: number | string, count: number): Promise<{
|
|
22
|
+
cursor: string;
|
|
23
|
+
elements: string[];
|
|
24
|
+
}>;
|
|
25
|
+
scan(matchPattern: string, cursor: number | string, count: number): Promise<{
|
|
26
|
+
cursor: string;
|
|
27
|
+
elements: string[];
|
|
28
|
+
}>;
|
|
29
|
+
lrange(key: string, start: number, stop: number): Promise<string[] | null>;
|
|
30
|
+
getUsingTags(key: string): Promise<string | null>;
|
|
31
|
+
set(key: string, value: string, options?: SetValueOptions): Promise<"OK" | null>;
|
|
32
|
+
hset(key: string, value: Record<string, string>): Promise<number>;
|
|
33
|
+
lpush(key: string, ...values: string[]): Promise<number>;
|
|
34
|
+
incrby(key: string, value: number): Promise<number>;
|
|
35
|
+
keys(pattern: string): Promise<string[]>;
|
|
36
|
+
remember(key: string, closure: () => Promise<string | null>, options?: SetValueOptions): Promise<string | null>;
|
|
37
|
+
remove(...keys: string[]): Promise<number>;
|
|
38
|
+
hdel(key: string, ...fields: string[]): Promise<number>;
|
|
39
|
+
expire(key: string, seconds: number): Promise<number>;
|
|
40
|
+
bumpTags(tags: string[]): Promise<"OK" | null>;
|
|
41
|
+
throttle(key: string, maxBurst: number, rate: number, periodSec: number, quantity?: number): Promise<ThrottleResult>;
|
|
42
|
+
flushDb(): Promise<"OK">;
|
|
43
|
+
private validate;
|
|
44
|
+
private wrapValueWithMetadata;
|
|
45
|
+
}
|
|
46
|
+
//#endregion
|
|
47
|
+
export { StoreService };
|