@digitalwalletcorp/redis-pooling 1.1.1 → 1.2.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,25 +3,26 @@ 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
  }
11
12
  export interface RedisClient extends Redis {
12
- getKeys(pattern: string): Promise<string[]>;
13
- deleteKeys(pattern: string): Promise<PromiseSettledResult<number>[]>;
14
- _originalDbIndex?: number;
13
+ getKeys(pattern: string, count?: number): Promise<string[]>;
14
+ deleteKeys(pattern: string, count?: number): Promise<PromiseSettledResult<number>[]>;
15
15
  }
16
16
  export declare class RedisPool {
17
17
  private readonly url;
18
18
  private readonly db;
19
19
  private readonly connectTimeout;
20
+ private readonly acquireTimeout;
20
21
  private readonly max;
21
22
  private readonly min;
22
23
  private readonly testOnBorrow;
23
24
  private readonly tls?;
24
- private readonly poolMap;
25
+ private pool?;
25
26
  private initialized;
26
27
  private readonly debug;
27
28
  constructor(config: RedisConfig, options?: {
@@ -36,8 +37,14 @@ export declare class RedisPool {
36
37
  * @param {number} dbIndex
37
38
  */
38
39
  private checkConnectivity;
40
+ /**
41
+ * Redisクライアントの接続が完了するまで待つ。接続に失敗した場合は、そのエラーで reject する
42
+ *
43
+ * @param {Redis} client
44
+ */
45
+ private waitForReady;
39
46
  private ping;
40
47
  debugLog(...args: any[]): void;
41
48
  private getPool;
42
- private createSingleDbPool;
49
+ private createPool;
43
50
  }
@@ -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,10 +221,10 @@ 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
  });
@@ -228,13 +235,14 @@ class RedisPool {
228
235
  * 指定されたパターンに一致するキーを Redis から全て取得する
229
236
  *
230
237
  * @param {string} pattern
238
+ * @param {number} [count] 1度にスキャンする件数 デフォルト:1000
231
239
  * @returns {Promise<string[]>}
232
240
  */
233
- client.getKeys = async function (pattern) {
241
+ client.getKeys = async function (pattern, count) {
234
242
  const allKeys = [];
235
243
  const stream = this.scanStream({
236
244
  match: pattern,
237
- count: 1000 // ioredisが1度にスキャンする件数の目安。1000件を超えるデータがあっても全件返却される
245
+ count: count ?? 1000
238
246
  });
239
247
  return new Promise((resolve, reject) => {
240
248
  stream.on('data', (keys) => {
@@ -242,8 +250,8 @@ class RedisPool {
242
250
  allKeys.push(...keys);
243
251
  }
244
252
  });
245
- stream.on('end', () => resolve(allKeys));
246
- stream.on('error', (err) => {
253
+ stream.once('end', () => resolve(allKeys));
254
+ stream.once('error', (err) => {
247
255
  reject(err);
248
256
  });
249
257
  });
@@ -264,52 +272,55 @@ class RedisPool {
264
272
  * .reduce((acc, cur) => acc + (cur as PromiseFulfilledResult<number>).value, 0);
265
273
  *
266
274
  * @param {string} pattern
275
+ * @param {number} [count] 1度にスキャンする件数 デフォルト:1000
267
276
  * @returns {Promise<PromiseSettledResult<number>>}
268
277
  */
269
- client.deleteKeys = async function (pattern) {
278
+ client.deleteKeys = async function (pattern, count) {
270
279
  const stream = this.scanStream({
271
280
  match: pattern,
272
- count: 1000 // 1度にスキャンする件数
281
+ count: count ?? 1000
273
282
  });
283
+ const results = [];
274
284
  return new Promise((resolve, reject) => {
275
- const tasks = [];
276
285
  stream.on('data', async (keys) => {
277
286
  if (keys.length) {
278
- tasks.push((async () => {
287
+ stream.pause();
288
+ try {
279
289
  // UNLINK を使用し、現在のインスタンス (this) で実行
280
290
  const unlinkResult = await this.unlink(...keys);
281
- return unlinkResult;
282
- })());
291
+ results.push({
292
+ status: 'fulfilled',
293
+ value: unlinkResult
294
+ });
295
+ }
296
+ catch (err) {
297
+ results.push({
298
+ status: 'rejected',
299
+ reason: err
300
+ });
301
+ }
302
+ finally {
303
+ stream.resume();
304
+ }
283
305
  }
284
306
  });
285
- stream.on('end', async () => {
286
- const results = await Promise.allSettled(tasks);
307
+ stream.once('end', async () => {
287
308
  resolve(results);
288
309
  });
289
- stream.on('error', (err) => {
310
+ stream.once('error', (err) => {
290
311
  reject(err);
291
312
  });
292
313
  });
293
314
  };
294
315
  // カスタムメソッド 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
- // });
316
+ try {
317
+ await this.waitForReady(client);
318
+ }
319
+ catch (error) {
320
+ // 接続できなかったクライアントはプールに入れない。ioredisの再接続も止める
321
+ client.disconnect();
322
+ throw error;
323
+ }
313
324
  return client;
314
325
  },
315
326
  destroy: async (client) => {
@@ -329,7 +340,8 @@ class RedisPool {
329
340
  return genericPool.createPool(factory, {
330
341
  max: this.max,
331
342
  min: this.min,
332
- testOnBorrow: this.testOnBorrow
343
+ testOnBorrow: this.testOnBorrow,
344
+ acquireTimeoutMillis: this.acquireTimeout
333
345
  });
334
346
  }
335
347
  }
@@ -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,6 +1,6 @@
1
1
  {
2
2
  "name": "@digitalwalletcorp/redis-pooling",
3
- "version": "1.1.1",
3
+ "version": "1.2.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",
@@ -34,12 +34,13 @@
34
34
  ],
35
35
  "devDependencies": {
36
36
  "@types/ioredis-mock": "^8.2.6",
37
- "@types/jest": "^29.5.14",
37
+ "@types/jest": "^30.0.0",
38
38
  "ioredis-mock": "^8.13.1",
39
- "jest": "^29.7.0",
40
- "ts-jest": "^29.3.4",
39
+ "jest": "^30.3.0",
40
+ "ts-jest": "^29.4.9",
41
41
  "ts-node": "^10.9.2",
42
- "typescript": "^5.8.3"
42
+ "tsconfig-paths": "^4.2.0",
43
+ "typescript": "^6.0.3"
43
44
  },
44
45
  "dependencies": {
45
46
  "generic-pool": "^3.9.0",
@@ -5,6 +5,7 @@ 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;
@@ -12,13 +13,13 @@ export interface RedisConfig {
12
13
  }
13
14
 
14
15
  export interface RedisClient extends Redis {
15
- getKeys(pattern: string): Promise<string[]>;
16
- deleteKeys(pattern: string): Promise<PromiseSettledResult<number>[]>;
17
- _originalDbIndex?: number; // 内部状態管理用変数
16
+ getKeys(pattern: string, count?: number): Promise<string[]>;
17
+ deleteKeys(pattern: string, count?: number): Promise<PromiseSettledResult<number>[]>;
18
18
  }
19
19
 
20
20
  const logHeader = '[RedisPooling]';
21
21
  const DEFAULT_CONNECT_TIMEOUT = 5000;
22
+ const DEFAULT_ACQUIRE_TIMEOUT = 10000;
22
23
  const DEFAULT_MAX_POOLING_SIZE = 10;
23
24
  const DEFAULT_MIN_POOLING_SIZE = 0;
24
25
  const REDIS_PING_TIMEOUT_MS = 3000; // 3秒
@@ -28,12 +29,13 @@ export class RedisPool {
28
29
  private readonly url: string;
29
30
  private readonly db: number;
30
31
  private readonly connectTimeout: number;
32
+ private readonly acquireTimeout: number;
31
33
  private readonly max: number;
32
34
  private readonly min: number;
33
35
  private readonly testOnBorrow: boolean;
34
36
  private readonly tls?: { rejectUnauthorized: false };
35
37
 
36
- private readonly poolMap = new Map<number, genericPool.Pool<RedisClient>>();
38
+ private pool?: genericPool.Pool<RedisClient>;
37
39
  private initialized = false;
38
40
  private readonly debug: boolean;
39
41
 
@@ -47,6 +49,7 @@ export class RedisPool {
47
49
  this.url = config.url;
48
50
  this.db = config.dbIndex ?? 0;
49
51
  this.connectTimeout = config.connectTimeout ?? DEFAULT_CONNECT_TIMEOUT;
52
+ this.acquireTimeout = config.acquireTimeout ?? DEFAULT_ACQUIRE_TIMEOUT;
50
53
  this.max = config.max ?? DEFAULT_MAX_POOLING_SIZE;
51
54
  this.min = config.min ?? DEFAULT_MIN_POOLING_SIZE;
52
55
  this.testOnBorrow = config.testOnBorrow ?? true;
@@ -65,69 +68,55 @@ export class RedisPool {
65
68
  }
66
69
 
67
70
  const index = dbIndex ?? this.db;
68
- const pool = this.getPool(index);
71
+ const pool = this.getPool();
72
+ const client = await pool.acquire();
69
73
  try {
70
- const client = await pool.acquire();
71
-
72
- this.debugLog(logHeader, `Redis client ${index} has been acquired.`);
73
- return client;
74
+ // プールの接続は、前の利用者が選択したDBを保持したまま返却される。そのため貸し出すたびに対象のDBを選択する
75
+ await client.select(index);
74
76
  } catch (error) {
77
+ await pool.destroy(client);
75
78
  throw error;
76
79
  }
80
+ this.debugLog(logHeader, `Redis client ${index} has been acquired.`);
81
+ return client;
77
82
  }
78
83
 
79
84
  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
- }
85
+ if (!client || !this.pool) {
86
+ return;
87
+ }
88
+ if (client.status === 'end' || client.status === 'close') {
89
+ // 再利用できない状態のRedisクライアントはプールから破棄する
90
+ await this.pool.destroy(client);
91
+ this.debugLog(logHeader, 'Redis client destroyed due to invalid status.');
92
+ } else {
93
+ await this.pool.release(client);
94
+ this.debugLog(logHeader, 'Redis client released.');
113
95
  }
114
96
  }
115
97
 
116
98
  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}...`);
99
+ const pool = this.pool;
100
+ if (!pool) {
101
+ return;
102
+ }
103
+ this.debugLog(logHeader, 'Destroying Redis pool...');
104
+ let timer: NodeJS.Timeout | undefined;
105
+ try {
119
106
  await Promise.race([
120
107
  (async () => {
121
108
  await pool.drain();
122
109
  await pool.clear();
123
110
  })(),
124
111
  new Promise<void>((_, reject) => {
125
- setTimeout(() => reject(new Error(`${logHeader} Timeout while draining Redis pool for DB index ${dbIndex}`)), timeoutMs);
112
+ timer = setTimeout(() => reject(new Error(`${logHeader} Timeout while draining Redis pool`)), timeoutMs);
126
113
  })
127
114
  ]);
128
- this.debugLog(logHeader, `Redis pool for DB index ${dbIndex} destroyed.`);
129
- this.poolMap.delete(dbIndex);
115
+ } finally {
116
+ clearTimeout(timer);
130
117
  }
118
+ this.debugLog(logHeader, 'Redis pool destroyed.');
119
+ this.pool = undefined;
131
120
  }
132
121
 
133
122
  /**
@@ -144,20 +133,37 @@ export class RedisPool {
144
133
  tls: this.tls,
145
134
  });
146
135
 
147
- return new Promise<void>((resolve, reject) => {
148
- const cleanup = () => {
149
- client.quit().catch(() => client.disconnect());
150
- };
136
+ try {
137
+ await this.waitForReady(client);
138
+ } finally {
139
+ client.quit().catch(() => client.disconnect());
140
+ }
141
+ }
151
142
 
152
- client.once('ready', () => {
143
+ /**
144
+ * Redisクライアントの接続が完了するまで待つ。接続に失敗した場合は、そのエラーで reject する
145
+ *
146
+ * @param {Redis} client
147
+ */
148
+ private async waitForReady(client: Redis): Promise<void> {
149
+ if (client.status === 'ready') {
150
+ return;
151
+ }
152
+ return new Promise<void>((resolve, reject) => {
153
+ const onReady = () => {
153
154
  cleanup();
154
155
  resolve();
155
- });
156
-
157
- client.once('error', (error) => {
156
+ };
157
+ const onError = (error: Error) => {
158
158
  cleanup();
159
159
  reject(error);
160
- });
160
+ };
161
+ const cleanup = () => {
162
+ client.off('ready', onReady);
163
+ client.off('error', onError);
164
+ };
165
+ client.once('ready', onReady);
166
+ client.once('error', onError);
161
167
  });
162
168
  }
163
169
 
@@ -185,20 +191,18 @@ export class RedisPool {
185
191
  }
186
192
  }
187
193
 
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);
194
+ private getPool(): genericPool.Pool<RedisClient> {
195
+ if (!this.pool) {
196
+ this.pool = this.createPool();
193
197
  }
194
- return pool;
198
+ return this.pool;
195
199
  }
196
200
 
197
- private createSingleDbPool(dbIndex: number): genericPool.Pool<RedisClient> {
201
+ private createPool(): genericPool.Pool<RedisClient> {
198
202
  const factory: genericPool.Factory<RedisClient> = {
199
203
  create: async (): Promise<RedisClient> => {
200
204
  const client = new Redis(this.url, {
201
- db: dbIndex,
205
+ db: this.db,
202
206
  connectTimeout: this.connectTimeout,
203
207
  keepAlive: 1,
204
208
  enableOfflineQueue: true,
@@ -212,11 +216,10 @@ export class RedisPool {
212
216
  },
213
217
  reconnectOnError: (error) => {
214
218
  process.emitWarning(`${logHeader} detected error (on reconnectOnError). ${error.message}`);
215
- return true;
219
+ // フェイルオーバー後にレプリカへ接続したままになっている場合だけ、再接続で解消できる
220
+ return error.message.startsWith('READONLY');
216
221
  }
217
222
  }) as RedisClient;
218
-
219
- client._originalDbIndex = dbIndex;
220
223
  client.on('error', error => {
221
224
  process.emitWarning(`${logHeader} detected error (on error). ${error.message}`);
222
225
  });
@@ -230,13 +233,14 @@ export class RedisPool {
230
233
  * 指定されたパターンに一致するキーを Redis から全て取得する
231
234
  *
232
235
  * @param {string} pattern
236
+ * @param {number} [count] 1度にスキャンする件数 デフォルト:1000
233
237
  * @returns {Promise<string[]>}
234
238
  */
235
- client.getKeys = async function(pattern: string): Promise<string[]> {
239
+ client.getKeys = async function(pattern: string, count?: number): Promise<string[]> {
236
240
  const allKeys: string[] = [];
237
241
  const stream = this.scanStream({
238
242
  match: pattern,
239
- count: 1000 // ioredisが1度にスキャンする件数の目安。1000件を超えるデータがあっても全件返却される
243
+ count: count ?? 1000
240
244
  });
241
245
 
242
246
  return new Promise((resolve, reject) => {
@@ -245,8 +249,8 @@ export class RedisPool {
245
249
  allKeys.push(...keys);
246
250
  }
247
251
  });
248
- stream.on('end', () => resolve(allKeys));
249
- stream.on('error', (err: Error) => {
252
+ stream.once('end', () => resolve(allKeys));
253
+ stream.once('error', (err: Error) => {
250
254
  reject(err);
251
255
  });
252
256
  });
@@ -267,54 +271,54 @@ export class RedisPool {
267
271
  * .reduce((acc, cur) => acc + (cur as PromiseFulfilledResult<number>).value, 0);
268
272
  *
269
273
  * @param {string} pattern
274
+ * @param {number} [count] 1度にスキャンする件数 デフォルト:1000
270
275
  * @returns {Promise<PromiseSettledResult<number>>}
271
276
  */
272
- client.deleteKeys = async function(pattern: string): Promise<PromiseSettledResult<number>[]> {
277
+ client.deleteKeys = async function(pattern: string, count?: number): Promise<PromiseSettledResult<number>[]> {
273
278
  const stream = this.scanStream({
274
279
  match: pattern,
275
- count: 1000 // 1度にスキャンする件数
280
+ count: count ?? 1000
276
281
  });
282
+ const results: PromiseSettledResult<number>[] = [];
277
283
 
278
284
  return new Promise((resolve, reject) => {
279
- const tasks: Promise<number>[] = [];
280
285
  stream.on('data', async (keys: string[]) => {
281
286
  if (keys.length) {
282
- tasks.push((async () => {
287
+ stream.pause();
288
+ try {
283
289
  // UNLINK を使用し、現在のインスタンス (this) で実行
284
290
  const unlinkResult = await this.unlink(...keys);
285
- return unlinkResult;
286
- })());
291
+ results.push({
292
+ status: 'fulfilled',
293
+ value: unlinkResult
294
+ });
295
+ } catch (err) {
296
+ results.push({
297
+ status: 'rejected',
298
+ reason: err
299
+ });
300
+ } finally {
301
+ stream.resume();
302
+ }
287
303
  }
288
304
  });
289
- stream.on('end', async () => {
290
- const results = await Promise.allSettled(tasks);
305
+ stream.once('end', async () => {
291
306
  resolve(results);
292
307
  });
293
- stream.on('error', (err: Error) => {
308
+ stream.once('error', (err: Error) => {
294
309
  reject(err);
295
310
  });
296
311
  });
297
312
  };
298
313
  // カスタムメソッド END
299
314
 
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
- // });
315
+ try {
316
+ await this.waitForReady(client);
317
+ } catch (error) {
318
+ // 接続できなかったクライアントはプールに入れない。ioredisの再接続も止める
319
+ client.disconnect();
320
+ throw error;
321
+ }
318
322
 
319
323
  return client;
320
324
  },
@@ -335,7 +339,8 @@ export class RedisPool {
335
339
  return genericPool.createPool(factory, {
336
340
  max: this.max,
337
341
  min: this.min,
338
- testOnBorrow: this.testOnBorrow
342
+ testOnBorrow: this.testOnBorrow,
343
+ acquireTimeoutMillis: this.acquireTimeout
339
344
  });
340
345
  }
341
346
  }