Skip to content

Conversation

@joker23
Copy link
Contributor

@joker23 joker23 commented Nov 18, 2025

This PR will introduce file data source initializer for FDv2 that could be specified by adding in an optional intializerOption to the FDv2 datasource option. If this option is not specified then the behavior should not change from before this change.

Additionally:

  • I've added some more type definitions to align better with FDv2 as well as a change set builder to convert FDv1 scheme to FDv2.
  • added a new custom data source options mode that allows users to specify the ordering of their initializers and synchronizers

NOTE: will need to look into a problem where while the initializers are running in expected order, the client initialized event seems to be prematurely firing. Example with the following config:

const ldClient = init(sdkKey, {
  dataSystem: {
    dataSource: {
      dataSourceOptionsType: 'custom',
      initializers: [
      {
        type: 'file',
        paths: [path.resolve(__dirname, 'flagdatav1.json')]
      },
      {
        type: 'polling'
      },
    ],
      synchronizers: [
        {
          type: 'streaming',
          streamInitialReconnectDelay: 1
        }
      ],
    }
  }
});

STDOUT with the sample-feature flag set to false in LD:

fs start
fs stop
polling started
*** SDK successfully initialized!
*** The 'sample-feature' feature flag evaluates to true.
        ██
          ██
      ████████
         ███████
██ LAUNCHDARKLY █
         ███████
      ████████
          ██
        ██

*** Event triggered: update:sample-feature
polling stopped
*** The 'sample-feature' feature flag evaluates to false.
info: [LaunchDarkly] Opened LaunchDarkly stream connection

In the above run, we have the correct ordering where the fs initializer got data, but since it does not report a valid basis, the polling initializer is also being ran. But as you can see, the client reported initialized before the polling initializer was able to update the data to the real thing (but further down we can see that the flag value is being set correctly before the streaming synchronizer runs)

I think this issue could be addressed in a separate change.


Note

Introduce FDv2 file-based initializer and customizable initializer/synchronizer pipeline, plus an adaptor to convert FDv1 payloads to FDv2 and related typing updates.

  • FDv2 core:
    • FDv1→FDv2 adaptor: Add FDv1PayloadAdaptor to build FDv2 change sets from FDv1 payloads; export via internal/fdv2/index.
    • Proto/processor typing: Strengthen proto types (EventType, ObjectKind, etc.); allow empty state in payload-transferred and optional id.
  • SDK server:
    • File initializer: Implement FileDataInitializerFDv2 to load flags/segments from JSON or YAML (optional parser) and emit FDv2 payloads.
    • Polling FDv2: Use FDv1PayloadAdaptor to handle FDv1 responses (selector FDv1Fallback).
    • Custom data source options: Add dataSourceOptionsType: 'custom' with ordered initializers (file/polling) and synchronizers (streaming/polling); wire into LDClientImpl.
    • Config: Export DEFAULT_STREAM_RECONNECT_DELAY; validation accepts custom options.
  • Tests:
    • Add comprehensive tests for FDv1PayloadAdaptor, FileDataInitializerFDv2, and CompositeDataSource multi-initializer behavior.

Written by Cursor Bugbot for commit 718b11a. This will update automatically on new commits. Configure here.

this commit will introduce the implementation of FDv2 File initiator
@joker23 joker23 requested a review from a team as a code owner November 18, 2025 23:08
@joker23 joker23 changed the title Szhang/sdk 1577/f dv2 file initializer feat: add FDv2 FileDataSource initializer Nov 18, 2025
@github-actions
Copy link
Contributor

@launchdarkly/browser size report
This is the brotli compressed size of the ESM build.
Compressed size: 169118 bytes
Compressed size limit: 200000
Uncompressed size: 789399 bytes

@github-actions
Copy link
Contributor

github-actions bot commented Nov 18, 2025

