Skip to content

Commit 5e2b2cb

Browse files
committed
Fix basis.
1 parent a38aee1 commit 5e2b2cb

File tree

4 files changed

+67
-7
lines changed

4 files changed

+67
-7
lines changed

packages/sdk/browser/src/BrowserFDv2DataManager.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ export default class BrowserFDv2DataManager implements DataManager {
130130

131131
// Streaming synchronizer — primary, for live updates.
132132
const streamingEndpoints = endpoints.streaming();
133-
const streamingSyncFactory = (_sg: () => string | undefined) => {
133+
const streamingSyncFactory = (sg: () => string | undefined) => {
134134
const streamUriPath = streamingEndpoints.pathGet(
135135
this._platform.encoding!,
136136
plainContextString,
@@ -140,6 +140,7 @@ export default class BrowserFDv2DataManager implements DataManager {
140140
serviceEndpoints: this._config.serviceEndpoints,
141141
streamUriPath,
142142
parameters: queryParams,
143+
selectorGetter: sg,
143144
headers: this._baseHeaders,
144145
initialRetryDelayMillis: this._config.streamInitialReconnectDelay * 1000,
145146
logger: this._logger,

packages/shared/sdk-client/__tests__/datasource/fdv2/StreamingFDv2Base.test.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,58 @@ it('produces results in order', async () => {
430430
base.close();
431431
});
432432

433+
it('includes basis parameter in stream URI when selectorGetter returns a value', () => {
434+
const mockEventSource = createMockEventSource();
435+
const mockRequests = createMockRequests(mockEventSource);
436+
437+
const base = createBase(mockRequests, logger, {
438+
streamUriPath: '/sdk/stream/eval/ctx',
439+
parameters: [{ key: 'auth', value: 'my-key' }],
440+
selectorGetter: () => '(p:test:1)',
441+
});
442+
base.start();
443+
444+
const uri = mockRequests.createEventSource.mock.calls[0][0];
445+
expect(uri).toContain(`basis=${encodeURIComponent('(p:test:1)')}`);
446+
expect(uri).toContain('auth=my-key');
447+
448+
base.close();
449+
});
450+
451+
it('does not include basis parameter when selectorGetter returns undefined', () => {
452+
const mockEventSource = createMockEventSource();
453+
const mockRequests = createMockRequests(mockEventSource);
454+
455+
const base = createBase(mockRequests, logger, {
456+
streamUriPath: '/sdk/stream/eval/ctx',
457+
parameters: [{ key: 'auth', value: 'my-key' }],
458+
selectorGetter: () => undefined,
459+
});
460+
base.start();
461+
462+
const uri = mockRequests.createEventSource.mock.calls[0][0];
463+
expect(uri).not.toContain('basis');
464+
expect(uri).toContain('auth=my-key');
465+
466+
base.close();
467+
});
468+
469+
it('does not include basis parameter when no selectorGetter is provided', () => {
470+
const mockEventSource = createMockEventSource();
471+
const mockRequests = createMockRequests(mockEventSource);
472+
473+
const base = createBase(mockRequests, logger, {
474+
streamUriPath: '/sdk/stream/eval/ctx',
475+
parameters: [{ key: 'auth', value: 'my-key' }],
476+
});
477+
base.start();
478+
479+
const uri = mockRequests.createEventSource.mock.calls[0][0];
480+
expect(uri).not.toContain('basis');
481+
482+
base.close();
483+
});
484+
433485
it('close is idempotent', () => {
434486
const mockEventSource = createMockEventSource();
435487
const mockRequests = createMockRequests(mockEventSource);

packages/shared/sdk-client/__tests__/datasource/fdv2/streamingTestHelpers.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,13 +114,15 @@ export function createBase(
114114
pingHandler?: PingHandler;
115115
streamUriPath?: string;
116116
parameters?: { key: string; value: string }[];
117+
selectorGetter?: () => string | undefined;
117118
} = {},
118119
) {
119120
return createStreamingBase({
120121
requests: mockRequests as any,
121122
serviceEndpoints,
122123
streamUriPath: options.streamUriPath ?? '/sdk/stream/eval/test-context',
123124
parameters: options.parameters ?? [],
125+
selectorGetter: options.selectorGetter,
124126
headers: baseHeaders,
125127
initialRetryDelayMillis: 1000,
126128
logger,

packages/shared/sdk-client/src/datasource/fdv2/StreamingFDv2Base.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ export function createStreamingBase(config: {
8383
serviceEndpoints: ServiceEndpoints;
8484
streamUriPath: string;
8585
parameters: { key: string; value: string }[];
86+
selectorGetter?: () => string | undefined;
8687
headers: LDHeaders;
8788
initialRetryDelayMillis: number;
8889
logger?: LDLogger;
@@ -95,13 +96,17 @@ export function createStreamingBase(config: {
9596
config.logger,
9697
);
9798

98-
const streamUri = getStreamingUri(
99-
config.serviceEndpoints,
100-
config.streamUriPath,
101-
config.parameters,
102-
);
10399
const headers: { [key: string]: string | string[] } = { ...config.headers };
104100

101+
function buildStreamUri(): string {
102+
const params = [...config.parameters];
103+
const basis = config.selectorGetter?.();
104+
if (basis) {
105+
params.push({ key: 'basis', value: encodeURIComponent(basis) });
106+
}
107+
return getStreamingUri(config.serviceEndpoints, config.streamUriPath, params);
108+
}
109+
105110
let eventSource: EventSource | undefined;
106111
let connectionAttemptStartTime: number | undefined;
107112
let fdv1Fallback = false;
@@ -260,7 +265,7 @@ export function createStreamingBase(config: {
260265

261266
logConnectionAttempt();
262267

263-
const es = config.requests.createEventSource(streamUri, {
268+
const es = config.requests.createEventSource(buildStreamUri(), {
264269
headers,
265270
errorFilter: (error: HttpErrorResponse) => handleError(error),
266271
initialRetryDelayMillis: config.initialRetryDelayMillis,

0 commit comments

Comments
 (0)