Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add support for conditional event source capabilities. #577

Merged
merged 9 commits into from
Sep 11, 2024
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ jest.mock('../src/platform', () => ({
requests: {
createEventSource: jest.fn(),
fetch: jest.fn(),
getEventSourceCapabilities: jest.fn(),
},
encoding: new PlatformEncoding(),
storage: new PlatformStorage(logger),
Expand Down Expand Up @@ -70,6 +71,7 @@ it('uses correct default diagnostic url', () => {
requests: {
createEventSource: jest.fn(),
fetch: mockedFetch,
getEventSourceCapabilities: jest.fn(),
},
encoding: new PlatformEncoding(),
storage: new PlatformStorage(logger),
Expand Down Expand Up @@ -97,6 +99,7 @@ it('uses correct default analytics event url', async () => {
requests: {
createEventSource: createMockEventSource,
fetch: mockedFetch,
getEventSourceCapabilities: jest.fn(),
},
encoding: new PlatformEncoding(),
storage: new PlatformStorage(logger),
Expand Down Expand Up @@ -128,6 +131,7 @@ it('uses correct default polling url', async () => {
requests: {
createEventSource: jest.fn(),
fetch: mockedFetch,
getEventSourceCapabilities: jest.fn(),
},
encoding: new PlatformEncoding(),
storage: new PlatformStorage(logger),
Expand Down Expand Up @@ -158,6 +162,7 @@ it('uses correct default streaming url', (done) => {
requests: {
createEventSource: mockedCreateEventSource,
fetch: jest.fn(),
getEventSourceCapabilities: jest.fn(),
},
encoding: new PlatformEncoding(),
storage: new PlatformStorage(logger),
Expand Down Expand Up @@ -197,6 +202,7 @@ it('includes authorization header for polling', async () => {
requests: {
createEventSource: jest.fn(),
fetch: mockedFetch,
getEventSourceCapabilities: jest.fn(),
},
encoding: new PlatformEncoding(),
storage: new PlatformStorage(logger),
Expand Down Expand Up @@ -231,6 +237,7 @@ it('includes authorization header for streaming', (done) => {
requests: {
createEventSource: mockedCreateEventSource,
fetch: jest.fn(),
getEventSourceCapabilities: jest.fn(),
},
encoding: new PlatformEncoding(),
storage: new PlatformStorage(logger),
Expand Down
9 changes: 9 additions & 0 deletions packages/sdk/react-native/src/platform/PlatformRequests.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type {
EventName,
EventSource,
EventSourceCapabilities,
EventSourceInitDict,
LDLogger,
Options,
Expand All @@ -21,6 +22,14 @@ export default class PlatformRequests implements Requests {
});
}

getEventSourceCapabilities(): EventSourceCapabilities {
return {
readTimeout: false,
Copy link
Member Author

Choose a reason for hiding this comment

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

It has a timeout, but that is a timeout for the XmlHttpRequest.

Which I think is the duration of the entire request.

headers: true,
customMethod: true,
};
}

fetch(url: string, options?: Options): Promise<Response> {
// @ts-ignore
return fetch(url, options);
Expand Down
9 changes: 9 additions & 0 deletions packages/sdk/server-node/src/platform/NodeRequests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { HttpsProxyAgentOptions } from 'https-proxy-agent';
import { EventSource as LDEventSource } from 'launchdarkly-eventsource';

import {
EventSourceCapabilities,
LDLogger,
LDProxyOptions,
LDTLSOptions,
Expand Down Expand Up @@ -158,6 +159,14 @@ export default class NodeRequests implements platform.Requests {
return new LDEventSource(url, expandedOptions);
}

getEventSourceCapabilities(): EventSourceCapabilities {
return {
readTimeout: true,
headers: true,
customMethod: true,
};
}

usingProxy(): boolean {
return this.hasProxy;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { Headers, NullEventSource } from '@launchdarkly/js-server-sdk-common';
import type {
EventSource,
EventSourceCapabilities,
EventSourceInitDict,
Options,
Requests,
Expand Down Expand Up @@ -41,4 +42,12 @@ export default class EdgeRequests implements Requests {
createEventSource(url: string, eventSourceInitDict: EventSourceInitDict): EventSource {
return new NullEventSource(url, eventSourceInitDict);
}

getEventSourceCapabilities(): EventSourceCapabilities {
return {
readTimeout: false,
headers: false,
customMethod: false,
};
}
}
27 changes: 27 additions & 0 deletions packages/shared/common/src/api/platform/Requests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,38 @@ export interface Options {
timeout?: number;
}

export interface EventSourceCapabilities {
/**
* If true the event source supports read timeouts. A read timeout for an
* event source represents the maximum time between receiving any data.
* If you receive 1 byte, and then a period of time greater than the read
* time out elapses, and you do not receive a second byte, then that would
* cause the event source to timeout.
*
* It is not a timeout for the read of the entire body, which should be
* indefinite.
*/
readTimeout: boolean;

/**
* If true the event source supports customized verbs POST/REPORT instead of
* only the default GET.
*/
customMethod: boolean;

/**
* If true the event source supports setting HTTP headers.
*/
headers: boolean;
}

export interface Requests {
fetch(url: string, options?: Options): Promise<Response>;

createEventSource(url: string, eventSourceInitDict: EventSourceInitDict): EventSource;

getEventSourceCapabilities(): EventSourceCapabilities;

/**
* Returns true if a proxy is configured.
*/
Expand Down
1 change: 1 addition & 0 deletions packages/shared/mocks/src/platform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export const createBasicPlatform = () => ({
requests: {
fetch: jest.fn(),
createEventSource: jest.fn(),
getEventSourceCapabilities: jest.fn(),
},
storage: {
get: jest.fn(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,7 @@ function makeMockPlatform(storage: Storage, crypto: Crypto): Platform {
requests: {
fetch: jest.fn(),
createEventSource: jest.fn(),
getEventSourceCapabilities: jest.fn(),
},
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { waitFor } from '@testing-library/dom';

import {
EventSource,
EventSourceCapabilities,
EventSourceInitDict,
Info,
PlatformData,
Expand Down Expand Up @@ -45,6 +46,13 @@ function makeRequests(): Requests {
createEventSource(_url: string, _eventSourceInitDict: EventSourceInitDict): EventSource {
throw new Error('Function not implemented.');
},
getEventSourceCapabilities(): EventSourceCapabilities {
return {
readTimeout: false,
headers: false,
customMethod: false,
};
},
};
}

Expand Down Expand Up @@ -169,6 +177,13 @@ it('stops polling when stopped', (done) => {
createEventSource(_url: string, _eventSourceInitDict: EventSourceInitDict): EventSource {
throw new Error('Function not implemented.');
},
getEventSourceCapabilities(): EventSourceCapabilities {
return {
readTimeout: false,
headers: false,
customMethod: false,
};
},
};
const dataCallback = jest.fn();
const errorCallback = jest.fn();
Expand Down
9 changes: 9 additions & 0 deletions packages/shared/sdk-server-edge/src/platform/requests.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { NullEventSource } from '@launchdarkly/js-server-sdk-common';
import type {
EventSource,
EventSourceCapabilities,
EventSourceInitDict,
Options,
Requests,
Expand All @@ -16,4 +17,12 @@ export default class EdgeRequests implements Requests {
createEventSource(url: string, eventSourceInitDict: EventSourceInitDict): EventSource {
return new NullEventSource(url, eventSourceInitDict);
}

getEventSourceCapabilities(): EventSourceCapabilities {
return {
readTimeout: false,
headers: false,
customMethod: false,
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ describe('given a requestor', () => {
createEventSource(_url: string, _eventSourceInitDict: EventSourceInitDict): EventSource {
throw new Error('Function not implemented.');
},
getEventSourceCapabilities() {
throw new Error('Function not implemented.');
},
};

requestor = new Requestor(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@ function makePlatform(requestState: RequestState) {
createEventSource(_url: string, _eventSourceInitDict: EventSourceInitDict): EventSource {
throw new Error('Function not implemented.');
},
getEventSourceCapabilities() {
throw new Error('Function not implemented.');
},
};
return {
info,
Expand Down
Loading