@digitalwalletcorp/redis-pooling 1.1.1 → 1.3.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/README.md CHANGED
@@ -124,6 +124,7 @@ Creates a Redis connection pool.
124
124
  | `max` | number | 10 | Maximum number of clients in the pool. |
125
125
  | `min` | number | 0 | Minimum number of clients in the pool. |
126
126
  | `connectTimeout` | number | 5000 | Connection timeout in milliseconds. |
127
+ | `acquireTimeout` | number | 10000 | Timeout in milliseconds to acquire a client from the pool. |
127
128
  | `testOnBorrow` | boolean | true | Enable connection validate on borrow. |
128
129
  | `enableTls` | boolean | false | Enable TLS for Redis connection. |
129
130
 
@@ -149,6 +150,9 @@ Extends the standard `ioredis` `Redis` client with additional helpers:
149
150
  This library provides a Redis connection pool capable of managing Redis clients
150
151
  connected to different database indexes (`SELECT db`).
151
152
 
153
+ All database indexes share a single pool, so `max` is the upper limit of connections to the Redis server.
154
+ The database index is selected every time a client is acquired.
155
+
152
156
  **Calling `acquire(dbIndex)`:**
153
157
 
154
158
  > When `dbIndex` is specified, the acquired client will be connected to the specified database index.
@@ -3,30 +3,32 @@ export interface RedisConfig {
3
3
  url: string;
4
4
  dbIndex?: number;
5
5
  connectTimeout?: number;
6
+ acquireTimeout?: number;
6
7
  max?: number;
7
8
  min?: number;
8
9
  testOnBorrow?: boolean;
9
10
  enableTls?: boolean;
10
11
  }
12
+ export interface RedisPoolOptions {
13
+ debug?: boolean;
14
+ }
11
15
  export interface RedisClient extends Redis {
12
- getKeys(pattern: string): Promise<string[]>;
13
- deleteKeys(pattern: string): Promise<PromiseSettledResult<number>[]>;
14
- _originalDbIndex?: number;
16
+ getKeys(pattern: string, count?: number): Promise<string[]>;
17
+ deleteKeys(pattern: string, count?: number): Promise<PromiseSettledResult<number>[]>;
15
18
  }
