@@ -23,6 +23,11 @@ const INTEGRATION_MODE = Object.freeze({
2323 LOCAL_REDIS : "LOCAL_REDIS" ,
2424 NO_REDIS : "NO_REDIS" ,
2525} ) ;
26+ const CLIENT_NAME = Object . freeze ( {
27+ SILENT : "SILENT" ,
28+ MAIN : "MAIN" ,
29+ SUBSCRIBER : "SUBSCRIBER" ,
30+ } ) ;
2631const CF_REDIS_SERVICE_LABEL = "redis-cache" ;
2732const REDIS_CLIENT_DEFAULT_PING_INTERVAL = 4 * 60000 ;
2833
@@ -140,18 +145,28 @@ const _getRedisOptionsTuple = () => {
140145 return __activeOptionsTuple ;
141146} ;
142147
148+ const _noReconnectStrategy = ( ) => new VError ( { name : VERROR_CLUSTER_NAME } , "disabled reconnect" ) ;
149+
143150/**
144151 * Lazily create a new redis client. Client creation transparently handles
145152 * - custom credentials and client options passed in via {@link setCustomOptions},
146153 * - Cloud Foundry service with label "redis-cache" (hyperscaler option), and
147154 * - local redis-server.
148155 *
156+ * @param {string } clientName
157+ * @param {CreateOptions } [options]
149158 * @returns {RedisClient|RedisCluster }
150159 * @private
151160 */
152- const _createClientBase = ( clientName ) => {
161+ const _createClientBase = ( clientName , options = { } ) => {
162+ const { doReconnect = true } = options ;
153163 try {
154164 const [ isCluster , redisClientOptions ] = _getRedisOptionsTuple ( ) ;
165+
166+ if ( ! doReconnect ) {
167+ redisClientOptions . socket . reconnectStrategy = _noReconnectStrategy ;
168+ }
169+
155170 return isCluster
156171 ? redis . createCluster ( {
157172 rootNodes : [ redisClientOptions ] , // NOTE: assume this ignores everything but socket/url
@@ -167,10 +182,21 @@ const _createClientBase = (clientName) => {
167182 }
168183} ;
169184
170- const _createClientAndConnect = async ( clientName , { doLogEvents = true } = { } ) => {
185+ /**
186+ * @typedef CreateOptions
187+ * @type object
188+ * @property {doLogEvents } [boolean] log error events, defaults to true
189+ * @property {doReconnect } [boolean] setting to false disables reconnect strategy, defaults to true
190+ */
191+ /**
192+ * @param {string } clientName
193+ * @param {CreateOptions } [options]
194+ */
195+ const _createClientAndConnect = async ( clientName , options = { } ) => {
196+ const { doLogEvents = true } = options ;
171197 let client = null ;
172198 try {
173- client = _createClientBase ( clientName ) ;
199+ client = _createClientBase ( clientName , options ) ;
174200 } catch ( err ) {
175201 throw new VError ( { name : VERROR_CLUSTER_NAME , cause : err , info : { clientName } } , "error during create client" ) ;
176202 }
@@ -210,7 +236,10 @@ const _canGetClient = async () => {
210236 if ( __canGetClientPromise === null ) {
211237 __canGetClientPromise = ( async ( ) => {
212238 try {
213- const silentClient = await _createClientAndConnect ( "silent" , { doLogEvents : false } ) ;
239+ const silentClient = await _createClientAndConnect ( CLIENT_NAME . SILENT , {
240+ doLogEvents : false ,
241+ doReconnect : false ,
242+ } ) ;
214243 await _closeClientBase ( silentClient ) ;
215244 return true ;
216245 } catch { } // eslint-disable-line no-empty
@@ -251,7 +280,7 @@ const getIntegrationMode = async () => {
251280 */
252281const getMainClient = async ( ) => {
253282 if ( ! __mainClientPromise ) {
254- __mainClientPromise = _createClientAndConnect ( "main" ) ;
283+ __mainClientPromise = _createClientAndConnect ( CLIENT_NAME . MAIN ) ;
255284 }
256285 return await __mainClientPromise ;
257286} ;
@@ -277,7 +306,7 @@ const closeMainClient = async () => {
277306 */
278307const getSubscriberClient = async ( ) => {
279308 if ( ! __subscriberClientPromise ) {
280- __subscriberClientPromise = _createClientAndConnect ( "subscriber" ) ;
309+ __subscriberClientPromise = _createClientAndConnect ( CLIENT_NAME . SUBSCRIBER ) ;
281310 }
282311 return await __subscriberClientPromise ;
283312} ;
0 commit comments