Skip to content

Commit 4d77e6b

Browse files
committed
fix: issue where context updates somtimes missed
Signed-off-by: Todd Baert <toddbaert@gmail.com>
1 parent 106f9e8 commit 4d77e6b

File tree

2 files changed

+33
-12
lines changed

2 files changed

+33
-12
lines changed

libs/providers/flagd-web/src/lib/flagd-web-provider.spec.ts

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { CallbackClient, Code, ConnectError, PromiseClient } from '@bufbuild/connect-web';
22
import { Struct } from '@bufbuild/protobuf';
3-
import { Client, ErrorCode, OpenFeature, ProviderEvents, StandardResolutionReasons } from '@openfeature/web-sdk';
3+
import { Client, ErrorCode, JsonValue, OpenFeature, ProviderEvents, StandardResolutionReasons } from '@openfeature/web-sdk';
44
import fetchMock from 'jest-fetch-mock';
55
import { Service } from '../proto/ts/schema/v1/schema_connectweb';
66
import { AnyFlag, EventStreamResponse, ResolveAllResponse } from '../proto/ts/schema/v1/schema_pb';
@@ -105,6 +105,10 @@ class MockPromiseClient implements Partial<PromiseClient<typeof Service>> {
105105
}
106106

107107
describe(FlagdWebProvider.name, () => {
108+
afterEach(() => {
109+
jest.clearAllMocks();
110+
});
111+
108112
describe('resolution functionality', () => {
109113
let client: Client;
110114
beforeAll((done) => {
@@ -126,10 +130,6 @@ describe(FlagdWebProvider.name, () => {
126130
});
127131
});
128132

129-
afterEach(() => {
130-
fetchMock.resetMocks();
131-
});
132-
133133
it(FlagdWebProvider.prototype.resolveBooleanEvaluation.name, async () => {
134134
const details = client.getBooleanDetails(BOOL_FLAG_KEY, false);
135135
expect(details.value).toEqual(BOOL_FLAG_VALUE);
@@ -159,13 +159,14 @@ describe(FlagdWebProvider.name, () => {
159159
});
160160
});
161161

162-
describe('events-enabled', () => {
162+
describe('events', () => {
163163
let client: Client;
164164
let mockCallbackClient: MockCallbackClient;
165+
const mockPromiseClient = new MockPromiseClient() as unknown as PromiseClient<typeof Service>;
166+
const context = { some: 'value' };
165167

166168
beforeEach(() => {
167169
mockCallbackClient = new MockCallbackClient();
168-
const mockPromiseClient = new MockPromiseClient() as unknown as PromiseClient<typeof Service>;
169170
OpenFeature.setProvider(
170171
new FlagdWebProvider(
171172
{ host: 'fake.com', maxRetries: -1 },
@@ -207,6 +208,23 @@ describe(FlagdWebProvider.name, () => {
207208
type: EVENT_CONFIGURATION_CHANGE,
208209
});
209210
});
211+
212+
it('should trigger call to resolveAll with current context', (done) => {
213+
214+
client.addHandler(ProviderEvents.ConfigurationChanged, () => {
215+
try {
216+
expect(mockPromiseClient.resolveAll).toHaveBeenLastCalledWith({context: Struct.fromJson(context as JsonValue)});
217+
done();
218+
} catch(err) {
219+
done(err);
220+
}
221+
});
222+
OpenFeature.setContext(context).then(() => {
223+
mockCallbackClient.mockMessage({
224+
type: EVENT_CONFIGURATION_CHANGE,
225+
});
226+
});
227+
});
210228
});
211229

212230
describe(ProviderEvents.Error, () => {

libs/providers/flagd-web/src/lib/flagd-web-provider.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
FlagValue,
1313
JsonValue,
1414
Logger,
15+
OpenFeature,
1516
Provider,
1617
ProviderEvents,
1718
ResolutionDetails,
@@ -71,7 +72,7 @@ export class FlagdWebProvider implements Provider {
7172
}
7273

7374
async initialize(context: EvaluationContext): Promise<void> {
74-
await this.retryConnect(context);
75+
await this.retryConnect();
7576
}
7677

7778
resolveBooleanEvaluation(flagKey: string, _: boolean): ResolutionDetails<boolean> {
@@ -105,23 +106,25 @@ export class FlagdWebProvider implements Provider {
105106
};
106107
}
107108

108-
private async retryConnect(context: EvaluationContext) {
109+
private async retryConnect() {
109110
this._delayMs = Math.min(this._delayMs * BACK_OFF_MULTIPLIER, this._maxDelay);
110111

111112
return new Promise<void>((resolve) => {
112113
this._callbackClient.eventStream(
113114
{},
114115
(message) => {
116+
// get the context at the time of the message
117+
const currentContext = OpenFeature.getContext();
115118
this._logger?.debug(`${FlagdWebProvider.name}: event received: ${message.type}`);
116119
switch (message.type) {
117120
case EVENT_PROVIDER_READY:
118-
this.fetchAll(context).then(() => {
121+
this.fetchAll(currentContext).then(() => {
119122
this.resetConnectionState();
120123
resolve();
121124
});
122125
return;
123126
case EVENT_CONFIGURATION_CHANGE: {
124-
this.fetchAll(context).then(() => {
127+
this.fetchAll(currentContext).then(() => {
125128
this.events.emit(ProviderEvents.ConfigurationChanged);
126129
});
127130
return;
@@ -132,7 +135,7 @@ export class FlagdWebProvider implements Provider {
132135
this._logger?.error(`${FlagdWebProvider.name}: could not establish connection to flagd`);
133136
if (this._retry < this._maxRetries) {
134137
this._retry++;
135-
setTimeout(() => this.retryConnect(context), this._delayMs);
138+
setTimeout(() => this.retryConnect(), this._delayMs);
136139
} else {
137140
this._logger?.warn(`${FlagdWebProvider.name}: max retries reached`);
138141
this.events.emit(ProviderEvents.Error);

0 commit comments

Comments
 (0)