Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
8cc95b6
feat: add FDv2 configuration builder
beekld Jun 2, 2026
cdaec02
feat: add FDv1 polling overload to FDv2Builder::FDv1Fallback
beekld Jun 3, 2026
b3690ca
feat: variadic synchronizers, initializers, and per-source endpoint o…
beekld Jun 3, 2026
62709ec
test: update FDv2 URL tests to match refactored signatures
beekld Jun 4, 2026
a39b086
refactor: split FDv1 and FDv2 streaming/polling configs
beekld Jun 4, 2026
9bb657e
refactor: FDv2Builder starts empty; add Default() for spec config
beekld Jun 4, 2026
407bc56
merge: bring in FDv1 fallback TTL changes from #540
beekld Jun 8, 2026
e1a9969
test: adapt new TTL streaming tests to 545's endpoint signature
beekld Jun 8, 2026
c22e53d
merge: pick up retry_after removal from #540
beekld Jun 9, 2026
638babc
merge: pick up FDv1 status translation from #540
beekld Jun 9, 2026
b2eae57
fix: pass status manager to FDv1AdapterSynchronizer
beekld Jun 9, 2026
71c202c
merge: pick up OpenSSL bump from #540
beekld Jun 11, 2026
7afaf7e
merge: pick up #539 squash from #540
beekld Jun 11, 2026
dab36f4
merge: pick up FDv1 source lifecycle fix from #540
beekld Jun 11, 2026
7d01543
merge: pick up FDv1 adapter status sink fix from #540
beekld Jun 11, 2026
d759139
fix: wire FDv1 adapter factories to new private-status-manager API
beekld Jun 11, 2026
937bf4a
merge: pick up shared_ptr/init-error fixes from #540
beekld Jun 12, 2026
1524301
fix: construct FDv1 sources via make_shared for enable_shared_from_this
beekld Jun 12, 2026
15f5d5d
merge: pick up #550 from #540
beekld Jun 12, 2026
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
@@ -1,6 +1,7 @@
#pragma once

#include <launchdarkly/server_side/config/builders/data_system/background_sync_builder.hpp>
#include <launchdarkly/server_side/config/builders/data_system/fdv2_builder.hpp>
#include <launchdarkly/server_side/config/builders/data_system/lazy_load_builder.hpp>
#include <launchdarkly/server_side/config/built/data_system/data_system_config.hpp>

