Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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 @@ -123,8 +123,8 @@ describe('createPayloadListenerFDv2', () => {
const listener = createPayloadListener(dataSourceUpdates, logger, basisReceived);
listener(fullTransferPayload);

expect(logger.debug).toBeCalledWith(expect.stringMatching(/initializing/i));
expect(dataSourceUpdates.applyChanges).toBeCalledWith(
expect(logger.debug).toHaveBeenCalledWith(expect.stringMatching(/initializing/i));
expect(dataSourceUpdates.applyChanges).toHaveBeenCalledWith(
true,
{
features: {
Expand All @@ -134,7 +134,7 @@ describe('createPayloadListenerFDv2', () => {
segkey: { key: 'segkey', version: 2 },
},
},
basisReceived,
expect.any(Function),
{ environmentId: 'envId' },
'initial',
);
Expand All @@ -144,7 +144,7 @@ describe('createPayloadListenerFDv2', () => {
const listener = createPayloadListener(dataSourceUpdates, logger, basisReceived);
listener(changesTransferPayload);

expect(logger.debug).toBeCalledWith(expect.stringMatching(/updating/i));
expect(logger.debug).toHaveBeenCalledWith(expect.stringMatching(/updating/i));
expect(dataSourceUpdates.applyChanges).toHaveBeenCalledTimes(1);
expect(dataSourceUpdates.applyChanges).toHaveBeenNthCalledWith(
1,
Expand All @@ -168,7 +168,7 @@ describe('createPayloadListenerFDv2', () => {
},
},
},
basisReceived,
expect.any(Function),
{ environmentId: 'envId' },
'changes',
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,30 @@ export type SynchronizerDataSource =
| StreamingDataSourceConfiguration;

/**
* This data source will allow developers to define their own composite data source
* @experimental
* This data source will allow developers to define their own composite data source.
* This is a free-form option and is not subject to any backwards compatibility guarantees or semantic
* versioning.
*
* The following example is roughly equivilent to using the {@link StandardDataSourceOptions} with the default values.
* @example
* ```typescript
* dataSource: {
* dataSourceOptionsType: 'custom',
* initializers: [
* {
* type: 'polling'
* },
* ],
* synchronizers: [
* {
* type: 'streaming',
* },
* {
* type: 'polling',
* }
* ],
* }
*/
export interface CustomDataSourceOptions {
dataSourceOptionsType: 'custom';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,14 @@ export const createPayloadListener =
dataSourceUpdates.applyChanges(
payload.basis,
converted,
basisReceived,
() => {
if (payload.state !== '') {
// NOTE: this is a hack right now. The only condition that we will consider a valid basis
// is when there is a valid selector. Currently, the only data source that does not have a
// valid selector is the file data initializer, which will have a blank selector.
basisReceived();
Copy link
Member

Choose a reason for hiding this comment

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

Would the FDv2 fallback also not have a selector? I may just not know how that part works.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

From my understanding here, the basis can be consumed without a selector, however that would not be considered a successful initialization from this particular initializer. I think this function might not be named correctly here as from the invocation it is simply a success callback (

payloadListener = createPayloadListener(dataSourceUpdates, logger, initSuccess);
). @tanderson-ld thoughts?

Copy link
Contributor

@tanderson-ld tanderson-ld Dec 8, 2025

Choose a reason for hiding this comment

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

I agree there is a bug in the code before this PR as even when payload.basis is false, basisReceived is called.

LDClientImpl is passing in a function called initSuccess. I think at that time I had thought getting a basis (independent of selector) was sufficient to consider it initialized. This would be my thinking at the time since I thought this code path was only hit when basis == true.

Since Casey's requirement is "Basis with a Payload Selector.", should this logic be updated to ensure basis is also true when selector is not null?

The name basisRecieved in basisReceived: VoidFunction = () => {} parameter may need to be adjusted.

}
},
initMetadata,
payload.state,
);
Expand Down