Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/react18/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"typescript": "^4.4.2",
"typescript": "^5.8.3",
"web-vitals": "^2.1.0"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
"rollup": "^4.22.4",
"rollup-plugin-dts": "^6.1.1",
"ts-jest": "^29.1.0",
"typescript": "^5.1.3"
"typescript": "^5.8.3"
},
"config": {
"commitizen": {
Expand Down
2 changes: 1 addition & 1 deletion packages/openfeature-server-provider/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"@openfeature/server-sdk": "^1.13.5",
"@spotify-confidence/sdk": "workspace:*",
"rollup": "4.24.0",
"typescript": "5.1.6"
"typescript": "^5.8.3"
},
"peerDependencies": {
"@openfeature/server-sdk": "^1.13.5",
Expand Down
2 changes: 1 addition & 1 deletion packages/openfeature-web-provider/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"@openfeature/web-sdk": "^1.0.3",
"@spotify-confidence/sdk": "workspace:*",
"rollup": "4.24.0",
"typescript": "5.1.6"
"typescript": "^5.8.3"
},
"peerDependencies": {
"@openfeature/web-sdk": "^1.0.3",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ describe('ConfidenceWebProvider E2E tests', () => {
errorCode: 'GENERAL',
flagKey: 'web-sdk-e2e-flag.str',
flagMetadata: {},
errorMessage: 'Resolve timeout',
errorMessage: 'The operation was aborted due to timeout',
reason: 'ERROR',
value: 'default',
});
Expand Down
2 changes: 1 addition & 1 deletion packages/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"@types/react": "^18",
"react": "^19",
"rollup": "4.24.0",
"typescript": "5.1.6"
"typescript": "^5.8.3"
},
"exports": {
".": {
Expand Down
2 changes: 1 addition & 1 deletion packages/sdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"prettier": "*",
"rollup": "4.24.0",
"ts-proto": "^2.3.0",
"typescript": "5.1.6"
"typescript": "^5.8.3"
},
"publishConfig": {
"registry": "https://registry.npmjs.org/",
Expand Down
2 changes: 1 addition & 1 deletion packages/sdk/src/FlagResolverClient.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ describe('Client environment Evaluation', () => {
// This is due the request logic that's only used in the client environment
expect(flagResolution.evaluate('testflag', {})).toEqual({
errorCode: 'TIMEOUT',
errorMessage: 'Resolve timeout',
errorMessage: 'The operation was aborted due to timeout',
reason: 'ERROR',
value: {},
});
Expand Down
27 changes: 6 additions & 21 deletions packages/sdk/src/FlagResolverClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,11 @@ import {
} from './generated/confidence/telemetry/v1/telemetry';
import { Logger } from './logger';
import { WaitUntil } from './types';
import { Signals } from './signals';

const FLAG_PREFIX = 'flags/';
const retryCodes = new Set([408, 502, 503, 504]);

export class ResolveError extends Error {
constructor(public readonly code: FlagEvaluation.ErrorCode, message: string) {
super(message);
}
}
export class PendingResolution<T = FlagResolution> extends AccessiblePromise<T> {
#context: Context;
#controller: AbortController;
Expand Down Expand Up @@ -192,11 +188,7 @@ export class FetchingFlagResolverClient implements FlagResolverClient {
};

return PendingResolution.create(context, signal => {
const signalWithTimeout = withTimeout(
signal,
this.resolveTimeout,
new ResolveError('TIMEOUT', 'Resolve timeout'),
);
const signalWithTimeout = withTimeout(signal, this.resolveTimeout);
const start = performance.now();

return this.cacheReadThrough(context, () => this.resolveFlagsJson(request, signalWithTimeout))
Expand All @@ -207,7 +199,8 @@ export class FetchingFlagResolverClient implements FlagResolverClient {
})
.catch(error => {
const latency = performance.now() - start;
const errorCode: FlagEvaluation.ErrorCode = error instanceof ResolveError ? error.code : 'GENERAL';
const errorCode: FlagEvaluation.ErrorCode =
error instanceof DOMException && error.name == 'TimeoutError' ? 'TIMEOUT' : 'GENERAL';
this.markLatency(latency, errorCode === 'TIMEOUT' ? TraceStatus.STATUS_TIMEOUT : TraceStatus.STATUS_ERROR);
return FlagResolution.failed(context, errorCode, error.message);
});
Expand Down Expand Up @@ -347,16 +340,8 @@ export function withRequestLogic(fetchBuilder: FetchBuilder, logger: Logger) {
.route(url => url.endsWith('flags:apply'), fetchApply);
}

function withTimeout(signal: AbortSignal, timeout: number, reason?: any): AbortSignal {
const controller = new AbortController();
const timeoutId: NodeJS.Timeout | number = setTimeout(() => controller.abort(reason), timeout);
// in Node setTimeout returns an object, with an unref function which will prevent the timeout from keeping the process alive
if (typeof timeoutId === 'object') timeoutId.unref();
signal.addEventListener('abort', () => {
clearTimeout(timeoutId);
controller.abort(signal.reason);
});
return controller.signal;
function withTimeout(signal: AbortSignal, timeout: number): AbortSignal {
return Signals.any([Signals.timeout(timeout), signal]);
}

function resolvablePromise<T = void>(): [
Expand Down
33 changes: 33 additions & 0 deletions packages/sdk/src/signals.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
export namespace Signals {
const anyPolyfill: (typeof AbortSignal)['any'] = signals => {
const controller = new AbortController();
const abort = () => {
controller.abort();
clear();
};
const clear = () => {
signals.forEach(signal => {
signal.removeEventListener('abort', abort);
});
};
for (const signal of signals) {
if (signal.aborted) {
abort();
break;
}
signal.addEventListener('abort', abort);
}
return controller.signal;
};

const timeoutPolyfill: (typeof AbortSignal)['timeout'] = milliseconds => {
const controller = new AbortController();
setTimeout(() => {
controller.abort(new DOMException('signal timed out', 'TimeoutError'));
}, milliseconds);
return controller.signal;
};
Comment on lines +23 to +29
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not contain the "special stuff" we previously had for NodeJS. Will all node version contain the native AbortSignal.timeout?

this

  // in Node setTimeout returns an object, with an unref function which will prevent the timeout from keeping the process alive
  if (typeof timeoutId === 'object') timeoutId.unref();


export const any = typeof AbortSignal.any === 'function' ? AbortSignal.any : anyPolyfill;
export const timeout = typeof AbortSignal.timeout === 'function' ? AbortSignal.timeout : timeoutPolyfill;
}
56 changes: 28 additions & 28 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3737,7 +3737,7 @@ __metadata:
"@openfeature/server-sdk": "npm:^1.13.5"
"@spotify-confidence/sdk": "workspace:*"
rollup: "npm:4.24.0"
typescript: "npm:5.1.6"
typescript: "npm:^5.8.3"
peerDependencies:
"@openfeature/server-sdk": ^1.13.5
"@spotify-confidence/sdk": ">=0.1.4 <0.4.0"
Expand All @@ -3753,7 +3753,7 @@ __metadata:
"@spotify-confidence/sdk": "workspace:*"
fast-deep-equal: "npm:^3.1.3"
rollup: "npm:4.24.0"
typescript: "npm:5.1.6"
typescript: "npm:^5.8.3"
peerDependencies:
"@openfeature/web-sdk": ^1.0.3
"@spotify-confidence/sdk": ">=0.1.4 <0.4.0"
Expand All @@ -3769,7 +3769,7 @@ __metadata:
react: "npm:^19"
rollup: "npm:4.24.0"
server-only: "npm:^0.0.1"
typescript: "npm:5.1.6"
typescript: "npm:^5.8.3"
peerDependencies:
"@spotify-confidence/sdk": ">=0.3.1 <0.4.0"
react: ^18 || ^19
Expand All @@ -3785,7 +3785,7 @@ __metadata:
prettier: "npm:*"
rollup: "npm:4.24.0"
ts-proto: "npm:^2.3.0"
typescript: "npm:5.1.6"
typescript: "npm:^5.8.3"
web-vitals: "npm:^3.5.2"
languageName: unknown
linkType: soft
Expand Down Expand Up @@ -15002,7 +15002,7 @@ __metadata:
react: "npm:^18.2.0"
react-dom: "npm:^18.2.0"
react-scripts: "npm:5.0.1"
typescript: "npm:^4.4.2"
typescript: "npm:^5.8.3"
web-vitals: "npm:^2.1.0"
languageName: unknown
linkType: soft
Expand Down Expand Up @@ -15637,7 +15637,7 @@ __metadata:
rollup: "npm:^4.22.4"
rollup-plugin-dts: "npm:^6.1.1"
ts-jest: "npm:^29.1.0"
typescript: "npm:^5.1.3"
typescript: "npm:^5.8.3"
languageName: unknown
linkType: soft

Expand Down Expand Up @@ -17387,16 +17387,6 @@ __metadata:
languageName: node
linkType: hard

"typescript@npm:5.1.6, typescript@npm:^4.6.4 || ^5.0.0, typescript@npm:^5.1.3":
version: 5.1.6
resolution: "typescript@npm:5.1.6"
bin:
tsc: bin/tsc
tsserver: bin/tsserver
checksum: 10c0/45ac28e2df8365fd28dac42f5d62edfe69a7203d5ec646732cadc04065331f34f9078f81f150fde42ed9754eed6fa3b06a8f3523c40b821e557b727f1992e025
languageName: node
linkType: hard

"typescript@npm:5.4.2":
version: 5.4.2
resolution: "typescript@npm:5.4.2"
Expand All @@ -17407,23 +17397,23 @@ __metadata:
languageName: node
linkType: hard

"typescript@npm:^4.4.2":
version: 4.9.5
resolution: "typescript@npm:4.9.5"
"typescript@npm:^4.6.4 || ^5.0.0":
version: 5.1.6
resolution: "typescript@npm:5.1.6"
bin:
tsc: bin/tsc
tsserver: bin/tsserver
checksum: 10c0/5f6cad2e728a8a063521328e612d7876e12f0d8a8390d3b3aaa452a6a65e24e9ac8ea22beb72a924fd96ea0a49ea63bb4e251fb922b12eedfb7f7a26475e5c56
checksum: 10c0/45ac28e2df8365fd28dac42f5d62edfe69a7203d5ec646732cadc04065331f34f9078f81f150fde42ed9754eed6fa3b06a8f3523c40b821e557b727f1992e025
languageName: node
linkType: hard

"typescript@patch:typescript@npm%3A5.1.6#optional!builtin<compat/typescript>, typescript@patch:typescript@npm%3A^4.6.4 || ^5.0.0#optional!builtin<compat/typescript>, typescript@patch:typescript@npm%3A^5.1.3#optional!builtin<compat/typescript>":
version: 5.1.6
resolution: "typescript@patch:typescript@npm%3A5.1.6#optional!builtin<compat/typescript>::version=5.1.6&hash=5da071"
"typescript@npm:^5.8.3":
version: 5.8.3
resolution: "typescript@npm:5.8.3"
bin:
tsc: bin/tsc
tsserver: bin/tsserver
checksum: 10c0/c2bded58ab897a8341fdbb0c1d92ea2362f498cfffebdc8a529d03e15ea2454142dfbf122dabbd9a5cb79b7123790d27def16e11844887d20636226773ed329a
checksum: 10c0/5f8bb01196e542e64d44db3d16ee0e4063ce4f3e3966df6005f2588e86d91c03e1fb131c2581baf0fb65ee79669eea6e161cd448178986587e9f6844446dbb48
languageName: node
linkType: hard

Expand All @@ -17437,13 +17427,23 @@ __metadata:
languageName: node
linkType: hard

"typescript@patch:typescript@npm%3A^4.4.2#optional!builtin<compat/typescript>":
version: 4.9.5
resolution: "typescript@patch:typescript@npm%3A4.9.5#optional!builtin<compat/typescript>::version=4.9.5&hash=289587"
"typescript@patch:typescript@npm%3A^4.6.4 || ^5.0.0#optional!builtin<compat/typescript>":
version: 5.1.6
resolution: "typescript@patch:typescript@npm%3A5.1.6#optional!builtin<compat/typescript>::version=5.1.6&hash=5da071"
bin:
tsc: bin/tsc
tsserver: bin/tsserver
checksum: 10c0/c2bded58ab897a8341fdbb0c1d92ea2362f498cfffebdc8a529d03e15ea2454142dfbf122dabbd9a5cb79b7123790d27def16e11844887d20636226773ed329a
languageName: node
linkType: hard

"typescript@patch:typescript@npm%3A^5.8.3#optional!builtin<compat/typescript>":
version: 5.8.3
resolution: "typescript@patch:typescript@npm%3A5.8.3#optional!builtin<compat/typescript>::version=5.8.3&hash=d69c25"
bin:
tsc: bin/tsc
tsserver: bin/tsserver
checksum: 10c0/e3333f887c6829dfe0ab6c1dbe0dd1e3e2aeb56c66460cb85c5440c566f900c833d370ca34eb47558c0c69e78ced4bfe09b8f4f98b6de7afed9b84b8d1dd06a1
checksum: 10c0/92ea03509e06598948559ddcdd8a4ae5a7ab475766d5589f1b796f5731b3d631a4c7ddfb86a3bd44d58d10102b132cd4b4994dda9b63e6273c66d77d6a271dbd
languageName: node
linkType: hard

Expand Down
Loading