@samet-it/be-redis-common 1.1.9 → 1.1.10
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.
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { RedisConnectionLike
|
|
2
|
-
import type { CacheChannelProps, CacheChannelLike, CacheChannelOpt } from "@samet-it/be-cache-common";
|
|
1
|
+
import type { RedisConnectionLike } from "../connection";
|
|
2
|
+
import type { CacheChannelProps, CacheChannelLike, CacheChannelOpt, CacheExecOpt } from "@samet-it/be-cache-common";
|
|
3
3
|
import type { Entity } from "@samet-it/be-base-common";
|
|
4
4
|
import type { RedisClientType } from "redis";
|
|
5
5
|
import type { KeyValue } from "@leyyo/common";
|
|
@@ -39,3 +39,7 @@ export interface RedisDirectChannelOpt extends RedisChannelOpt {
|
|
|
39
39
|
* */
|
|
40
40
|
name?: string;
|
|
41
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Redis query option
|
|
44
|
+
* */
|
|
45
|
+
export type RedisExecOpt = CacheExecOpt;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { RedisConnectionLike
|
|
2
|
-
import type { RedisChannelProps, RedisChannelLike, RedisChannelOpt } from "./index.types";
|
|
1
|
+
import type { RedisConnectionLike } from "../connection";
|
|
2
|
+
import type { RedisChannelProps, RedisChannelLike, RedisChannelOpt, RedisExecOpt } from "./index.types";
|
|
3
3
|
import { type Entity } from "@samet-it/be-base-common";
|
|
4
4
|
import { CacheChannel } from "@samet-it/be-cache-common";
|
|
5
5
|
import type { KeyValue } from "@leyyo/common";
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import type { CacheConnectionLike, CacheConnOpt
|
|
1
|
+
import type { CacheConnectionLike, CacheConnOpt } from "@samet-it/be-cache-common";
|
|
2
2
|
import type { RedisClientType } from "redis";
|
|
3
3
|
import type { Entity } from "@samet-it/be-base-common";
|
|
4
4
|
import type { RedisDirectChannelOpt, RedisChannelLike } from "../channel";
|
|
5
5
|
import type { CacheConnProps } from "@samet-it/be-cache-common";
|
|
6
|
-
import { KeyValue } from "@leyyo/common";
|
|
6
|
+
import type { KeyValue } from "@leyyo/common";
|
|
7
7
|
/**
|
|
8
8
|
* Redis connection interface
|
|
9
9
|
* */
|
|
10
|
-
export interface RedisConnectionLike extends CacheConnectionLike
|
|
10
|
+
export interface RedisConnectionLike extends CacheConnectionLike {
|
|
11
11
|
/** @inheritDoc */
|
|
12
12
|
get props(): Readonly<RedisConnProps>;
|
|
13
13
|
/**
|
|
@@ -63,12 +63,6 @@ export interface RedisConnProps extends CacheConnProps, RedisConnOpt {
|
|
|
63
63
|
* @type {RedisClientType}
|
|
64
64
|
* */
|
|
65
65
|
client: RedisClientType;
|
|
66
|
-
/**
|
|
67
|
-
* Connection try count
|
|
68
|
-
*
|
|
69
|
-
* @type {number}
|
|
70
|
-
* */
|
|
71
|
-
tryCount: number;
|
|
72
66
|
/**
|
|
73
67
|
* Connection url
|
|
74
68
|
*
|
|
@@ -76,7 +70,3 @@ export interface RedisConnProps extends CacheConnProps, RedisConnOpt {
|
|
|
76
70
|
* */
|
|
77
71
|
producedUrl: string;
|
|
78
72
|
}
|
|
79
|
-
/**
|
|
80
|
-
* Redis query option
|
|
81
|
-
* */
|
|
82
|
-
export type RedisExecOpt = CacheExecOpt;
|
|
@@ -1,28 +1,46 @@
|
|
|
1
|
-
import type { RedisConnectionLike,
|
|
1
|
+
import type { RedisConnectionLike, RedisConnProps, RedisConnOpt } from "./index.types";
|
|
2
2
|
import { CacheConnection } from "@samet-it/be-cache-common";
|
|
3
3
|
import type { RedisClientType } from "redis";
|
|
4
4
|
/**
|
|
5
5
|
* Redis connection abstract class
|
|
6
6
|
* */
|
|
7
|
-
export declare abstract class RedisConnection extends CacheConnection
|
|
7
|
+
export declare abstract class RedisConnection extends CacheConnection implements RedisConnectionLike {
|
|
8
8
|
/**
|
|
9
|
-
* Base/starting/min delay
|
|
9
|
+
* Base/starting/min delay for connection
|
|
10
10
|
*
|
|
11
11
|
* @type {number} - as seconds
|
|
12
12
|
* */
|
|
13
|
-
private static readonly
|
|
13
|
+
private static readonly CONN_BASE_DELAY;
|
|
14
14
|
/**
|
|
15
|
-
* Last/max delay
|
|
15
|
+
* Last/max delay for connection
|
|
16
16
|
*
|
|
17
17
|
* @type {number} - as seconds
|
|
18
18
|
* */
|
|
19
|
-
private static readonly
|
|
19
|
+
private static readonly CONN_MAX_DELAY;
|
|
20
20
|
/**
|
|
21
21
|
* Try count
|
|
22
22
|
*
|
|
23
23
|
* @type {number} - times
|
|
24
24
|
* */
|
|
25
|
-
private static readonly
|
|
25
|
+
private static readonly CONN_TRY_COUNT;
|
|
26
|
+
/**
|
|
27
|
+
* Base/starting/min delay for ping
|
|
28
|
+
*
|
|
29
|
+
* @type {number} - as seconds
|
|
30
|
+
* */
|
|
31
|
+
private static readonly PING_BASE_DELAY;
|
|
32
|
+
/**
|
|
33
|
+
* Last/max delay ping
|
|
34
|
+
*
|
|
35
|
+
* @type {number} - as seconds
|
|
36
|
+
* */
|
|
37
|
+
private static readonly PING_MAX_DELAY;
|
|
38
|
+
/**
|
|
39
|
+
* Try count
|
|
40
|
+
*
|
|
41
|
+
* @type {number} - times
|
|
42
|
+
* */
|
|
43
|
+
private static readonly PING_TRY_COUNT;
|
|
26
44
|
/** {@inheritDoc} */
|
|
27
45
|
protected _props: RedisConnProps;
|
|
28
46
|
/**
|
|
@@ -43,12 +61,8 @@ export declare abstract class RedisConnection extends CacheConnection<RedisExecO
|
|
|
43
61
|
* Build url from credentials
|
|
44
62
|
* */
|
|
45
63
|
protected _buildUrl(): void;
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
*
|
|
49
|
-
* @return {number}
|
|
50
|
-
* */
|
|
51
|
-
protected _delayWithJitter(): number;
|
|
64
|
+
protected get _connectionDelay(): number;
|
|
65
|
+
protected get _pingDelay(): number;
|
|
52
66
|
/** {@inheritDoc} */
|
|
53
67
|
connect(): Promise<boolean>;
|
|
54
68
|
/** {@inheritDoc} */
|
|
@@ -62,7 +62,6 @@ class RedisConnection extends be_cache_common_1.CacheConnection {
|
|
|
62
62
|
if (!this.logger) {
|
|
63
63
|
this.logger = be_base_common_1.logger.create(this);
|
|
64
64
|
}
|
|
65
|
-
this._props.tryCount = 0;
|
|
66
65
|
this._readFromEnv();
|
|
67
66
|
this._buildUrl();
|
|
68
67
|
}
|
|
@@ -118,14 +117,11 @@ class RedisConnection extends be_cache_common_1.CacheConnection {
|
|
|
118
117
|
}
|
|
119
118
|
this._props.producedUrl = `${protocol}://${_secure}${host}${_port}${_db}`;
|
|
120
119
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
_delayWithJitter() {
|
|
127
|
-
const exp = Math.min(RedisConnection.BASE_DELAY * Math.pow(2, this._props.tryCount), RedisConnection.MAX_DELAY);
|
|
128
|
-
return exp / 2 + Math.random() * (exp / 2);
|
|
120
|
+
get _connectionDelay() {
|
|
121
|
+
return this._delayWithJitter(this._props.connectTryCount, RedisConnection.CONN_BASE_DELAY, RedisConnection.CONN_MAX_DELAY);
|
|
122
|
+
}
|
|
123
|
+
get _pingDelay() {
|
|
124
|
+
return this._delayWithJitter(this._props.pingTryCount, RedisConnection.PING_BASE_DELAY, RedisConnection.PING_MAX_DELAY);
|
|
129
125
|
}
|
|
130
126
|
// endregion protected-method
|
|
131
127
|
// region connect
|
|
@@ -139,33 +135,38 @@ class RedisConnection extends be_cache_common_1.CacheConnection {
|
|
|
139
135
|
if (this.isConnected) {
|
|
140
136
|
return true;
|
|
141
137
|
}
|
|
142
|
-
if (this._props.
|
|
143
|
-
const err = new be_cache_common_1.CacheError('Maximum try county', { tryCount: this._props.
|
|
144
|
-
this.logger.error(be_base_common_1.errorHandler.common.logText(err, 'connect'
|
|
138
|
+
if (this._props.connectTryCount > RedisConnection.CONN_TRY_COUNT) {
|
|
139
|
+
const err = new be_cache_common_1.CacheError('Maximum try county', { tryCount: this._props.connectTryCount });
|
|
140
|
+
this.logger.error(be_base_common_1.errorHandler.common.logText(err, 'connect'));
|
|
145
141
|
return false;
|
|
146
142
|
}
|
|
147
143
|
try {
|
|
148
144
|
props.client = redis.createClient({ url: this._props.producedUrl });
|
|
149
145
|
props.client
|
|
150
146
|
.on("error", err => {
|
|
151
|
-
this.
|
|
152
|
-
props.
|
|
147
|
+
this.logger.warn(be_base_common_1.errorHandler.common.logText(err, 'connection', this._props.connectTryCount));
|
|
148
|
+
props.connectTryCount++;
|
|
153
149
|
const old = this.isConnected;
|
|
154
150
|
props.isConnected = false;
|
|
155
151
|
if (old) {
|
|
156
152
|
this._triggerOnCase('disconnected', this._onDisconnected, false);
|
|
157
153
|
}
|
|
158
|
-
setTimeout(() => this.connect().then(), this.
|
|
154
|
+
setTimeout(() => this.connect().then(), this._connectionDelay);
|
|
159
155
|
})
|
|
160
156
|
.on('connect', () => {
|
|
161
157
|
this.logger.info(`on[connect]`);
|
|
162
158
|
props.isConnected = true;
|
|
163
|
-
props.
|
|
159
|
+
props.connectTryCount = 0;
|
|
164
160
|
this._triggerOnCase('connected', this._onConnected, false);
|
|
165
161
|
if (props.isFirst === undefined) {
|
|
166
162
|
this._triggerOnCase('first-connected', this._onFirstConnected, true);
|
|
167
163
|
props.isFirst = false;
|
|
168
164
|
}
|
|
165
|
+
// clear stopped ping
|
|
166
|
+
if (this._props.pingTryCount > RedisConnection.PING_TRY_COUNT) {
|
|
167
|
+
this._props.pingTryCount = 0;
|
|
168
|
+
setTimeout(() => this.ping(true).then(), 30000);
|
|
169
|
+
}
|
|
169
170
|
})
|
|
170
171
|
.on('ready', () => this.logger.info('on[ready]'))
|
|
171
172
|
.on('close', () => this.logger.info('on[close]'))
|
|
@@ -176,7 +177,7 @@ class RedisConnection extends be_cache_common_1.CacheConnection {
|
|
|
176
177
|
setTimeout(() => this.ping(true).then(), 30000);
|
|
177
178
|
}
|
|
178
179
|
catch (e) {
|
|
179
|
-
this.
|
|
180
|
+
this.logger.warn(be_base_common_1.errorHandler.common.logText(e, 'connection', this._props.connectTryCount));
|
|
180
181
|
}
|
|
181
182
|
return true;
|
|
182
183
|
});
|
|
@@ -187,14 +188,23 @@ class RedisConnection extends be_cache_common_1.CacheConnection {
|
|
|
187
188
|
if (!this.isEnabled) {
|
|
188
189
|
return false;
|
|
189
190
|
}
|
|
191
|
+
if (this._props.pingTryCount > RedisConnection.PING_TRY_COUNT) {
|
|
192
|
+
const err = new be_cache_common_1.CacheError('Maximum try county', { tryCount: this._props.pingTryCount });
|
|
193
|
+
this.logger.error(be_base_common_1.errorHandler.common.logText(err, 'connect'));
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
190
196
|
let result = false;
|
|
191
197
|
if (this.isConnected) {
|
|
192
198
|
try {
|
|
193
199
|
yield this.client.ping();
|
|
200
|
+
this._props.pingTryCount = 0;
|
|
194
201
|
result = true;
|
|
195
202
|
}
|
|
196
203
|
catch (err) {
|
|
197
|
-
this.
|
|
204
|
+
this._props.pingTryCount++;
|
|
205
|
+
this.logger.warn(be_base_common_1.errorHandler.common.logText(err, 'ping', this._props.pingTryCount));
|
|
206
|
+
setTimeout(() => this.ping(true).then(), this._pingDelay);
|
|
207
|
+
next = false;
|
|
198
208
|
}
|
|
199
209
|
}
|
|
200
210
|
if (next) {
|
|
@@ -207,20 +217,38 @@ class RedisConnection extends be_cache_common_1.CacheConnection {
|
|
|
207
217
|
exports.RedisConnection = RedisConnection;
|
|
208
218
|
// region private-property
|
|
209
219
|
/**
|
|
210
|
-
* Base/starting/min delay
|
|
220
|
+
* Base/starting/min delay for connection
|
|
221
|
+
*
|
|
222
|
+
* @type {number} - as seconds
|
|
223
|
+
* */
|
|
224
|
+
RedisConnection.CONN_BASE_DELAY = 500; // 0.5 sec
|
|
225
|
+
/**
|
|
226
|
+
* Last/max delay for connection
|
|
227
|
+
*
|
|
228
|
+
* @type {number} - as seconds
|
|
229
|
+
* */
|
|
230
|
+
RedisConnection.CONN_MAX_DELAY = 1000 * 60 * 60; // 60 minutes
|
|
231
|
+
/**
|
|
232
|
+
* Try count
|
|
233
|
+
*
|
|
234
|
+
* @type {number} - times
|
|
235
|
+
* */
|
|
236
|
+
RedisConnection.CONN_TRY_COUNT = 100; // 100 times
|
|
237
|
+
/**
|
|
238
|
+
* Base/starting/min delay for ping
|
|
211
239
|
*
|
|
212
240
|
* @type {number} - as seconds
|
|
213
241
|
* */
|
|
214
|
-
RedisConnection.
|
|
242
|
+
RedisConnection.PING_BASE_DELAY = 200; // 0.2 sec
|
|
215
243
|
/**
|
|
216
|
-
* Last/max delay
|
|
244
|
+
* Last/max delay ping
|
|
217
245
|
*
|
|
218
246
|
* @type {number} - as seconds
|
|
219
247
|
* */
|
|
220
|
-
RedisConnection.
|
|
248
|
+
RedisConnection.PING_MAX_DELAY = 1000 * 60 * 10; // 10 minutes
|
|
221
249
|
/**
|
|
222
250
|
* Try count
|
|
223
251
|
*
|
|
224
252
|
* @type {number} - times
|
|
225
253
|
* */
|
|
226
|
-
RedisConnection.
|
|
254
|
+
RedisConnection.PING_TRY_COUNT = 100; // 100 times
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@samet-it/be-redis-common",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.10",
|
|
4
4
|
"description": "Redis common component",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"redis",
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
"@babel/preset-env": "^7.28.0",
|
|
42
42
|
"@babel/preset-typescript": "^7.27.1",
|
|
43
43
|
"@eslint/js": "^9.33.0",
|
|
44
|
+
"@types/express": "^5.0.6",
|
|
44
45
|
"@types/jest": "^30.0.0",
|
|
45
46
|
"@types/node": "^24.2.1",
|
|
46
47
|
"@typescript-eslint/eslint-plugin": "^8.39.1",
|
|
@@ -70,7 +71,7 @@
|
|
|
70
71
|
"@leyyo/common": "^1.2.4",
|
|
71
72
|
"@leyyo/env": "^1.2.5",
|
|
72
73
|
"@samet-it/be-base-common": "^1.1.5",
|
|
73
|
-
"@samet-it/be-cache-common": "^1.1.
|
|
74
|
+
"@samet-it/be-cache-common": "^1.1.10",
|
|
74
75
|
"redis": "^5.10.0"
|
|
75
76
|
}
|
|
76
77
|
}
|