16
19
  export declare class RedisPool {
17
20
  private readonly url;
18
21
  private readonly db;
19
22
  private readonly connectTimeout;
23
+ private readonly acquireTimeout;
20
24
  private readonly max;
21
25
  private readonly min;
22
26
  private readonly testOnBorrow;
23
27
  private readonly tls?;
24
- private readonly poolMap;
28
+ private pool?;
25
29
  private initialized;
26
30
  private readonly debug;
27
- constructor(config: RedisConfig, options?: {
28
- debug?: boolean;
29
- });
31
+ constructor(config: RedisConfig, options?: RedisPoolOptions);
30
32
  acquire(dbIndex?: number): Promise<RedisClient>;
31
33
  release(client?: RedisClient): Promise<void>;
32
34
  destroy(timeoutMs?: number): Promise<void>;
@@ -36,8 +38,14 @@ export declare class RedisPool {
36
38
  * @param {number} dbIndex
37
39
  */
38
40
  private checkConnectivity;
41
+ /**
42
+ * Redisクライアントの接続が完了するまで待つ。接続に失敗した場合は、そのエラーで reject する
43
+ *
44
+ * @param {Redis} client
45
+ */
46
+ private waitForReady;
39
47
  private ping;
40
- debugLog(...args: any[]): void;
48
+ private debugLog;
41
49
  private getPool;
42
- private createSingleDbPool;
50
+ private createPool;
43
51
  }
@@ -38,6 +38,7 @@ const ioredis_1 = require("ioredis");
38
38
  const genericPool = __importStar(require("generic-pool"));
39
39
  const logHeader = '[RedisPooling]';
40
40
  const DEFAULT_CONNECT_TIMEOUT = 5000;
41
+ const DEFAULT_ACQUIRE_TIMEOUT = 10000;
41
42
  const DEFAULT_MAX_POOLING_SIZE = 10;
42
43
  const DEFAULT_MIN_POOLING_SIZE = 0;
43
44
  const REDIS_PING_TIMEOUT_MS = 3000; // 3秒
@@ -45,11 +46,12 @@ class RedisPool {
45
46
  url;
46
47
  db;
47
48
  connectTimeout;
49
+ acquireTimeout;
48
50
  max;
49
51
  min;
50
52
  testOnBorrow;
51
53
  tls;
52
- poolMap = new Map();
54
+ pool;
53
55
  initialized = false;
54
56
  debug;
55
57
  constructor(config, options) {
@@ -59,6 +61,7 @@ class RedisPool {
59
61
  this.url = config.url;
60
62
  this.db = config.dbIndex ?? 0;
61
63
  this.connectTimeout = config.connectTimeout ?? DEFAULT_CONNECT_TIMEOUT;
64
+ this.acquireTimeout = config.acquireTimeout ?? DEFAULT_ACQUIRE_TIMEOUT;
62
65
  this.max = config.max ?? DEFAULT_MAX_POOLING_SIZE;
63
66
  this.min = config.min ?? DEFAULT_MIN_POOLING_SIZE;
64
67
  this.testOnBorrow = config.testOnBorrow ?? true;
@@ -74,69 +77,56 @@ class RedisPool {
74
77
  this.initialized = true;
75
78
  }
76
79
  const index = dbIndex ?? this.db;
77
- const pool = this.getPool(index);
80
+ const pool = this.getPool();
81
+ const client = await pool.acquire();
78
82
  try {
79
- const client = await pool.acquire();
80
- this.debugLog(logHeader, `Redis client ${index} has been acquired.`);
81
- return client;
83
+ // プールの接続は、前の利用者が選択したDBを保持したまま返却される。そのため貸し出すたびに対象のDBを選択する
84
+ await client.select(index);
82
85
  }
83
86
  catch (error) {
87
+ await pool.destroy(client);
84
88
  throw error;
85
89
  }
90
+ this.debugLog(logHeader, `Redis client ${index} has been acquired.`);
91
+ return client;
86
92
  }
87
93
  async release(client) {
88
- if (client) {
89
- const dbIndex = client._originalDbIndex ?? this.db;
90
- const pool = this.poolMap.get(dbIndex);
91
- if (!pool) {
92
- return;
93
- }
94
- let needDestroy = false;
95
- switch (true) {
96
- case client.status === 'end':
97
- case client.status === 'close':
98
- // Redisクライアントの状態が再利用できない場合はプールから破棄
99
- needDestroy = true;
100
- break;
101
- case client.status === 'ready':
102
- try {
103
- // 元のDBインデックスに戻す
104
- await client.select(dbIndex);
105
- }
106
- catch (error) {
107
- // selectに失敗する→Redisクライアントが不正な状態にあると判断できるのでプールから破棄
108
- needDestroy = true;
109
- }
110
- break;
111
- default:
112
- }
113
- if (needDestroy) {
114
- // Redisクライアントの破棄
115
- await pool.destroy(client);
116
- this.debugLog(logHeader, `Redis client ${dbIndex} destroyed due to invalid status.`);
117
- }
118
- else {
119
- // Redisクライアントの返却
120
- await pool.release(client);
121
- this.debugLog(logHeader, `Redis client ${dbIndex} released.`);
122
- }
94
+ if (!client || !this.pool) {
95
+ return;
96
+ }
97
+ if (client.status === 'end' || client.status === 'close') {
98
+ // 再利用できない状態のRedisクライアントはプールから破棄する
99
+ await this.pool.destroy(client);
100
+ this.debugLog(logHeader, 'Redis client destroyed due to invalid status.');
101
+ }
102
+ else {
103
+ await this.pool.release(client);
104
+ this.debugLog(logHeader, 'Redis client released.');
123
105
  }
124
106
  }
125
107
  async destroy(timeoutMs = 5000) {
126
- for (const [dbIndex, pool] of this.poolMap.entries()) {
127
- this.debugLog(logHeader, `Destroying Redis pool for DB index ${dbIndex}...`);
108
+ const pool = this.pool;
109
+ if (!pool) {
110
+ return;
111
+ }
112
+ this.debugLog(logHeader, 'Destroying Redis pool...');
113
+ let timer;
114
+ try {
128
115
  await Promise.race([
129
116
  (async () => {
130
117
  await pool.drain();
131
118
  await pool.clear();
132
119
  })(),
133
120
  new Promise((_, reject) => {
134
- setTimeout(() => reject(new Error(`${logHeader} Timeout while draining Redis pool for DB index ${dbIndex}`)), timeoutMs);
121
+ timer = setTimeout(() => reject(new Error(`${logHeader} Timeout while draining Redis pool`)), timeoutMs);
135
122
  })
136
123
  ]);
137
- this.debugLog(logHeader, `Redis pool for DB index ${dbIndex} destroyed.`);
138
- this.poolMap.delete(dbIndex);
139
124
  }
125
+ finally {
126
+ clearTimeout(timer);
127
+ }
128
+ this.debugLog(logHeader, 'Redis pool destroyed.');
129
+ this.pool = undefined;
140
130
  }
141
131
  /**
142
132
  * 初めてacquireが呼ばれた時に、指定された接続情報で接続できるかチェックする
@@ -151,18 +141,37 @@ class RedisPool {
151
141
  connectTimeout: this.connectTimeout,
152
142
  tls: this.tls,
153
143
  });
144
+ try {
145
+ await this.waitForReady(client);
146
+ }
147
+ finally {
148
+ client.quit().catch(() => client.disconnect());
149
+ }
150
+ }
151
+ /**
152
+ * Redisクライアントの接続が完了するまで待つ。接続に失敗した場合は、そのエラーで reject する
153
+ *
154
+ * @param {Redis} client
155
+ */
156
+ async waitForReady(client) {
157
+ if (client.status === 'ready') {
158
+ return;
159
+ }
154
160
  return new Promise((resolve, reject) => {
155
- const cleanup = () => {
156
- client.quit().catch(() => client.disconnect());
157
- };
158
- client.once('ready', () => {
161
+ const onReady = () => {
159
162
  cleanup();
160
163
  resolve();
161
- });
162
- client.once('error', (error) => {
164
+ };
165
+ const onError = (error) => {
163
166
  cleanup();
164
167
  reject(error);
165
- });
168
+ };
169
+ const cleanup = () => {
170
+ client.off('ready', onReady);
171
+ client.off('error', onError);
172
+ };
173
+ client.once('ready', onReady);
174
+ client.once('error', onError);
166
175
  });
167
176
  }
168
177
  async ping(client) {
@@ -188,19 +197,17 @@ class RedisPool {
188
197
  console.debug(...args);
189
198
  }
190
199
  }
191
- getPool(dbIndex) {
192
- let pool = this.poolMap.get(dbIndex);
193
- if (!pool) {
194
- pool = this.createSingleDbPool(dbIndex);
195
- this.poolMap.set(dbIndex, pool);
200
+ getPool() {
201
+ if (!this.pool) {
202
+ this.pool = this.createPool();
196
203
  }
197
- return pool;
204
+ return this.pool;
198
205
  }
199
- createSingleDbPool(dbIndex) {
206
+ createPool() {
200
207
  const factory = {
201
208
  create: async () => {
202
209
  const client = new ioredis_1.Redis(this.url, {
203
- db: dbIndex,
210
+ db: this.db,
204
211
  connectTimeout: this.connectTimeout,
205
212
  keepAlive: 1,
206
213
  enableOfflineQueue: true,
@@ -214,27 +221,26 @@ class RedisPool {
214
221
  },
215
222
  reconnectOnError: (error) => {
216
223
  process.emitWarning(`${logHeader} detected error (on reconnectOnError). ${error.message}`);
217
- return true;
224
+ // フェイルオーバー後にレプリカへ接続したままになっている場合だけ、再接続で解消できる
225
+ return error.message.startsWith('READONLY');
218
226
  }
219
227
  });
220
- client._originalDbIndex = dbIndex;
221
228
  client.on('error', error => {
222
229
  process.emitWarning(`${logHeader} detected error (on error). ${error.message}`);
223
230
  });
224
- // カスタムメソッド内の処理でthis.debugLogなどが参照できなくなるため、poolのインスタンスを変数キャプチャする
225
- const poolInstance = this;
226
231
  // カスタムメソッド START
227
232
  /**
228
233
  * 指定されたパターンに一致するキーを Redis から全て取得する
229
234
  *
230
235
  * @param {string} pattern
236
+ * @param {number} [count] 1度にスキャンする件数 デフォルト:1000
231
237
  * @returns {Promise<string[]>}
232
238
  */
233
- client.getKeys = async function (pattern) {
239
+ client.getKeys = async function (pattern, count) {
234
240
  const allKeys = [];
235
241
  const stream = this.scanStream({
236
242
  match: pattern,
237
- count: 1000 // ioredisが1度にスキャンする件数の目安。1000件を超えるデータがあっても全件返却される
243
+ count: count ?? 1000
238
244
  });
239
245
  return new Promise((resolve, reject) => {
240
246
  stream.on('data', (keys) => {
@@ -242,8 +248,8 @@ class RedisPool {
242
248
  allKeys.push(...keys);
243
249
  }
244
250
  });
245
- stream.on('end', () => resolve(allKeys));
246
- stream.on('error', (err) => {
251
+ stream.once('end', () => resolve(allKeys));
252
+ stream.once('error', (err) => {
247
253
  reject(err);
248
254
  });
249
255
  });
@@ -264,52 +270,55 @@ class RedisPool {
264
270
  * .reduce((acc, cur) => acc + (cur as PromiseFulfilledResult<number>).value, 0);
265
271
  *
266
272
  * @param {string} pattern
273
+ * @param {number} [count] 1度にスキャンする件数 デフォルト:1000
267
274
  * @returns {Promise<PromiseSettledResult<number>>}
268
275
  */
269
- client.deleteKeys = async function (pattern) {
276
+ client.deleteKeys = async function (pattern, count) {
270
277
  const stream = this.scanStream({
271
278
  match: pattern,
272
- count: 1000 // 1度にスキャンする件数
279
+ count: count ?? 1000
273
280
  });
281
+ const results = [];
274
282
  return new Promise((resolve, reject) => {
275
- const tasks = [];
276
283
  stream.on('data', async (keys) => {
277
284
  if (keys.length) {
278
- tasks.push((async () => {
285
+ stream.pause();
286
+ try {
279
287
  // UNLINK を使用し、現在のインスタンス (this) で実行
280
288
  const unlinkResult = await this.unlink(...keys);
281
- return unlinkResult;
282
- })());
289
+ results.push({
290
+ status: 'fulfilled',
291
+ value: unlinkResult
292
+ });
293
+ }
294
+ catch (err) {
295
+ results.push({
296
+ status: 'rejected',
297
+ reason: err
298
+ });
299
+ }
300
+ finally {
301
+ stream.resume();
302
+ }
283
303
  }
284
304
  });
285
- stream.on('end', async () => {
286
- const results = await Promise.allSettled(tasks);
305
+ stream.once('end', async () => {
287
306
  resolve(results);
288
307
  });
289
- stream.on('error', (err) => {
308
+ stream.once('error', (err) => {
290
309
  reject(err);
291
310
  });
292
311
  });
293
312
  };
294
313
  // カスタムメソッド END
295
- // 接続が不安定な場合は以下のロジックが生きるかもしれないので残しておく
296
- // 動作確認した限りでは以下のロジックはなくても問題なく動作する
297
- // await new Promise<void>((resolve, reject) => {
298
- // const onReady = () => {
299
- // cleanup();
300
- // resolve();
301
- // };
302
- // const onError = (error: Error) => {
303
- // cleanup();
304
- // reject(error);
305
- // };
306
- // const cleanup = () => {
307
- // client.off('ready', onReady);
308
- // client.off('error', onError);
309
- // };
310
- // client.once('ready', onReady);
311
- // client.once('error', onError);
312
- // });
314
+ try {
315
+ await this.waitForReady(client);
316
+ }
317
+ catch (error) {
318
+ // 接続できなかったクライアントはプールに入れない。ioredisの再接続も止める
319
+ client.disconnect();
320
+ throw error;
321
+ }
313
322
  return client;
314
323
  },
315
324
  destroy: async (client) => {
@@ -329,7 +338,8 @@ class RedisPool {
329
338
  return genericPool.createPool(factory, {
330
339
  max: this.max,
331
340
  min: this.min,
332
- testOnBorrow: this.testOnBorrow
341
+ testOnBorrow: this.testOnBorrow,
342
+ acquireTimeoutMillis: this.acquireTimeout
333
343
  });
334
344
  }
335
345
  }
@@ -1 +1 @@
1
- {"version":3,"file":"redis-pooling.js","sourceRoot":"","sources":["../src/redis-pooling.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"redis-pooling.js","sourceRoot":"","sources":["../src/redis-pooling.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "@digitalwalletcorp/redis-pooling",
3
- "version": "1.1.1",
3
+ "version": "1.3.0",
4
4
  "description": "This is a library for redis connection pooling",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
7
7
  "scripts": {
8
8
  "build": "tsc --project tsconfig.build.json",
9
+ "install:dev": "rm -rf lib dest && find node_modules -mindepth 1 -delete && yarn install",
9
10
  "version:patch": "npm version patch",
10
11
  "version:minor": "npm version minor",
11
12
  "version:major": "npm version major",
@@ -32,17 +33,20 @@
32
33
  "lib/**/*",
33
34
  "src/**/*"
34
35
  ],
36
+ "peerDependencies": {
37
+ "generic-pool": ">=3.9.0",
38
+ "ioredis": ">=5.0.0"
39
+ },
35
40
  "devDependencies": {
36
41
  "@types/ioredis-mock": "^8.2.6",
37
- "@types/jest": "^29.5.14",
42
+ "@types/jest": "^30.0.0",
43
+ "generic-pool": "^3.9.0",
44
+ "ioredis": "^5.9.2",
38
45
  "ioredis-mock": "^8.13.1",
39
- "jest": "^29.7.0",
40
- "ts-jest": "^29.3.4",
46
+ "jest": "^30.3.0",
47
+ "ts-jest": "^29.4.9",
41
48
  "ts-node": "^10.9.2",
42
- "typescript": "^5.8.3"
43
- },
44
- "dependencies": {
45
- "generic-pool": "^3.9.0",
46
- "ioredis": "^5.9.2"
49
+ "tsconfig-paths": "^4.2.0",
50
+ "typescript": "^6.0.3"
47
51
  }
48
52
  }
@@ -5,20 +5,25 @@ export interface RedisConfig {
5
5
  url: string;
6
6
  dbIndex?: number;
7
7
  connectTimeout?: number;
8
+ acquireTimeout?: number;
8
9
  max?: number;
9
10
  min?: number;
10
11
  testOnBorrow?: boolean;
11
12
  enableTls?: boolean;
12
13
  }
13
14
 
15
+ export interface RedisPoolOptions {
16
+ debug?: boolean;
17
+ }
18
+
14
19
  export interface RedisClient extends Redis {
15
- getKeys(pattern: string): Promise<string[]>;
16
- deleteKeys(pattern: string): Promise<PromiseSettledResult<number>[]>;
17
- _originalDbIndex?: number; // 内部状態管理用変数
20
+ getKeys(pattern: string, count?: number): Promise<string[]>;
21
+ deleteKeys(pattern: string, count?: number): Promise<PromiseSettledResult<number>[]>;
18
22
  }
19
23
 
20
24
  const logHeader = '[RedisPooling]';
21
25
  const DEFAULT_CONNECT_TIMEOUT = 5000;
26
+ const DEFAULT_ACQUIRE_TIMEOUT = 10000;
22
27
  const DEFAULT_MAX_POOLING_SIZE = 10;
23
28
  const DEFAULT_MIN_POOLING_SIZE = 0;
24
29
  const REDIS_PING_TIMEOUT_MS = 3000; // 3秒
@@ -28,18 +33,17 @@ export class RedisPool {
28
33
  private readonly url: string;
29
34
  private readonly db: number;
30
35
  private readonly connectTimeout: number;
36
+ private readonly acquireTimeout: number;
31
37
  private readonly max: number;
32
38
  private readonly min: number;
33
39
  private readonly testOnBorrow: boolean;
34
40
  private readonly tls?: { rejectUnauthorized: false };
35
41
 
36
- private readonly poolMap = new Map<number, genericPool.Pool<RedisClient>>();
42
+ private pool?: genericPool.Pool<RedisClient>;
37
43
  private initialized = false;
38
44
  private readonly debug: boolean;
39
45
 
40
- constructor(config: RedisConfig, options?: {
41
- debug?: boolean;
42
- }) {
46
+ constructor(config: RedisConfig, options?: RedisPoolOptions) {
43
47
  if (!config.url) {
44
48
  throw new Error(`${logHeader} Redis connection url is required.`);
45
49
  }
@@ -47,6 +51,7 @@ export class RedisPool {
47
51
  this.url = config.url;
48
52
  this.db = config.dbIndex ?? 0;
49
53
  this.connectTimeout = config.connectTimeout ?? DEFAULT_CONNECT_TIMEOUT;
54
+ this.acquireTimeout = config.acquireTimeout ?? DEFAULT_ACQUIRE_TIMEOUT;
50
55
  this.max = config.max ?? DEFAULT_MAX_POOLING_SIZE;
51
56
  this.min = config.min ?? DEFAULT_MIN_POOLING_SIZE;
52
57
  this.testOnBorrow = config.testOnBorrow ?? true;
@@ -65,69 +70,55 @@ export class RedisPool {
65
70
  }
66
71
 
67
72
  const index = dbIndex ?? this.db;
68
- const pool = this.getPool(index);
73
+ const pool = this.getPool();
74
+ const client = await pool.acquire();
69
75
  try {
70
- const client = await pool.acquire();
71
-
72
- this.debugLog(logHeader, `Redis client ${index} has been acquired.`);
73
- return client;
76
+ // プールの接続は、前の利用者が選択したDBを保持したまま返却される。そのため貸し出すたびに対象のDBを選択する
77
+ await client.select(index);
74
78
  } catch (error) {
79
+ await pool.destroy(client);
75
80
  throw error;
76
81
  }
82
+ this.debugLog(logHeader, `Redis client ${index} has been acquired.`);
83
+ return client;
77
84
  }
78
85
 
79
86
  public async release(client?: RedisClient): Promise<void> {
80
- if (client) {
81
- const dbIndex = client._originalDbIndex ?? this.db;
82
- const pool = this.poolMap.get(dbIndex);
83
- if (!pool) {
84
- return;
85
- }
86
- let needDestroy = false;
87
- switch (true) {
88
- case client.status === 'end':
89
- case client.status === 'close':
90
- // Redisクライアントの状態が再利用できない場合はプールから破棄
91
- needDestroy = true;
92
- break;
93
- case client.status === 'ready':
94
- try {
95
- // 元のDBインデックスに戻す
96
- await client.select(dbIndex);
97
- } catch (error) {
98
- // selectに失敗する→Redisクライアントが不正な状態にあると判断できるのでプールから破棄
99
- needDestroy = true;
100
- }
101
- break;
102
- default:
103
- }
104
- if (needDestroy) {
105
- // Redisクライアントの破棄
106
- await pool.destroy(client);
107
- this.debugLog(logHeader, `Redis client ${dbIndex} destroyed due to invalid status.`);
108
- } else {
109
- // Redisクライアントの返却
110
- await pool.release(client);
111
- this.debugLog(logHeader, `Redis client ${dbIndex} released.`);
112
- }
87
+ if (!client || !this.pool) {
88
+ return;
89
+ }
90
+ if (client.status === 'end' || client.status === 'close') {
91
+ // 再利用できない状態のRedisクライアントはプールから破棄する
92
+ await this.pool.destroy(client);
93
+ this.debugLog(logHeader, 'Redis client destroyed due to invalid status.');
94
+ } else {
95
+ await this.pool.release(client);
96
+ this.debugLog(logHeader, 'Redis client released.');
113
97
  }
114
98
  }
115
99
 
116
100
  public async destroy(timeoutMs = 5000): Promise<void> {
117
- for (const [dbIndex, pool] of this.poolMap.entries()) {
118
- this.debugLog(logHeader, `Destroying Redis pool for DB index ${dbIndex}...`);
101
+ const pool = this.pool;
102
+ if (!pool) {
103
+ return;
104
+ }
105
+ this.debugLog(logHeader, 'Destroying Redis pool...');
106
+ let timer: NodeJS.Timeout | undefined;
107
+ try {
119
108
  await Promise.race([
120
109
  (async () => {
121
110
  await pool.drain();
122
111
  await pool.clear();
123
112
  })(),
124
113
  new Promise<void>((_, reject) => {
125
- setTimeout(() => reject(new Error(`${logHeader} Timeout while draining Redis pool for DB index ${dbIndex}`)), timeoutMs);
114
+ timer = setTimeout(() => reject(new Error(`${logHeader} Timeout while draining Redis pool`)), timeoutMs);
126
115
  })
127
116
  ]);
128
- this.debugLog(logHeader, `Redis pool for DB index ${dbIndex} destroyed.`);
129
- this.poolMap.delete(dbIndex);
117
+ } finally {
118
+ clearTimeout(timer);
130
119
  }
120
+ this.debugLog(logHeader, 'Redis pool destroyed.');
121
+ this.pool = undefined;
131
122
  }
132
123
 
133
124
  /**
@@ -144,20 +135,37 @@ export class RedisPool {
144
135
  tls: this.tls,
145
136
  });
146
137
 
147
- return new Promise<void>((resolve, reject) => {
148
- const cleanup = () => {
149
- client.quit().catch(() => client.disconnect());
150
- };
138
+ try {
139
+ await this.waitForReady(client);
140
+ } finally {
141
+ client.quit().catch(() => client.disconnect());
142
+ }
143
+ }
151
144
 
152
- client.once('ready', () => {
145
+ /**
146
+ * Redisクライアントの接続が完了するまで待つ。接続に失敗した場合は、そのエラーで reject する
147
+ *
148
+ * @param {Redis} client
149
+ */
150
+ private async waitForReady(client: Redis): Promise<void> {
151
+ if (client.status === 'ready') {
152
+ return;
153
+ }
154
+ return new Promise<void>((resolve, reject) => {
155
+ const onReady = () => {
153
156
  cleanup();
154
157
  resolve();
155
- });
156
-
157
- client.once('error', (error) => {
158
+ };
159
+ const onError = (error: Error) => {
158
160
  cleanup();
159
161
  reject(error);
160
- });
162
+ };
163
+ const cleanup = () => {
164
+ client.off('ready', onReady);
165
+ client.off('error', onError);
166
+ };
167
+ client.once('ready', onReady);
168
+ client.once('error', onError);
161
169
  });
162
170
  }
163
171
 
@@ -179,26 +187,24 @@ export class RedisPool {
179
187
  }
180
188
  }
181
189
 
182
- public debugLog(...args: any[]): void {
190
+ private debugLog(...args: any[]): void {
183
191
  if (this.debug) {
184
192
  console.debug(...args);
185
193
  }
186
194
  }
187
195
 
188
- private getPool(dbIndex: number): genericPool.Pool<RedisClient> {
189
- let pool = this.poolMap.get(dbIndex);
190
- if (!pool) {
191
- pool = this.createSingleDbPool(dbIndex);
192
- this.poolMap.set(dbIndex, pool);
196
+ private getPool(): genericPool.Pool<RedisClient> {
197
+ if (!this.pool) {
198
+ this.pool = this.createPool();
193
199
  }
194
- return pool;
200
+ return this.pool;
195
201
  }
196
202
 
197
- private createSingleDbPool(dbIndex: number): genericPool.Pool<RedisClient> {
203
+ private createPool(): genericPool.Pool<RedisClient> {
198
204
  const factory: genericPool.Factory<RedisClient> = {
199
205
  create: async (): Promise<RedisClient> => {
200
206
  const client = new Redis(this.url, {
201
- db: dbIndex,
207
+ db: this.db,
202
208
  connectTimeout: this.connectTimeout,
203
209
  keepAlive: 1,
204
210
  enableOfflineQueue: true,
@@ -212,31 +218,28 @@ export class RedisPool {
212
218
  },
213
219
  reconnectOnError: (error) => {
214
220
  process.emitWarning(`${logHeader} detected error (on reconnectOnError). ${error.message}`);
215
- return true;
221
+ // フェイルオーバー後にレプリカへ接続したままになっている場合だけ、再接続で解消できる
222
+ return error.message.startsWith('READONLY');
216
223
  }
217
224
  }) as RedisClient;
218
-
219
- client._originalDbIndex = dbIndex;
220
225
  client.on('error', error => {
221
226
  process.emitWarning(`${logHeader} detected error (on error). ${error.message}`);
222
227
  });
223
228
 
224
- // カスタムメソッド内の処理でthis.debugLogなどが参照できなくなるため、poolのインスタンスを変数キャプチャする
225
- const poolInstance = this;
226
-
227
229
  // カスタムメソッド START
228
230
 
229
231
  /**
230
232
  * 指定されたパターンに一致するキーを Redis から全て取得する
231
233
  *
232
234
  * @param {string} pattern
235
+ * @param {number} [count] 1度にスキャンする件数 デフォルト:1000
233
236
  * @returns {Promise<string[]>}
234
237
  */
235
- client.getKeys = async function(pattern: string): Promise<string[]> {
238
+ client.getKeys = async function(pattern: string, count?: number): Promise<string[]> {
236
239
  const allKeys: string[] = [];
237
240
  const stream = this.scanStream({
238
241
  match: pattern,
239
- count: 1000 // ioredisが1度にスキャンする件数の目安。1000件を超えるデータがあっても全件返却される
242
+ count: count ?? 1000
240
243
  });
241
244
 
242
245
  return new Promise((resolve, reject) => {
@@ -245,8 +248,8 @@ export class RedisPool {
245
248
  allKeys.push(...keys);
246
249
  }
247
250
  });
248
- stream.on('end', () => resolve(allKeys));
249
- stream.on('error', (err: Error) => {
251
+ stream.once('end', () => resolve(allKeys));
252
+ stream.once('error', (err: Error) => {
250
253
  reject(err);
251
254
  });
252
255
  });
@@ -267,54 +270,54 @@ export class RedisPool {
267
270
  * .reduce((acc, cur) => acc + (cur as PromiseFulfilledResult<number>).value, 0);
268
271
  *
269
272
  * @param {string} pattern
273
+ * @param {number} [count] 1度にスキャンする件数 デフォルト:1000
270
274
  * @returns {Promise<PromiseSettledResult<number>>}
271
275
  */
272
- client.deleteKeys = async function(pattern: string): Promise<PromiseSettledResult<number>[]> {
276
+ client.deleteKeys = async function(pattern: string, count?: number): Promise<PromiseSettledResult<number>[]> {
273
277
  const stream = this.scanStream({
274
278
  match: pattern,
275
- count: 1000 // 1度にスキャンする件数
279
+ count: count ?? 1000
276
280
  });
281
+ const results: PromiseSettledResult<number>[] = [];
277
282
 
278
283
  return new Promise((resolve, reject) => {
279
- const tasks: Promise<number>[] = [];
280
284
  stream.on('data', async (keys: string[]) => {
281
285
  if (keys.length) {
282
- tasks.push((async () => {
286
+ stream.pause();
287
+ try {
283
288
  // UNLINK を使用し、現在のインスタンス (this) で実行
284
289
  const unlinkResult = await this.unlink(...keys);
285
- return unlinkResult;
286
- })());
290
+ results.push({
291
+ status: 'fulfilled',
292
+ value: unlinkResult
293
+ });
294
+ } catch (err) {
295
+ results.push({
296
+ status: 'rejected',
297
+ reason: err
298
+ });
299
+ } finally {
300
+ stream.resume();
301
+ }
287
302
  }
288
303
  });
289
- stream.on('end', async () => {
290
- const results = await Promise.allSettled(tasks);
304
+ stream.once('end', async () => {
291
305
  resolve(results);
292
306
  });
293
- stream.on('error', (err: Error) => {
307
+ stream.once('error', (err: Error) => {
294
308
  reject(err);
295
309
  });
296
310
  });
297
311
  };
298
312
  // カスタムメソッド END
299
313
 
300
- // 接続が不安定な場合は以下のロジックが生きるかもしれないので残しておく
301
- // 動作確認した限りでは以下のロジックはなくても問題なく動作する
302
- // await new Promise<void>((resolve, reject) => {
303
- // const onReady = () => {
304
- // cleanup();
305
- // resolve();
306
- // };
307
- // const onError = (error: Error) => {
308
- // cleanup();
309
- // reject(error);
310
- // };
311
- // const cleanup = () => {
312
- // client.off('ready', onReady);
313
- // client.off('error', onError);
314
- // };
315
- // client.once('ready', onReady);
316
- // client.once('error', onError);
317
- // });
314
+ try {
315
+ await this.waitForReady(client);
316
+ } catch (error) {
317
+ // 接続できなかったクライアントはプールに入れない。ioredisの再接続も止める
318
+ client.disconnect();
319
+ throw error;
320
+ }
318
321
 
319
322
  return client;
320
323
  },
@@ -335,7 +338,8 @@ export class RedisPool {
335
338
  return genericPool.createPool(factory, {
336
339
  max: this.max,
337
340
  min: this.min,
338
- testOnBorrow: this.testOnBorrow
341
+ testOnBorrow: this.testOnBorrow,
342
+ acquireTimeoutMillis: this.acquireTimeout
339
343
  });
340
344
  }
341
345
  }