Skip to content

Commit 82d2730

Browse files
committed
fix: ignore FDv1 fallback directive when FDv1 source is active
1 parent f99f1ad commit 82d2730

2 files changed

Lines changed: 53 additions & 1 deletion

File tree

libs/server-sdk/src/data_systems/fdv2/fdv2_data_system.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,8 @@ void FDv2DataSystem::OnSynchronizerResult(
375375
active_conditions_.reset();
376376
return;
377377
}
378-
if (result.fdv1_fallback) {
378+
if (result.fdv1_fallback &&
379+
!source_manager_.IsCurrentSynchronizerFDv1Fallback()) {
379380
source_manager_.SwitchToFDv1Fallback();
380381
if (source_manager_.AvailableSynchronizerCount() > 0) {
381382
LD_LOG(logger_, LogLevel::kInfo)

libs/server-sdk/tests/fdv2_data_system_test.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1203,6 +1203,57 @@ TEST(FDv2DataSystemTest, InitializerFdv1FlagSwitchesToFdv1Adapter) {
12031203
EXPECT_EQ(1, fdv1_factory_ptr->build_count_);
12041204
}
12051205

1206+
TEST(FDv2DataSystemTest, FDv1SourceSelfDirectiveDoesNotRebuildFDv1) {
1207+
auto logger = MakeNullLogger();
1208+
boost::asio::io_context ioc;
1209+
data_components::DataSourceStatusManager status_manager;
1210+
1211+
// FDv2 source emits a ChangeSet with the directive, switching to the
1212+
// FDv1 fallback.
1213+
auto fdv2_sync =
1214+
std::make_unique<MockSynchronizer>(std::vector<FDv2SourceResult>{[]() {
1215+
FDv2SourceResult r{FDv2SourceResult::ChangeSet{
1216+
data_model::ChangeSet<ChangeSetData>{
1217+
data_model::ChangeSetType::kNone,
1218+
{},
1219+
data_model::Selector{}}}};
1220+
r.fdv1_fallback = true;
1221+
return r;
1222+
}()});
1223+
auto fdv2_factory =
1224+
std::make_unique<OneShotSynchronizerFactory>(std::move(fdv2_sync));
1225+
1226+
// FDv1 source then emits a result also carrying the directive. Once
1227+
// FDv1 is active, the directive is silently ignored and the source is
1228+
// not rebuilt.
1229+
auto fdv1_sync =
1230+
std::make_unique<MockSynchronizer>(std::vector<FDv2SourceResult>{[]() {
1231+
FDv2SourceResult r{
1232+
FDv2SourceResult::Interrupted{FDv2SourceResult::ErrorInfo{
1233+
FDv2SourceResult::ErrorInfo::ErrorKind::kErrorResponse,
1234+
/*status_code=*/418, "self-trigger",
1235+
std::chrono::system_clock::now()}}};
1236+
r.fdv1_fallback = true;
1237+
return r;
1238+
}()});
1239+
auto fdv1_factory =
1240+
std::make_unique<FDv1FallbackOneShotFactory>(std::move(fdv1_sync));
1241+
auto* fdv1_factory_ptr = fdv1_factory.get();
1242+
1243+
std::vector<std::unique_ptr<IFDv2SynchronizerFactory>> synchronizers;
1244+
synchronizers.push_back(std::move(fdv2_factory));
1245+
synchronizers.push_back(std::move(fdv1_factory));
1246+
1247+
FDv2DataSystem ds({}, std::move(synchronizers),
1248+
/*fallback_condition_factory=*/nullptr,
1249+
/*recovery_condition_factory=*/nullptr,
1250+
ioc.get_executor(), &status_manager, logger);
1251+
ds.Initialize();
1252+
ioc.run();
1253+
1254+
EXPECT_EQ(1, fdv1_factory_ptr->build_count_);
1255+
}
1256+
12061257
// ============================================================================
12071258
// Destruction protocol: in-flight orchestration
12081259
// ============================================================================

0 commit comments

Comments
 (0)