diff --git a/package-lock.json b/package-lock.json index ed4aa7f..61e91e6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@athenna/cache", - "version": "5.9.0", + "version": "5.10.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@athenna/cache", - "version": "5.9.0", + "version": "5.10.0", "license": "MIT", "devDependencies": { "@athenna/artisan": "^5.12.0", diff --git a/package.json b/package.json index bb882be..118bb73 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@athenna/cache", - "version": "5.9.0", + "version": "5.10.0", "description": "The cache handler for Athenna Framework.", "license": "MIT", "author": "João Lenon ", diff --git a/src/cache/drivers/RedisDriver.ts b/src/cache/drivers/RedisDriver.ts index 5dca2ed..4dc0ce3 100644 --- a/src/cache/drivers/RedisDriver.ts +++ b/src/cache/drivers/RedisDriver.ts @@ -106,9 +106,34 @@ export class RedisDriver extends Driver { return } + const config = Config.get(`cache.stores.${this.store}`) const { createClient } = this.getRedis() - this.client = createClient({ url: this.url, socket: this.socket }) + const defaultReconnectStrategy = (retries: number) => { + if (retries >= 5) { + return new Error( + `Cache store "${this.store}": max reconnect retries reached` + ) + } + return Math.min(retries * 200, 2000) + } + + this.client = createClient({ + url: this.url, + socket: { + ...this.socket, + reconnectStrategy: config?.reconnectStrategy ?? defaultReconnectStrategy + } + }) + + // Required: without this listener node-redis emits 'error' events as + // unhandled rejections whenever the connection drops after initial connect. + this.client.on('error', err => { + Log.channelOrVanilla('application').error( + `({red} Error) on ({yellow} ${this.store}) cache store: ${err.message}` + ) + }) + this.client .connect() .then(() => { @@ -118,6 +143,11 @@ export class RedisDriver extends Driver { ) } }) + .catch(err => { + Log.channelOrVanilla('application').error( + `Failed to connect to ({yellow} ${this.store}) cache store: ${err.message}` + ) + }) this.isConnected = true this.isSavedOnFactory = options.saveOnFactory diff --git a/src/types/StoreOptions.ts b/src/types/StoreOptions.ts index 3ce500f..95c902e 100644 --- a/src/types/StoreOptions.ts +++ b/src/types/StoreOptions.ts @@ -82,5 +82,16 @@ export type StoreOptions = { * @default Config.get(`cache.stores.${store}.maxEntrySize`) */ maxEntrySize?: number + + /** + * Define a custom reconnect strategy for the Redis connection. + * Receives the number of retries so far. Return a number (ms delay + * before next retry) or an Error to stop retrying and reject all + * pending commands. Defaults to exponential backoff that gives up + * after 5 retries. + * + * @default built-in exponential backoff, max 5 retries + */ + reconnectStrategy?: (retries: number) => number | Error } }