Skip to content

Commit af660a0

Browse files
committed
fix: stop emitting kOff status from FDv2DataSystem destructor
1 parent fafc2bc commit af660a0

3 files changed

Lines changed: 12 additions & 42 deletions

File tree

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ void FDv2DataSystem::Close() {
6868
if (active_conditions_) {
6969
active_conditions_->Close();
7070
}
71-
status_manager_->SetState(DataSourceStatus::DataSourceState::kOff);
7271
}
7372

7473
std::shared_ptr<data_model::FlagDescriptor> FDv2DataSystem::GetFlag(

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

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,8 @@ namespace launchdarkly::server_side::data_systems {
5151
* Destruction protocol:
5252
*
5353
* The destructor cancels in-flight orchestration (closes the active
54-
* source, emits status kOff), but does NOT block to drain executor
55-
* callbacks that may already be queued. Before destroying, the caller
56-
* must ensure both of:
54+
* source) but does NOT block to drain executor callbacks that may
55+
* already be queued. Before destroying, the caller must ensure both of:
5756
*
5857
* 1. The executor that orchestration callbacks run on has been stopped
5958
* AND any thread running it has been joined. Otherwise a previously-
@@ -120,8 +119,6 @@ namespace launchdarkly::server_side::data_systems {
120119
* v
121120
* [Done; final status preserved]
122121
*
123-
* Calling the destructor at any time -> [Closed; status kOff].
124-
*
125122
* Status transitions:
126123
*
127124
* kInitializing (initial) -> kValid on first successful ChangeSet apply.
@@ -130,11 +127,10 @@ namespace launchdarkly::server_side::data_systems {
130127
* the initializer phase if not yet Valid).
131128
* kOff if all initializers exhaust without data
132129
* and no synchronizers are configured.
133-
* kValid -> kInterrupted on errors; kOff in destructor or
134-
* when synchronizers cycle through and exhaust.
130+
* kValid -> kInterrupted on errors; kOff when
131+
* synchronizers cycle through and exhaust.
135132
* kInterrupted -> kValid on next successful ChangeSet apply;
136-
* kOff in destructor or on synchronizer
137-
* exhaustion.
133+
* kOff on synchronizer exhaustion.
138134
* kOff -> terminal.
139135
*/
140136
class FDv2DataSystem final : public data_interfaces::IDataSystem {

libs/server-sdk/tests/fdv2_data_system_test.cpp

Lines changed: 7 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -272,25 +272,6 @@ TEST(FDv2DataSystemTest, OfflineMode_NoFactories_StatusValid) {
272272
EXPECT_FALSE(ds.Initialized());
273273
}
274274

275-
TEST(FDv2DataSystemTest, Destructor_TransitionsStatusToOff) {
276-
auto logger = MakeNullLogger();
277-
boost::asio::io_context ioc;
278-
data_components::DataSourceStatusManager status_manager;
279-
280-
{
281-
FDv2DataSystem ds({}, {}, /*fallback_condition_factory=*/nullptr,
282-
/*recovery_condition_factory=*/nullptr,
283-
ioc.get_executor(), &status_manager, logger);
284-
ds.Initialize();
285-
ASSERT_EQ(status_manager.Status().State(),
286-
DataSourceStatus::DataSourceState::kValid);
287-
}
288-
289-
// After ~FDv2DataSystem, status is Off.
290-
EXPECT_EQ(status_manager.Status().State(),
291-
DataSourceStatus::DataSourceState::kOff);
292-
}
293-
294275
// ============================================================================
295276
// Initializer phase
296277
// ============================================================================
@@ -1227,14 +1208,13 @@ TEST(FDv2DataSystemTest, InitializerFdv1FlagSwitchesToFdv1Adapter) {
12271208
// ============================================================================
12281209
//
12291210
// The destructor contract (fdv2_data_system.hpp) requires the destructor to
1230-
// cancel in-flight orchestration (close the active source, transition status
1231-
// to kOff) without firing any continuation against the destroyed object. The
1232-
// caller's responsibility is to ensure the executor is no longer running by
1233-
// the time destruction begins; the orchestrator's responsibility is to leave
1234-
// nothing dangling. These two tests pin that contract for both phases.
1211+
// cancel in-flight orchestration (close the active source) without firing
1212+
// any continuation against the destroyed object. The caller's responsibility
1213+
// is to ensure the executor is no longer running by the time destruction
1214+
// begins; the orchestrator's responsibility is to leave nothing dangling.
1215+
// These two tests pin that contract for both phases.
12351216

1236-
TEST(FDv2DataSystemTest,
1237-
Destructor_WithInFlightInitializer_ClosesSourceAndStatusOff) {
1217+
TEST(FDv2DataSystemTest, Destructor_WithInFlightInitializer_ClosesSource) {
12381218
auto logger = MakeNullLogger();
12391219
boost::asio::io_context ioc;
12401220
data_components::DataSourceStatusManager status_manager;
@@ -1261,12 +1241,9 @@ TEST(FDv2DataSystemTest,
12611241
// ~FDv2DataSystem ran with the initializer's Future still unresolved.
12621242

12631243
EXPECT_TRUE(initializer_closed);
1264-
EXPECT_EQ(status_manager.Status().State(),
1265-
DataSourceStatus::DataSourceState::kOff);
12661244
}
12671245

1268-
TEST(FDv2DataSystemTest,
1269-
Destructor_WithInFlightSynchronizer_ClosesSourceAndStatusOff) {
1246+
TEST(FDv2DataSystemTest, Destructor_WithInFlightSynchronizer_ClosesSource) {
12701247
auto logger = MakeNullLogger();
12711248
boost::asio::io_context ioc;
12721249
data_components::DataSourceStatusManager status_manager;
@@ -1292,6 +1269,4 @@ TEST(FDv2DataSystemTest,
12921269
}
12931270

12941271
EXPECT_TRUE(synchronizer_closed);
1295-
EXPECT_EQ(status_manager.Status().State(),
1296-
DataSourceStatus::DataSourceState::kOff);
12971272
}

0 commit comments

Comments
 (0)