Skip to content

Commit ef172ce

Browse files
Todd AndersonTodd Anderson
authored andcommitted
feat: falls back to FDv1 polling if flag delivery sends fallback header
1 parent aee6479 commit ef172ce

25 files changed

+341
-58
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
"packageManager": "[email protected]",
6767
"//": "Pin jsonc-parser because v3.3.0 breaks rollup-plugin-esbuild",
6868
"resolutions": {
69-
"jsonc-parser": "3.2.0"
69+
"jsonc-parser": "3.2.0",
70+
"parse5": "7.2.1"
7071
}
7172
}

packages/sdk/server-node/__tests__/LDClientNode.proxy.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ describe('When using a proxy', () => {
3838
it('can use proxy in polling mode', async () => {
3939
const proxy = await TestHttpServer.startProxy();
4040
const server = await TestHttpServer.start();
41-
server.forMethodAndPath('get', '/sdk/latest-all', TestHttpHandlers.respondJson(allData));
41+
server.forMethodAndPath('get', '/sdk/poll', TestHttpHandlers.respondJson(allData));
4242

4343
const client = new LDClientNode(sdkKey, {
4444
baseUri: server.url,
@@ -67,7 +67,7 @@ describe('When using a proxy', () => {
6767
const server = await TestHttpServer.start();
6868
const events = new AsyncQueue<SSEItem>();
6969
events.add({ type: 'put', data: JSON.stringify({ data: allData }) });
70-
server.forMethodAndPath('get', '/all', TestHttpHandlers.sseStream(events));
70+
server.forMethodAndPath('get', '/sdk/stream', TestHttpHandlers.sseStream(events));
7171

7272
const client = new LDClientNode(sdkKey, {
7373
streamUri: server.url,
@@ -94,7 +94,7 @@ describe('When using a proxy', () => {
9494
const proxy = await TestHttpServer.startProxy();
9595
const pollingServer = await TestHttpServer.start();
9696
const eventsServer = await TestHttpServer.start();
97-
pollingServer.forMethodAndPath('get', '/sdk/latest-all', TestHttpHandlers.respondJson(allData));
97+
pollingServer.forMethodAndPath('get', '/sdk/poll', TestHttpHandlers.respondJson(allData));
9898
eventsServer.forMethodAndPath('post', '/diagnostic', TestHttpHandlers.respond(200));
9999

100100
const client = new LDClientNode(sdkKey, {

packages/sdk/server-node/__tests__/LDClientNode.tls.test.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ describe('When using a TLS connection', () => {
2626

2727
it('can connect via HTTPS to a server with a self-signed certificate, if CA is specified', async () => {
2828
server = await TestHttpServer.startSecure();
29-
server.forMethodAndPath('get', '/sdk/latest-all', TestHttpHandlers.respondJson({}));
29+
server.forMethodAndPath('get', '/sdk/poll', TestHttpHandlers.respondJson({}));
3030

3131
client = new LDClientNode('sdk-key', {
3232
baseUri: server.url,
@@ -41,7 +41,7 @@ describe('When using a TLS connection', () => {
4141

4242
it('cannot connect via HTTPS to a server with a self-signed certificate, using default config', async () => {
4343
server = await TestHttpServer.startSecure();
44-
server.forMethodAndPath('get', '/sdk/latest-all', TestHttpHandlers.respondJson({}));
44+
server.forMethodAndPath('get', '/sdk/poll', TestHttpHandlers.respondJson({}));
4545

4646
client = new LDClientNode('sdk-key', {
4747
baseUri: server.url,
@@ -64,7 +64,7 @@ describe('When using a TLS connection', () => {
6464
const events = new AsyncQueue<SSEItem>();
6565
events.add({ type: 'put', data: JSON.stringify(eventData) });
6666
server = await TestHttpServer.startSecure();
67-
server.forMethodAndPath('get', '/stream/all', TestHttpHandlers.sseStream(events));
67+
server.forMethodAndPath('get', '/stream/sdk/stream', TestHttpHandlers.sseStream(events));
6868

6969
client = new LDClientNode('sdk-key', {
7070
baseUri: server.url,
@@ -83,7 +83,7 @@ describe('When using a TLS connection', () => {
8383
it('can use custom TLS options for posting events', async () => {
8484
server = await TestHttpServer.startSecure();
8585
server.forMethodAndPath('post', '/events/bulk', TestHttpHandlers.respond(200));
86-
server.forMethodAndPath('get', '/sdk/latest-all', TestHttpHandlers.respondJson({}));
86+
server.forMethodAndPath('get', '/sdk/poll', TestHttpHandlers.respondJson({}));
8787

8888
client = new LDClientNode('sdk-key', {
8989
baseUri: server.url,
@@ -99,7 +99,7 @@ describe('When using a TLS connection', () => {
9999
await client.flush();
100100

101101
const flagsRequest = await server.nextRequest();
102-
expect(flagsRequest.path).toEqual('/sdk/latest-all');
102+
expect(flagsRequest.path).toEqual('/sdk/poll');
103103

104104
const eventsRequest = await server.nextRequest();
105105
expect(eventsRequest.path).toEqual('/events/bulk');

packages/sdk/server-node/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
"dependencies": {
4848
"@launchdarkly/js-server-sdk-common": "2.10.0",
4949
"https-proxy-agent": "^5.0.1",
50-
"launchdarkly-eventsource": "2.0.3"
50+
"launchdarkly-eventsource": "2.2.0"
5151
},
5252
"devDependencies": {
5353
"@trivago/prettier-plugin-sort-imports": "^4.1.1",

packages/shared/common/__tests__/internal/fdv2/PayloadStreamReader.test.ts

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { EventListener, EventName, LDLogger } from '../../../src/api';
22
import { Payload } from '../../../src/internal/fdv2/payloadProcessor';
33
import { EventStream, PayloadStreamReader } from '../../../src/internal/fdv2/payloadStreamReader';
44

5-
65
class MockEventStream implements EventStream {
76
private _listeners: Record<EventName, EventListener> = {};
87

@@ -26,7 +25,7 @@ it('it sets basis to true when intent code is xfer-full', () => {
2625
});
2726

2827
mockStream.simulateEvent('server-intent', {
29-
data: '{"payloads": [{"code": "xfer-full", "id": "mockId"}]}',
28+
data: '{"payloads": [{"intentCode": "xfer-full", "id": "mockId"}]}',
3029
});
3130
mockStream.simulateEvent('payload-transferred', {
3231
data: '{"state": "mockState", "version": 1}',
@@ -48,7 +47,7 @@ it('it sets basis to false when intent code is xfer-changes', () => {
4847
});
4948

5049
mockStream.simulateEvent('server-intent', {
51-
data: '{"payloads": [{"code": "xfer-changes", "id": "mockId"}]}',
50+
data: '{"payloads": [{"intentCode": "xfer-changes", "id": "mockId"}]}',
5251
});
5352
mockStream.simulateEvent('payload-transferred', {
5453
data: '{"state": "mockState", "version": 1}',
@@ -70,7 +69,7 @@ it('it sets basis to false and emits empty payload when intent code is none', ()
7069
});
7170

7271
mockStream.simulateEvent('server-intent', {
73-
data: '{"payloads": [{"code": "none", "id": "mockId", "target": 42}]}',
72+
data: '{"payloads": [{"intentCode": "none", "id": "mockId", "target": 42}]}',
7473
});
7574
expect(receivedPayloads.length).toEqual(1);
7675
expect(receivedPayloads[0].id).toEqual('mockId');
@@ -89,7 +88,7 @@ it('it handles xfer-full then xfer-changes', () => {
8988
});
9089

9190
mockStream.simulateEvent('server-intent', {
92-
data: '{"payloads": [{"code": "xfer-full", "id": "mockId"}]}',
91+
data: '{"payloads": [{"intentCode": "xfer-full", "id": "mockId"}]}',
9392
});
9493
mockStream.simulateEvent('put-object', {
9594
data: '{"kind": "mockKind", "key": "flagA", "version": 123, "object": {"objectFieldA": "objectValueA"}}',
@@ -131,7 +130,7 @@ it('it includes multiple types of updates in payload', () => {
131130
});
132131

133132
mockStream.simulateEvent('server-intent', {
134-
data: '{"payloads": [{"code": "xfer-full", "id": "mockId"}]}',
133+
data: '{"payloads": [{"intentCode": "xfer-full", "id": "mockId"}]}',
135134
});
136135
mockStream.simulateEvent('put-object', {
137136
data: '{"kind": "mockKind", "key": "flagA", "version": 123, "object": {"objectFieldA": "objectValueA"}}',
@@ -172,7 +171,7 @@ it('it does not include messages thats are not between server-intent and payload
172171
data: '{"kind": "mockKind", "key": "flagShouldIgnore", "version": 123, "object": {"objectFieldShouldIgnore": "objectValueShouldIgnore"}}',
173172
});
174173
mockStream.simulateEvent('server-intent', {
175-
data: '{"payloads": [{"code": "xfer-full", "id": "mockId"}]}',
174+
data: '{"payloads": [{"intentCode": "xfer-full", "id": "mockId"}]}',
176175
});
177176
mockStream.simulateEvent('put-object', {
178177
data: '{"kind": "mockKind", "key": "flagA", "version": 123, "object": {"objectFieldA": "objectValueA"}}',
@@ -238,7 +237,7 @@ it('logs prescribed message when error event is encountered', () => {
238237
});
239238

240239
mockStream.simulateEvent('server-intent', {
241-
data: '{"payloads": [{"code": "xfer-full", "id": "mockId"}]}',
240+
data: '{"payloads": [{"intentCode": "xfer-full", "id": "mockId"}]}',
242241
});
243242
mockStream.simulateEvent('put-object', {
244243
data: '{"kind": "mockKind", "key": "flagA", "version": 123, "object": {"objectFieldA": "objectValueA"}}',
@@ -280,7 +279,7 @@ it('discards partially transferred data when an error is encountered', () => {
280279
});
281280

282281
mockStream.simulateEvent('server-intent', {
283-
data: '{"payloads": [{"code": "xfer-full", "id": "mockId"}]}',
282+
data: '{"payloads": [{"intentCode": "xfer-full", "id": "mockId"}]}',
284283
});
285284
mockStream.simulateEvent('put-object', {
286285
data: '{"kind": "mockKind", "key": "flagA", "version": 123, "object": {"objectFieldA": "objectValueA"}}',
@@ -295,7 +294,7 @@ it('discards partially transferred data when an error is encountered', () => {
295294
data: '{"state": "mockState", "version": 1}',
296295
});
297296
mockStream.simulateEvent('server-intent', {
298-
data: '{"payloads": [{"code": "xfer-full", "id": "mockId2"}]}',
297+
data: '{"payloads": [{"intentCode": "xfer-full", "id": "mockId2"}]}',
299298
});
300299
mockStream.simulateEvent('put-object', {
301300
data: '{"kind": "mockKind", "key": "flagX", "version": 123, "object": {"objectFieldX": "objectValueX"}}',
@@ -339,7 +338,7 @@ it('silently ignores unrecognized kinds', () => {
339338
});
340339

341340
mockStream.simulateEvent('server-intent', {
342-
data: '{"payloads": [{"code": "xfer-full", "id": "mockId"}]}',
341+
data: '{"payloads": [{"intentCode": "xfer-full", "id": "mockId"}]}',
343342
});
344343
mockStream.simulateEvent('put-object', {
345344
data: '{"kind": "mockKind", "key": "flagA", "version": 123, "object": {"objectFieldA": "objectValueA"}}',
@@ -369,7 +368,7 @@ it('ignores additional payloads beyond the first payload in the server-intent me
369368
});
370369

371370
mockStream.simulateEvent('server-intent', {
372-
data: '{"payloads": [{"code": "xfer-full", "id": "mockId"},{"code": "IShouldBeIgnored", "id": "IShouldBeIgnored"}]}',
371+
data: '{"payloads": [{"intentCode": "xfer-full", "id": "mockId"},{"intentCode": "IShouldBeIgnored", "id": "IShouldBeIgnored"}]}',
373372
});
374373
mockStream.simulateEvent('put-object', {
375374
data: '{"kind": "mockKind", "key": "flagA", "version": 123, "object": {"objectFieldA": "objectValueA"}}',

packages/shared/common/__tests__/options/ServiceEndpoints.test.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,14 @@ it('applies payload filter to polling and streaming endpoints', () => {
4949
'filterKey',
5050
);
5151

52-
expect(getStreamingUri(endpoints, '/all', [])).toEqual(
53-
'https://stream.launchdarkly.com/all?filter=filterKey',
52+
expect(getStreamingUri(endpoints, '/sdk/stream', [])).toEqual(
53+
'https://stream.launchdarkly.com/sdk/stream?filter=filterKey',
5454
);
55-
expect(getPollingUri(endpoints, '/sdk/latest-all', [])).toEqual(
56-
'https://sdk.launchdarkly.com/sdk/latest-all?filter=filterKey',
55+
expect(getPollingUri(endpoints, '/sdk/poll', [])).toEqual(
56+
'https://sdk.launchdarkly.com/sdk/poll?filter=filterKey',
5757
);
5858
expect(
59-
getPollingUri(endpoints, '/sdk/latest-all', [{ key: 'withReasons', value: 'true' }]),
60-
).toEqual('https://sdk.launchdarkly.com/sdk/latest-all?withReasons=true&filter=filterKey');
59+
getPollingUri(endpoints, '/sdk/poll', [{ key: 'withReasons', value: 'true' }]),
60+
).toEqual('https://sdk.launchdarkly.com/sdk/poll?withReasons=true&filter=filterKey');
6161
expect(getEventsUri(endpoints, '/bulk', [])).toEqual('https://events.launchdarkly.com/bulk');
6262
});

0 commit comments

Comments
 (0)