@@ -10,6 +10,7 @@ import type {
10
10
AppConfigGetOptions ,
11
11
AppConfigGetOutput ,
12
12
} from '../types/AppConfigProvider' ;
13
+ import { APPCONFIG_TOKEN_EXPIRATION } from '../constants' ;
13
14
14
15
/**
15
16
* ## Intro
@@ -182,7 +183,10 @@ import type {
182
183
*/
183
184
class AppConfigProvider extends BaseProvider {
184
185
public client ! : AppConfigDataClient ;
185
- protected configurationTokenStore = new Map < string , string > ( ) ;
186
+ protected configurationTokenStore = new Map <
187
+ string ,
188
+ { value : string ; expiration : number }
189
+ > ( ) ;
186
190
protected valueStore = new Map < string , Uint8Array > ( ) ;
187
191
private application ?: string ;
188
192
private environment : string ;
@@ -270,23 +274,26 @@ class AppConfigProvider extends BaseProvider {
270
274
/**
271
275
* Retrieve a configuration from AWS AppConfig.
272
276
*
277
+ * First we start the session and after that we retrieve the configuration from AppSync.
278
+ * When starting a session, the service returns a token that can be used to poll for changes
279
+ * for up to 24hrs, so we cache it for later use together with the expiration date.
280
+ *
281
+ * The value of the configuration is also cached internally because AppConfig returns an empty
282
+ * value if the configuration has not changed since the last poll. This way even if your code
283
+ * polls the configuration multiple times, we return the most recent value by returning the cached
284
+ * one if an empty response is returned by AppConfig.
285
+ *
273
286
* @param {string } name - Name of the configuration or its ID
274
287
* @param {AppConfigGetOptions } options - SDK options to propagate to `StartConfigurationSession` API call
275
288
*/
276
289
protected async _get (
277
290
name : string ,
278
291
options ?: AppConfigGetOptions
279
292
) : Promise < Uint8Array | undefined > {
280
- /**
281
- * The new AppConfig APIs require two API calls to return the configuration
282
- * First we start the session and after that we retrieve the configuration
283
- * We need to store { name: token } pairs to use in the next execution
284
- * We also need to store { name : value } pairs because AppConfig returns
285
- * an empty value if the session already has the latest configuration
286
- * but, we don't want to return an empty value to our callers.
287
- * {@link https://docs.aws.amazon.com/appconfig/latest/userguide/appconfig-retrieving-the-configuration.html}
288
- **/
289
- if ( ! this . configurationTokenStore . has ( name ) ) {
293
+ if (
294
+ ! this . configurationTokenStore . has ( name ) ||
295
+ this . configurationTokenStore . get ( name ) ! . expiration <= Date . now ( )
296
+ ) {
290
297
const sessionOptions : StartConfigurationSessionCommandInput = {
291
298
...( options ?. sdkOptions || { } ) ,
292
299
ApplicationIdentifier : this . application ,
@@ -303,20 +310,23 @@ class AppConfigProvider extends BaseProvider {
303
310
if ( ! session . InitialConfigurationToken )
304
311
throw new Error ( 'Unable to retrieve the configuration token' ) ;
305
312
306
- this . configurationTokenStore . set ( name , session . InitialConfigurationToken ) ;
313
+ this . configurationTokenStore . set ( name , {
314
+ value : session . InitialConfigurationToken ,
315
+ expiration : Date . now ( ) + APPCONFIG_TOKEN_EXPIRATION ,
316
+ } ) ;
307
317
}
308
318
309
319
const getConfigurationCommand = new GetLatestConfigurationCommand ( {
310
- ConfigurationToken : this . configurationTokenStore . get ( name ) ,
320
+ ConfigurationToken : this . configurationTokenStore . get ( name ) ?. value ,
311
321
} ) ;
312
322
313
323
const response = await this . client . send ( getConfigurationCommand ) ;
314
324
315
325
if ( response . NextPollConfigurationToken ) {
316
- this . configurationTokenStore . set (
317
- name ,
318
- response . NextPollConfigurationToken
319
- ) ;
326
+ this . configurationTokenStore . set ( name , {
327
+ value : response . NextPollConfigurationToken ,
328
+ expiration : Date . now ( ) + APPCONFIG_TOKEN_EXPIRATION ,
329
+ } ) ;
320
330
} else {
321
331
this . configurationTokenStore . delete ( name ) ;
322
332
}
0 commit comments