Skip to content

Commit 6cf1a3c

Browse files
Merge branch 'devin/1773359647-lazy-load-initialized-warning' into rlamb/persistence-contract-tests
2 parents 8d4e39c + cc44864 commit 6cf1a3c

6 files changed

Lines changed: 70 additions & 7 deletions

File tree

.github/actions/install-boost/action.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ runs:
4343
if: runner.os == 'macOS'
4444
shell: bash
4545
run: |
46-
brew install boost@1.85
47-
echo "BOOST_ROOT=$(brew --prefix boost@1.85)" >> $GITHUB_OUTPUT
46+
brew install boost
47+
echo "BOOST_ROOT=$(brew --prefix boost)" >> $GITHUB_OUTPUT
4848
4949
- name: Determine root
5050
id: determine-root

libs/server-sdk/src/client_impl.cpp

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -186,11 +186,19 @@ AllFlagsState ClientImpl::AllFlagsState(Context const& context,
186186
std::unordered_map<Client::FlagKey, Value> result;
187187

188188
if (!Initialized()) {
189-
LD_LOG(logger_, LogLevel::kWarn)
190-
<< "AllFlagsState() called before client has finished "
191-
"initializing. Data source not available. Returning empty state";
189+
if (data_system_->CanEvaluateWhenNotInitialized()) {
190+
LD_LOG(logger_, LogLevel::kWarn)
191+
<< "AllFlagsState() called before LaunchDarkly client "
192+
"initialization completed; using last known values "
193+
"from data store";
194+
} else {
195+
LD_LOG(logger_, LogLevel::kWarn)
196+
<< "AllFlagsState() called before client has finished "
197+
"initializing. Data source not available. Returning "
198+
"empty state";
192199

193-
return {};
200+
return {};
201+
}
194202
}
195203

196204
AllFlagsStateBuilder builder{options};
@@ -418,7 +426,16 @@ EvaluationDetail<Value> ClientImpl::VariationInternal(
418426
std::optional<enum EvaluationReason::ErrorKind> ClientImpl::PreEvaluationChecks(
419427
Context const& context) const {
420428
if (!Initialized()) {
421-
return EvaluationReason::ErrorKind::kClientNotReady;
429+
if (data_system_->CanEvaluateWhenNotInitialized()) {
430+
LD_LOG(logger_, LogLevel::kWarn)
431+
<< "Evaluation called before LaunchDarkly client "
432+
"initialization completed; using last known values "
433+
"from data store. The $inited key was not found in "
434+
"the store; typically a Relay Proxy or other SDK "
435+
"should set this key.";
436+
} else {
437+
return EvaluationReason::ErrorKind::kClientNotReady;
438+
}
422439
}
423440
if (!context.Valid()) {
424441
return EvaluationReason::ErrorKind::kUserNotSpecified;

libs/server-sdk/src/data_interfaces/system/idata_system.hpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,22 @@ class IDataSystem : public IStore {
2121
*/
2222
virtual void Initialize() = 0;
2323

24+
/**
25+
* @brief Returns true if the data system is capable of serving
26+
* flag evaluations even when Initialized() returns false.
27+
*
28+
* This is the case for Lazy Load (daemon mode), where data can be
29+
* fetched on-demand from the persistent store regardless of whether
30+
* the $inited key has been set. In contrast, Background Sync
31+
* cannot serve evaluations until initial data is received.
32+
*
33+
* When this returns true, the evaluation path should log a warning
34+
* (rather than returning CLIENT_NOT_READY) if Initialized() is false.
35+
*/
36+
[[nodiscard]] virtual bool CanEvaluateWhenNotInitialized() const {
37+
return false;
38+
}
39+
2440
virtual ~IDataSystem() override = default;
2541
IDataSystem(IDataSystem const& item) = delete;
2642
IDataSystem(IDataSystem&& item) = delete;

libs/server-sdk/src/data_systems/lazy_load/lazy_load_system.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ class LazyLoad final : public data_interfaces::IDataSystem {
5858

5959
bool Initialized() const override;
6060

61+
[[nodiscard]] bool CanEvaluateWhenNotInitialized() const override {
62+
return true;
63+
}
64+
6165
// Public for usage in tests.
6266
struct Kinds {
6367
static integrations::FlagKind const Flag;

libs/server-sdk/tests/lazy_load_system_test.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,3 +338,15 @@ TEST_F(LazyLoadTest, InitializeCalledAgainAfterTTL) {
338338
ASSERT_TRUE(lazy_load.Initialized());
339339
}
340340
}
341+
342+
TEST_F(LazyLoadTest, CanEvaluateWhenNotInitialized) {
343+
built::LazyLoadConfig const config{
344+
built::LazyLoadConfig::EvictionPolicy::Disabled,
345+
std::chrono::seconds(10), mock_reader};
346+
347+
data_systems::LazyLoad const lazy_load(logger, config, status_manager);
348+
349+
// LazyLoad can always serve evaluations on demand, even if not
350+
// initialized (i.e. $inited key not found in store).
351+
ASSERT_TRUE(lazy_load.CanEvaluateWhenNotInitialized());
352+
}

vendor/foxy/include/foxy/detail/export_connect_fields.hpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
#include <boost/utility/string_view.hpp>
2020
#include <boost/range/algorithm.hpp>
21+
#include <boost/version.hpp>
2122

2223
#include <type_traits>
2324
#include <array>
@@ -88,6 +89,18 @@ launchdarkly::foxy::detail::export_connect_fields(boost::beast::http::basic_fiel
8889
// iterate the `src` fields, moving any connect headers and the corresponding tokens to the `dst`
8990
// fields
9091
//
92+
// Boost 1.90 removed proxy_authentication_info, proxy_features, and
93+
// proxy_instruction from boost::beast::http::field.
94+
#if BOOST_VERSION >= 109000
95+
auto const hop_by_hops = std::array<http::field, 8>{http::field::connection,
96+
http::field::keep_alive,
97+
http::field::proxy_authenticate,
98+
http::field::proxy_authorization,
99+
http::field::proxy_connection,
100+
http::field::te,
101+
http::field::trailer,
102+
http::field::transfer_encoding};
103+
#else
91104
auto const hop_by_hops = std::array<http::field, 11>{http::field::connection,
92105
http::field::keep_alive,
93106
http::field::proxy_authenticate,
@@ -99,6 +112,7 @@ launchdarkly::foxy::detail::export_connect_fields(boost::beast::http::basic_fiel
99112
http::field::te,
100113
http::field::trailer,
101114
http::field::transfer_encoding};
115+
#endif
102116

103117
auto const is_connect_opt =
104118
[&connect_opts,

0 commit comments

Comments
 (0)