Skip to content

Commit

Permalink
Improved SnapshotAutoUpdater schedule def (#51)
Browse files Browse the repository at this point in the history
  • Loading branch information
petruki committed Feb 28, 2024
1 parent 9791d5d commit 56b90ca
Show file tree
Hide file tree
Showing 10 changed files with 105 additions and 37 deletions.
6 changes: 3 additions & 3 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ A clear and concise description of what you expected to happen.
- Deno version: e.g. (use deno --version)

```
deno 1.22.2 (release, x86_64-pc-windows-msvc)
v8 10.3.174.6
typescript 4.6.2
deno 1.41.0 (release, x86_64-pc-windows-msvc)
v8 12.1.285.27
typescript 5.3.3
```

**Additional context**
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ The context properties stores all information regarding connectivity.

> Initialization
```ts
import { Switcher } from "https://deno.land/x/switcher4deno@v1.0.2/mod.ts";
import { Switcher } from "https://deno.land/x/switcher4deno@v[VERSION]/mod.ts";

const url = 'https://switcherapi.com/api';
const url = 'https://api.switcherapi.com';
const apiKey = '[API_KEY]';
const environment = 'default';
const domain = 'My Domain';
Expand Down
7 changes: 6 additions & 1 deletion deno.jsonc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@switcherapi/switcher-client-deno",
"version": "1.0.7",
"description": "A Deno SDK for Switcher API",
"description": "Switcher4Deno is a Feature Flag Deno SDK client for Switcher API",
"tasks": {
"cache-reload": "deno cache --reload --lock=deno.lock --lock-write mod.ts",
"fmt": "deno fmt mod.ts src/ --options-single-quote --options-line-width=120 --check",
Expand All @@ -10,5 +10,10 @@
"lcov": "deno coverage coverage --lcov --output=coverage/report.lcov",
"clean": "rm -rf ./npm ./coverage ./generated-snapshots",
"cover": "deno task clean && deno task test && deno task lcov && genhtml -o coverage/html coverage/report.lcov"
},
"test": {
"include": [
"test/**/*.ts"
]
}
}
7 changes: 7 additions & 0 deletions snapshot/local.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"data": {
"domain": {
"version": 0
}
}
}
10 changes: 10 additions & 0 deletions src/lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,13 @@ export const DEFAULT_LOGGER = false;
export const DEFAULT_TEST_MODE = false;
export const DEFAULT_REGEX_MAX_BLACKLISTED = 50;
export const DEFAULT_REGEX_MAX_TIME_LIMIT = 3000;

export enum SWITCHER_OPTIONS {
SNAPSHOT_LOCATION = 'snapshotLocation',
SNAPSHOT_AUTO_UPDATE_INTERVAL = 'snapshotAutoUpdateInterval',
SILENT_MODE = 'silentMode',
REGEX_SAFE = 'regexSafe',
REGEX_MAX_BLACK_LIST = 'regexMaxBlackList',
REGEX_MAX_TIME_LIMIT = 'regexMaxTimeLimit',
CERT_PATH = 'certPath',
}
22 changes: 9 additions & 13 deletions src/lib/utils/snapshotAutoUpdater.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,28 @@
export default class SnapshotAutoUpdater {
static _worker: number | undefined;
private static _intervalId: number | undefined;

static schedule(
interval: number,
checkSnapshot: () => Promise<boolean>,
success?: (updated: boolean) => void,
reject?: (err: Error) => void,
success: (updated: boolean) => void = () => {},
reject: (err: Error) => void = () => {},
) {
if (this._worker) {
if (this._intervalId) {
this.terminate();
}

this._worker = setInterval(async () => {
this._intervalId = setInterval(async () => {
try {
const updated = await checkSnapshot();
if (success) {
success(updated);
}
success(updated);
} catch (err) {
if (reject) {
this.terminate();
reject(err);
}
this.terminate();
reject(err);
}
}, interval * 1000);
}

static terminate() {
clearInterval(this._worker);
clearInterval(this._intervalId);
}
}
16 changes: 8 additions & 8 deletions src/switcher-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
DEFAULT_REGEX_MAX_BLACKLISTED,
DEFAULT_REGEX_MAX_TIME_LIMIT,
DEFAULT_TEST_MODE,
SWITCHER_OPTIONS,
} from './lib/constants.ts';

/**
Expand Down Expand Up @@ -69,15 +70,15 @@ export class Switcher {
}

private static buildOptions(options: SwitcherOptions) {
if ('certPath' in options && options.certPath) {
if (SWITCHER_OPTIONS.CERT_PATH in options && options.certPath) {
services.setCerts(options.certPath);
}

if ('silentMode' in options && options.silentMode) {
if (SWITCHER_OPTIONS.SILENT_MODE in options && options.silentMode) {
this._initSilentMode(options.silentMode);
}

if ('snapshotAutoUpdateInterval' in options) {
if (SWITCHER_OPTIONS.SNAPSHOT_AUTO_UPDATE_INTERVAL in options) {
this._options.snapshotAutoUpdateInterval = options.snapshotAutoUpdateInterval;
this.scheduleSnapshotAutoUpdate();
}
Expand Down Expand Up @@ -296,15 +297,15 @@ export class Switcher {
}

private static _initTimedMatch(options: SwitcherOptions) {
if ('regexMaxBlackList' in options) {
if (SWITCHER_OPTIONS.REGEX_MAX_BLACK_LIST in options) {
TimedMatch.setMaxBlackListed(options.regexMaxBlackList || DEFAULT_REGEX_MAX_BLACKLISTED);
}

if ('regexMaxTimeLimit' in options) {
if (SWITCHER_OPTIONS.REGEX_MAX_TIME_LIMIT in options) {
TimedMatch.setMaxTimeLimit(options.regexMaxTimeLimit || DEFAULT_REGEX_MAX_TIME_LIMIT);
}

const hasRegexSafeOption = 'regexSafe' in options;
const hasRegexSafeOption = SWITCHER_OPTIONS.REGEX_SAFE in options;
if (!hasRegexSafeOption || (hasRegexSafeOption && options.regexSafe)) {
TimedMatch.initializeWorker();
}
Expand Down Expand Up @@ -572,8 +573,7 @@ export class Switcher {
}

_useSync() {
return this._delay == 0 ||
!ExecutionLogger.getExecution(this._key, this._input);
return this._delay == 0 || !ExecutionLogger.getExecution(this._key, this._input);
}

get key() {
Expand Down
44 changes: 36 additions & 8 deletions test/playground/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const apiKey = 'JDJiJDA4JEFweTZjSTR2bE9pUjNJOUYvRy9raC4vRS80Q2tzUnk1d3o1aXFmS2o5
const domain = 'Playground';
const component = 'switcher-playground';
const environment = 'default';
const url = 'https://switcherapi.com/api';
const url = 'https://api.switcherapi.com';
const snapshotLocation = './snapshot/';

let switcher: Switcher;
Expand All @@ -15,11 +15,39 @@ let switcher: Switcher;
*/
async function setupSwitcher(local: boolean) {
Switcher.buildContext({ url, apiKey, domain, component, environment }, { local, logger: true });
await Switcher.loadSnapshot(false, true)
.then(() => console.log('Snapshot loaded'))
await Switcher.loadSnapshot(false, local)
.then(version => console.log('Snapshot loaded - version:', version))
.catch(() => console.log('Failed to load Snapshot'));
}

/**
* This code snippet is a minimal example of how to configure and use Switcher4Deno locally.
* No remote API account is required.
*
* Snapshot is loaded from file at test/playground/snapshot/local.json
*/
const _testLocal = async () => {
Switcher.buildContext({
domain: 'Local Playground',
environment: 'local'
}, {
snapshotLocation: './snapshot/',
local: true
});

await Switcher.loadSnapshot()
.then(version => console.log('Snapshot loaded - version:', version))
.catch(() => console.log('Failed to load Snapshot'));

switcher = Switcher.factory();

setInterval(async () => {
const time = Date.now();
const result = await switcher.isItOn(SWITCHER_KEY);
console.log(`- ${Date.now() - time} ms - ${result}`);
}, 1000);
};

// Requires remote API
const _testSimpleAPICall = async (local: boolean) => {
await setupSwitcher(local);
Expand All @@ -30,12 +58,11 @@ const _testSimpleAPICall = async (local: boolean) => {

switcher = Switcher.factory();

while(true) {
setInterval(async () => {
const time = Date.now();
const result = await switcher.isItOn(SWITCHER_KEY);
console.log(`- ${Date.now() - time} ms - ${result}`);
await new Promise(resolve => setTimeout(resolve, 1000));
}
}, 1000);
};

// Requires remote API
Expand All @@ -47,8 +74,9 @@ const _testThrottledAPICall = async () => {
switcher = Switcher.factory();
switcher.throttle(1000);

for (let index = 0; index < 10; index++)
for (let index = 0; index < 10; index++) {
console.log(`Call #${index} - ${await switcher.isItOn(SWITCHER_KEY, [checkNumeric('1')])}}`);
}

Switcher.unloadSnapshot();
};
Expand Down Expand Up @@ -129,4 +157,4 @@ const _testSnapshotAutoUpdate = async () => {
}, 2000);
};

_testSimpleAPICall(true);
_testLocal();
4 changes: 2 additions & 2 deletions test/playground/snapshot/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"data": {
"domain": {
"name": "Playground",
"version": 1656648899029,
"version": 1,
"activated": true,
"group": [
{
Expand All @@ -15,7 +15,7 @@
"strategies": [
{
"strategy": "VALUE_VALIDATION",
"activated": true,
"activated": false,
"operation": "EXIST",
"values": [
"user_1"
Expand Down
22 changes: 22 additions & 0 deletions test/playground/snapshot/local.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"data": {
"domain": {
"name": "Local Playground",
"version": 1,
"activated": true,
"group": [
{
"name": "My Features",
"activated": true,
"config": [
{
"key": "MY_SWITCHER",
"activated": true,
"strategies": []
}
]
}
]
}
}
}

0 comments on commit 56b90ca

Please sign in to comment.