Expand All @@ -13,6 +14,7 @@ class DataSystemBuilder {
DataSystemBuilder();
using BackgroundSync = BackgroundSyncBuilder;
using LazyLoad = LazyLoadBuilder;
using FDv2 = FDv2Builder;

/**
* @brief Alias for Enabled(false).
Expand Down Expand Up @@ -46,10 +48,19 @@ class DataSystemBuilder {
*/
DataSystemBuilder& Method(LazyLoad lazy_load);

/**
* @brief Configures the FDv2 data system, which receives flag delivery
* updates over the new changeset-based protocol with built-in fallback
* and recovery semantics.
* @param fdv2 FDv2 configuration.
* @return Reference to this.
*/
DataSystemBuilder& Method(FDv2 fdv2);

[[nodiscard]] tl::expected<built::DataSystemConfig, Error> Build() const;

private:
std::optional<std::variant<BackgroundSync, LazyLoad>> method_builder_;
std::optional<std::variant<BackgroundSync, LazyLoad, FDv2>> method_builder_;
built::DataSystemConfig config_;
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
#pragma once

#include <launchdarkly/config/shared/builders/data_source_builder.hpp>
#include <launchdarkly/config/shared/sdks.hpp>
#include <launchdarkly/server_side/config/built/data_system/fdv2_config.hpp>

#include <chrono>
#include <optional>
#include <string>

namespace launchdarkly::server_side::config::builders {

class FDv2Builder {
public:
class Streaming {
public:
Streaming& InitialReconnectDelay(std::chrono::milliseconds delay);
Streaming& Filter(std::string filter_key);
Streaming& BaseUrl(std::string base_url);
[[nodiscard]] built::FDv2Config::StreamingConfig Build() const;

private:
std::chrono::milliseconds initial_reconnect_delay_{1000};
std::optional<std::string> filter_key_;
std::optional<std::string> base_url_override_;
};

class Polling {
public:
Polling& PollInterval(std::chrono::seconds interval);
Polling& Filter(std::string filter_key);
Polling& BaseUrl(std::string base_url);
[[nodiscard]] built::FDv2Config::PollingConfig Build() const;

private:
std::chrono::seconds poll_interval_{30};
std::optional<std::string> filter_key_;
std::optional<std::string> base_url_override_;
};

/**
* Constructs a builder with no initializers, no synchronizers, and no
* FDv1 fallback. Use Default() for the spec-recommended configuration.
*/
FDv2Builder();

/**
* @return A builder pre-populated with the spec-recommended initializers,
* synchronizers, and FDv1 fallback. Equivalent to calling
* Initializer(), Synchronizer(), and FDv1Fallback() with the
* standard sources.
*/
static FDv2Builder Default();

/**
* @brief Appends a polling initializer to the initializers list.
* @param source Polling source configuration for the initializer.
* @return Reference to this.
*/
FDv2Builder& Initializer(Polling source);

/**
* @brief Appends a streaming synchronizer to the synchronizers list.
* Order in the list determines preference: the first entry is the
* primary synchronizer, subsequent entries are fallbacks.
* @param source Streaming source configuration.
* @return Reference to this.
*/
FDv2Builder& Synchronizer(Streaming source);

/**
* @brief Appends a polling synchronizer to the synchronizers list. See
* Synchronizer(Streaming) for ordering semantics.
* @param source Polling source configuration.
* @return Reference to this.
*/
FDv2Builder& Synchronizer(Polling source);

using FDv1Streaming =
launchdarkly::config::shared::builders::StreamingBuilder<
launchdarkly::config::shared::ServerSDK>;
using FDv1Polling = launchdarkly::config::shared::builders::PollingBuilder<
launchdarkly::config::shared::ServerSDK>;

/**
* @brief Configures the FDv1 streaming source used as a last-resort
* fallback when the LaunchDarkly service signals (via the
* X-LD-FD-Fallback header) that the SDK should switch to FDv1. The
* fallback reads its endpoint from the top-level ServiceEndpoints; to
* point the fallback at a custom URL, configure ServiceEndpoints
* accordingly.
* @param source FDv1 streaming source configuration.
* @return Reference to this.
*/
FDv2Builder& FDv1Fallback(FDv1Streaming source);

/**
* @brief Configures the FDv1 polling source used as a last-resort
* fallback when the LaunchDarkly service signals (via the
* X-LD-FD-Fallback header) that the SDK should switch to FDv1. The
* fallback reads its endpoint from the top-level ServiceEndpoints; to
* point the fallback at a custom URL, configure ServiceEndpoints
* accordingly.
* @param source FDv1 polling source configuration.
* @return Reference to this.
*/
FDv2Builder& FDv1Fallback(FDv1Polling source);

/**
* @brief Disables the FDv1 fallback. After this call, an FDv1
* fallback directive from the service transitions the SDK to
* OFFLINE rather than reconnecting via FDv1.
* @return Reference to this.
*/
FDv2Builder& DisableFDv1Fallback();

/**
* @brief Sets how long the active synchronizer may remain interrupted
* before the orchestrator falls back to the next-preferred synchronizer.
* @param timeout Duration the synchronizer must be continuously
* interrupted for before fallback fires.
* @return Reference to this.
*/
FDv2Builder& FallbackTimeout(std::chrono::milliseconds timeout);

/**
* @brief Sets how long a fallback synchronizer must run successfully
* before the orchestrator attempts to recover to the primary
* synchronizer.
* @param timeout Duration the fallback synchronizer must run before a
* recovery attempt is made.
* @return Reference to this.
*/
FDv2Builder& RecoveryTimeout(std::chrono::milliseconds timeout);

[[nodiscard]] built::FDv2Config Build() const;

private:
built::FDv2Config config_;
};

} // namespace launchdarkly::server_side::config::builders
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include <launchdarkly/server_side/config/built/data_system/background_sync_config.hpp>
#include <launchdarkly/server_side/config/built/data_system/fdv2_config.hpp>
#include <launchdarkly/server_side/config/built/data_system/lazy_load_config.hpp>

#include <variant>
Expand All @@ -9,7 +10,7 @@ namespace launchdarkly::server_side::config::built {

struct DataSystemConfig {
bool disabled;
std::variant<LazyLoadConfig, BackgroundSyncConfig> system_;
std::variant<LazyLoadConfig, BackgroundSyncConfig, FDv2Config> system_;
};

} // namespace launchdarkly::server_side::config::built
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#pragma once

#include <launchdarkly/config/shared/built/data_source_config.hpp>
#include <launchdarkly/config/shared/sdks.hpp>

#include <chrono>
#include <optional>
#include <string>
#include <variant>
#include <vector>

namespace launchdarkly::server_side::config::built {

struct FDv2Config {
struct StreamingConfig {
std::chrono::milliseconds initial_reconnect_delay;
std::optional<std::string> filter_key;
std::optional<std::string> base_url_override;

friend bool operator==(StreamingConfig const& lhs,
StreamingConfig const& rhs) {
return lhs.initial_reconnect_delay == rhs.initial_reconnect_delay &&
lhs.filter_key == rhs.filter_key &&
lhs.base_url_override == rhs.base_url_override;
}
};

struct PollingConfig {
std::chrono::seconds poll_interval;
std::optional<std::string> filter_key;
std::optional<std::string> base_url_override;

friend bool operator==(PollingConfig const& lhs,
PollingConfig const& rhs) {
return lhs.poll_interval == rhs.poll_interval &&
lhs.filter_key == rhs.filter_key &&
lhs.base_url_override == rhs.base_url_override;
}
};

using FDv1StreamingConfig =
launchdarkly::config::shared::built::StreamingConfig<
launchdarkly::config::shared::ServerSDK>;
using FDv1PollingConfig =
launchdarkly::config::shared::built::PollingConfig<
launchdarkly::config::shared::ServerSDK>;

std::vector<PollingConfig> initializers;
std::vector<std::variant<StreamingConfig, PollingConfig>> synchronizers;
std::optional<std::variant<FDv1StreamingConfig, FDv1PollingConfig>>
fdv1_fallback;
std::chrono::milliseconds fallback_timeout;
std::chrono::milliseconds recovery_timeout;
};

} // namespace launchdarkly::server_side::config::built
5 changes: 5 additions & 0 deletions libs/server-sdk/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ target_sources(${LIBNAME}
config/builders/data_system/background_sync_builder.cpp
config/builders/data_system/bootstrap_builder.cpp
config/builders/data_system/data_system_builder.cpp
config/builders/data_system/fdv2_builder.cpp
config/builders/data_system/lazy_load_builder.cpp
config/builders/data_system/data_destination_builder.cpp
config/builders/big_segments_builder.cpp
Expand Down Expand Up @@ -78,6 +79,10 @@ target_sources(${LIBNAME}
data_systems/fdv2/fdv2_data_system.cpp
data_systems/fdv2/fdv1_adapter_synchronizer.hpp
data_systems/fdv2/fdv1_adapter_synchronizer.cpp
data_systems/fdv2/synchronizer_factories.hpp
data_systems/fdv2/synchronizer_factories.cpp
data_systems/fdv2/initializer_factories.hpp
data_systems/fdv2/initializer_factories.cpp
data_systems/background_sync/sources/streaming/streaming_data_source.hpp
data_systems/background_sync/sources/streaming/streaming_data_source.cpp
data_systems/background_sync/sources/streaming/event_handler.hpp
Expand Down
Loading
Loading