@@ -119,6 +119,30 @@ class FeatureToggles {
119119 // START OF CONSTRUCTOR SECTION
120120 // ========================================
121121
122+ static _getDefaultUniqueName ( ) {
123+ if ( ENV_UNIQUE_NAME ) {
124+ return ENV_UNIQUE_NAME ;
125+ }
126+ let cfApp ;
127+ try {
128+ cfApp = cfEnv . cfApp ;
129+ if ( cfApp . application_name ) {
130+ return cfApp . application_name ;
131+ }
132+ } catch ( err ) {
133+ throw new VError (
134+ {
135+ name : VERROR_CLUSTER_NAME ,
136+ cause : err ,
137+ info : {
138+ cfApp : JSON . stringify ( cfApp ) ,
139+ } ,
140+ } ,
141+ "error determining cf app name"
142+ ) ;
143+ }
144+ }
145+
122146 _processValidations ( featureKey , validations , configFilepath ) {
123147 const configDir = configFilepath ? pathlib . dirname ( configFilepath ) : process . cwd ( ) ;
124148
@@ -274,7 +298,16 @@ class FeatureToggles {
274298 ) ;
275299 }
276300
277- _reset ( { uniqueName, redisChannel = DEFAULT_REDIS_CHANNEL , redisKey = DEFAULT_REDIS_KEY } ) {
301+ /**
302+ * Implementation for {@link constructor}.
303+ *
304+ * @param {ConstructorOptions } [options]
305+ */
306+ _reset ( {
307+ uniqueName = FeatureToggles . _getDefaultUniqueName ( ) ,
308+ redisChannel = DEFAULT_REDIS_CHANNEL ,
309+ redisKey = DEFAULT_REDIS_KEY ,
310+ } = { } ) {
278311 this . __redisChannel = uniqueName ? redisChannel + "-" + uniqueName : redisChannel ;
279312 this . __redisKey = uniqueName ? redisKey + "-" + uniqueName : redisKey ;
280313
@@ -292,9 +325,19 @@ class FeatureToggles {
292325 this . __isConfigProcessed = false ;
293326 }
294327
295- // NOTE: constructors cannot be async, so we need to split this state preparation part from the initialize part
296- constructor ( { uniqueName = undefined , redisChannel = DEFAULT_REDIS_CHANNEL , redisKey = DEFAULT_REDIS_KEY } = { } ) {
297- this . _reset ( { uniqueName, redisChannel, redisKey } ) ;
328+ /**
329+ * @typedef ConstructorOptions
330+ * @type object
331+ * @property {string } [uniqueName] unique name to prefix both Redis channel and key
332+ * @property {string } [redisChannel] channel for Redis pub/sub to propagate changes across servers
333+ * @property {string } [redisKey] key in Redis to save non-fallback values
334+ */
335+ /**
336+ * NOTE: constructors cannot be async, so we need to split this state preparation part from the initialize part
337+ * @param {ConstructorOptions } [options]
338+ */
339+ constructor ( options ) {
340+ this . _reset ( options ) ;
298341 }
299342
300343 // ========================================
@@ -304,39 +347,14 @@ class FeatureToggles {
304347 // START OF SINGLETON SECTION
305348 // ========================================
306349
307- static _getInstanceUniqueName ( ) {
308- if ( ENV_UNIQUE_NAME ) {
309- return ENV_UNIQUE_NAME ;
310- }
311- let cfApp ;
312- try {
313- cfApp = cfEnv . cfApp ;
314- if ( cfApp . application_name ) {
315- return cfApp . application_name ;
316- }
317- } catch ( err ) {
318- throw new VError (
319- {
320- name : VERROR_CLUSTER_NAME ,
321- cause : err ,
322- info : {
323- cfApp : JSON . stringify ( cfApp ) ,
324- } ,
325- } ,
326- "error determining cf app name"
327- ) ;
328- }
329- }
330-
331350 /**
332351 * Get singleton instance
333352 *
334353 * @returns {FeatureToggles }
335354 */
336355 static getInstance ( ) {
337356 if ( ! FeatureToggles . __instance ) {
338- const uniqueName = FeatureToggles . _getInstanceUniqueName ( ) ;
339- FeatureToggles . __instance = new FeatureToggles ( { uniqueName } ) ;
357+ FeatureToggles . __instance = new FeatureToggles ( ) ;
340358 }
341359 return FeatureToggles . __instance ;
342360 }
@@ -713,6 +731,11 @@ class FeatureToggles {
713731 ) ;
714732 }
715733
734+ /**
735+ * Implementation for {@link initializeFeatures}.
736+ *
737+ * @param {InitializeOptions } [options]
738+ */
716739 async _initializeFeatures ( { config : configRuntime , configFile : configFilepath , configAuto } = { } ) {
717740 if ( this . __isInitialized ) {
718741 return ;
@@ -840,9 +863,23 @@ class FeatureToggles {
840863 return this ;
841864 }
842865
866+ /**
867+ * TODO
868+ * @typedef Config
869+ * @type object
870+ */
871+ /**
872+ * @typedef InitializeOptions
873+ * @type object
874+ * @property {Config } [config]
875+ * @property {string } [configFile]
876+ * @property {Config } [configAuto]
877+ */
843878 /**
844879 * Initialize needs to run and finish before other APIs are called. It processes the configuration, sets up
845880 * related internal state, and starts communication with redis.
881+ *
882+ * @param {InitializeOptions } [options]
846883 */
847884 async initializeFeatures ( options ) {
848885 if ( ! this . __initializePromise ) {
@@ -919,11 +956,15 @@ class FeatureToggles {
919956 */
920957 async getRemoteFeaturesInfos ( ) {
921958 this . _ensureInitialized ( ) ;
959+
960+ let remoteStateScopedValues ;
961+ // NOTE: for NO_REDIS mode, we show local updates
922962 if ( ( await redis . getIntegrationMode ( ) ) === REDIS_INTEGRATION_MODE . NO_REDIS ) {
923- return { } ;
963+ remoteStateScopedValues = this . __stateScopedValues ?? { } ;
964+ } else {
965+ remoteStateScopedValues = await redis . hashGetAllObjects ( this . __redisKey ) ;
924966 }
925967
926- const remoteStateScopedValues = await redis . hashGetAllObjects ( this . __redisKey ) ;
927968 if ( ! remoteStateScopedValues ) {
928969 return null ;
929970 }
0 commit comments