Skip to content

Commit

Permalink
feat: expose if refresh changed state in node sdk (#450)
Browse files Browse the repository at this point in the history
Signed-off-by: Mark Phelps <[email protected]>
  • Loading branch information
markphelps authored Oct 16, 2024
1 parent 0488b13 commit 1f357f8
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 16 deletions.
9 changes: 8 additions & 1 deletion flipt-client-browser/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,16 @@ The `FliptEvaluationClient` class pulls flag state from the Flipt instance at th

To update the flag state, you can call the `refresh` method on the `FliptEvaluationClient` class.

> [!NOTE]
> The `refresh` method returns a boolean indicating whether the flag state changed.
```typescript
// Refresh the flag state
fliptEvaluationClient.refresh();
let changed = await fliptEvaluationClient.refresh();

if (changed) {
// Do something
}
```

## ETag Support
Expand Down
9 changes: 8 additions & 1 deletion flipt-client-node/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,16 @@ This state is pulled from the Flipt instance on instantiation and every `update_

To update the flag state manually, you can call the `refresh` method on the `FliptEvaluationClient` class.

> [!NOTE]
> The `refresh` method returns a boolean indicating whether the flag state changed.
```typescript
// Refresh the flag state
fliptEvaluationClient.refresh();
let changed = await fliptEvaluationClient.refresh();

if (changed) {
// Do something
}
```

## ETag Support
Expand Down
4 changes: 2 additions & 2 deletions flipt-client-node/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion flipt-client-node/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@flipt-io/flipt-client",
"version": "0.10.1",
"version": "0.11.0",
"description": "Flipt Client Evaluation SDK for Node.js",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
41 changes: 30 additions & 11 deletions flipt-client-node/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ export class FliptEvaluationClient {
return resp;
}

if (!resp.ok) {
if (!resp.ok && resp.status !== 304) {
throw new Error(`Failed to fetch data: ${resp.statusText}`);
}

Expand All @@ -99,29 +99,48 @@ export class FliptEvaluationClient {

// handle case if they pass in a custom fetcher that doesn't throw on non-2xx status codes
const resp = await fetcher();
if (!resp.ok && resp.status !== 304) {
if (!resp.ok) {
throw new Error(`Failed to fetch data: ${resp.statusText}`);
}

const data = await resp.json();
const engine = new Engine(namespace);
engine.snapshot(data);
const client = new FliptEvaluationClient(engine, fetcher);

client.storeEtag(resp);
if (options.updateInterval && options.updateInterval > 0) {
client.startAutoRefresh(options.updateInterval * 1000);
}

return client;
}

/**
* Store etag from response for next requests
*/
private storeEtag(resp: Response) {
let etag = resp.headers.get('etag');
if (etag) {
this.etag = etag;
}
}

/**
* Start the auto refresh interval
* @param interval - optional interval in milliseconds
* @returns void
*/
private startAutoRefresh(interval: number = 120_000) {
this.stopAutoRefresh();
this.updateInterval = setInterval(async () => {
await this.refresh();
}, interval);
}

/**
* Stop the auto refresh interval
* @returns void
*/
private stopAutoRefresh() {
if (this.updateInterval) {
clearInterval(this.updateInterval);
Expand All @@ -131,22 +150,22 @@ export class FliptEvaluationClient {

/**
* Refresh the flags snapshot
* @returns void
* @returns {boolean} true if snapshot changed
*/
public async refresh() {
public async refresh(): Promise<boolean> {
const opts = { etag: this.etag };
const resp = await this.fetcher(opts);

if (resp.status === 304) {
let etag = resp.headers.get('etag');
if (etag) {
this.etag = etag;
}
return;
let etag = resp.headers.get('etag');
if (this.etag && this.etag === etag) {
return false;
}

this.storeEtag(resp);

const data = await resp.json();
this.engine.snapshot(data);
return true;
}

/**
Expand Down

0 comments on commit 1f357f8

Please sign in to comment.