Skip to content

Commit

Permalink
Retrying poller initialization.
Browse files Browse the repository at this point in the history
  • Loading branch information
tarehart committed Jan 6, 2024
1 parent 7d440e5 commit 04c816d
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 6 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
[![npm version][npm-badge]][npm-url]
[![Build Status - GitHub Actions][gha-badge]][gha-ci]

A wrapper around @aws-sdk/client-appconfigdata to provide background polling and caching.
This library polls AWS AppConfig on a background thread so your app has instant access to a cached version of your configuration.
It relies on the official @aws-sdk/client-appconfigdata library to fetch the data.

Although AWS seems to recommend their [simplified retrieval methods](https://docs.aws.amazon.com/appconfig/latest/userguide/appconfig-retrieving-simplified-methods.html) for fetching AppConfig, i.e. running an agent in a separate process, you may prefer to use this library:

- You don't need to set up a lambda extension.
- You easily get parity between your local development server and prod.
- The parsed version of your config is conveniently cached.
- You get convenient reporting of transient errors while the library works in the background to recover.
- You get reporting of transient errors while the library works in the background to recover.

## Usage

Expand Down
42 changes: 42 additions & 0 deletions __tests__/poller.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,4 +180,46 @@ describe('Poller', () => {
standardConfig.configParser(configValue2),
);
});

it('Retries start session if first one fails', async () => {
const configValue = 'worked once';

appConfigClientMock.on(StartConfigurationSessionCommand)
.rejectsOnce({
message: 'Failed to start',
})
.resolves({
InitialConfigurationToken: 'initialToken',
});

appConfigClientMock
.on(GetLatestConfigurationCommand)
.resolves({
Configuration: Uint8ArrayBlobAdapter.fromString(configValue),
});

const dataClient = new AppConfigDataClient();

poller = new Poller({
dataClient: dataClient,
...standardConfig,
});

const initialResponse = await poller.start();
expect(initialResponse.error).toBeDefined();
expect(initialResponse.isInitiallySuccessful).toBeFalsy();

const latest = poller.getConfigurationString();

expect(latest.latestValue).toBeUndefined();
expect(latest.errorCausingStaleValue).toBeUndefined();

await wait(standardConfig.pollIntervalSeconds * 1000 + 100);

const updated = poller.getConfigurationObject();
expect(updated.errorCausingStaleValue).toBeUndefined();
expect(updated.latestValue).toEqual(
standardConfig.configParser(configValue),
);
});
});
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "aws-appconfig-poller",
"version": "0.0.4",
"version": "0.0.5",
"description": "A wrapper around @aws-sdk/client-appconfigdata to provide background polling and caching.",
"repository": {
"type": "git",
Expand Down Expand Up @@ -41,7 +41,7 @@
"test": "jest --coverage",
"prettier": "prettier --config .prettierrc --write .",
"test:watch": "jest --watch",
"infinite": "tsc && node build/examples/infinitePoller.js"
"infinite": "tsc && node dist/examples/infinitePoller.js"
},
"author": "Tyler Arehart <tarehart@users.noreply.github.com>",
"license": "MIT",
Expand Down
6 changes: 4 additions & 2 deletions src/poller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ export interface Outcome {

type PollingPhase = 'ready' | 'starting' | 'active' | 'stopped';

const DEFAULT_POLL_INTERVAL_SECONDS = 60;

export class Poller<T> {
private readonly DEFAULT_POLL_INTERVAL_SECONDS = 60;

private readonly config: PollerConfig<T>;

Expand Down Expand Up @@ -130,6 +131,7 @@ export class Poller<T> {

return await this.fetchLatestConfiguration();
} catch (e) {
this.timeoutHandle = setTimeout(this.startPolling.bind(this), this.config.pollIntervalSeconds || DEFAULT_POLL_INTERVAL_SECONDS)
return {
isInitiallySuccessful: false,
error: e,
Expand Down Expand Up @@ -248,7 +250,7 @@ export class Poller<T> {
return (
this.config.pollIntervalSeconds ||
awsSuggestedSeconds ||
this.DEFAULT_POLL_INTERVAL_SECONDS
DEFAULT_POLL_INTERVAL_SECONDS
);
}
}

0 comments on commit 04c816d

Please sign in to comment.