@launchdarkly/js-sdk-common size report
This is the brotli compressed size of the ESM build.
Compressed size: 25833 bytes
Compressed size limit: 26000
Uncompressed size: 126555 bytes

@github-actions
Copy link
Contributor

@launchdarkly/js-client-sdk-common size report
This is the brotli compressed size of the ESM build.
Compressed size: 17636 bytes
Compressed size limit: 20000
Uncompressed size: 90259 bytes

@github-actions
Copy link
Contributor

github-actions bot commented Nov 18, 2025

@launchdarkly/js-client-sdk size report
This is the brotli compressed size of the ESM build.
Compressed size: 22168 bytes
Compressed size limit: 25000
Uncompressed size: 76564 bytes

@joker23 joker23 force-pushed the szhang/sdk-1577/FDv2-file-initializer branch 2 times, most recently from 5d8cadd to cf28ade Compare November 18, 2025 23:20
| DeleteObject
| PayloadTransferred
| GoodbyeObject
| ErrorObject;
Copy link
Contributor

Choose a reason for hiding this comment

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

If new values are added to the protocol, is the code well behaved? Same for nearby types.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yea payload changes will potentially break this, but that is probably true even if we didn't declare these types?

Copy link
Contributor

Choose a reason for hiding this comment

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

Double check logic in the processFDv1FlagsAndSegments in PollingProcessorFDv2 matches this and/or consider commonizing.

Copy link
Contributor Author

@joker23 joker23 Nov 19, 2025

Choose a reason for hiding this comment

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

ah yea the logic is the same! Let me think of a way to merge the logic.

Now that I am thinking about this more, I don't think sdk-common is the right place to create this builder? I am not sure how FDv2 is going to show up for client side implementations so probably move this out to sdk-server then, if we find out that client implementation is similar, move it back out to sdk-common? @abarker-launchdarkly @kinyoklion thoughts?

Otherwise, I think the plan will be change this to a FDv1PayloadAdaptor instead of a builder.

Copy link
Member

Choose a reason for hiding this comment

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

If the data inside the objects is opaque, then the the code itself would likely be the same for both of them.

I am fine with it not being common until we need it though.

A note specifically for internal/common code, but code we intend to use client-side we likely want to avoid classes and do this with functions, as generally speaking they end up smaller when minified. (Or old school function that returns object).

'DataSourceOptions',
typeof options.dataSource,
),
];
Copy link
Contributor

Choose a reason for hiding this comment

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

Should a customer be able to configure to use only a file data source? @kinyoklion thoughts?

I think they should be able to configure just the file data source with polling and streaming disabled, but you'll have to confirm with others on team as I haven't dealt with file data source implementations.

Copy link
Member

Choose a reason for hiding this comment

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

I think we discussed sync, but yeah it should be possible. This would be a typical use case with FDv1. Often times people use file data sources for testing purposes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Okay I think we can have a separate story to handle file synchronizer? I think it would be a fairly trivial implementation on top of this PR.

@joker23 joker23 force-pushed the szhang/sdk-1577/FDv2-file-initializer branch from cf28ade to 15d65d7 Compare November 19, 2025 15:25
@joker23 joker23 force-pushed the szhang/sdk-1577/FDv2-file-initializer branch from 24bee72 to 10363a9 Compare November 19, 2025 21:42
this commit adds a fdv1 payload adaptor to process fdv1 data sets
@joker23 joker23 force-pushed the szhang/sdk-1577/FDv2-file-initializer branch 2 times, most recently from b1b1883 to e1b1349 Compare November 20, 2025 23:05
this enables users to specify file data source initializer
@joker23 joker23 force-pushed the szhang/sdk-1577/FDv2-file-initializer branch from e1b1349 to 718b11a Compare November 20, 2025 23:58
dataCallback(false, { initMetadata, payload });
});

statusCallback(subsystemCommon.DataSourceState.Valid);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@tanderson-ld what does marking the state as valid do exactly? Is this what is telling the client that this initializer is successful?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants