Repository navigation
feat: Add the FDv2 cache initializer and per-context freshness to the client #613
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
2f07984
c747381
cb4d085
4406211
f45dfd4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| #include "cache_initializer.hpp" | ||
|
|
||
| #include <utility> | ||
|
|
||
| namespace launchdarkly::client_side::data_sources { | ||
|
|
||
| static char const* const kIdentity = "FDv2 cache initializer"; | ||
|
|
||
| FDv2CacheInitializer::FDv2CacheInitializer(flag_manager::FlagPersistence* cache, | ||
| Context context, | ||
| Logger const& logger) | ||
|
Check warning on line 11 in libs/client-sdk/src/data_sources/fdv2/cache_initializer.cpp
|
||
| : cache_(cache), context_(std::move(context)), logger_(logger) {} | ||
|
|
||
| async::Future<FDv2SourceResult> FDv2CacheInitializer::Run() { | ||
| auto data = cache_->ReadCached(context_); | ||
| if (!data) { | ||
| LD_LOG(logger_, LogLevel::kDebug) | ||
| << kIdentity << ": no cached data for this context"; | ||
| // A miss leaves the data set unchanged so initialization can continue. | ||
| return async::MakeFuture(FDv2SourceResult{FDv2SourceResult::ChangeSet{ | ||
| FlagChangeSet{data_model::ChangeSetType::kNone, | ||
| {}, | ||
| data_model::Selector{}}}}); | ||
| } | ||
|
|
||
| LD_LOG(logger_, LogLevel::kDebug) | ||
| << kIdentity << ": loaded " << data->size() | ||
| << " flags for this context"; | ||
|
|
||
| FlagChangeSetData changes; | ||
| changes.reserve(data->size()); | ||
| for (auto& [key, item] : *data) { | ||
| changes.push_back(FlagChange{key, std::move(item)}); | ||
| } | ||
|
|
||
| return async::MakeFuture(FDv2SourceResult{FDv2SourceResult::ChangeSet{ | ||
| FlagChangeSet{data_model::ChangeSetType::kFull, std::move(changes), | ||
| data_model::Selector{}}}}); | ||
| } | ||
|
|
||
| void FDv2CacheInitializer::Close() { | ||
| // Run() completes on the calling thread, so there is nothing to cancel. | ||
| } | ||
|
|
||
| std::string const& FDv2CacheInitializer::Identity() const { | ||
| static std::string const identity = kIdentity; | ||
| return identity; | ||
| } | ||
|
|
||
| FDv2CacheInitializerFactory::FDv2CacheInitializerFactory( | ||
| flag_manager::FlagPersistence* cache, | ||
| Context context, | ||
| Logger const& logger) | ||
|
Check warning on line 53 in libs/client-sdk/src/data_sources/fdv2/cache_initializer.cpp
|
||
| : cache_(cache), context_(std::move(context)), logger_(logger) {} | ||
|
|
||
| std::unique_ptr<IFDv2Initializer> FDv2CacheInitializerFactory::Build() { | ||
| return std::make_unique<FDv2CacheInitializer>(cache_, context_, logger_); | ||
| } | ||
|
|
||
| } // namespace launchdarkly::client_side::data_sources | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| #pragma once | ||
|
|
||
| #include "ifdv2_initializer.hpp" | ||
| #include "ifdv2_initializer_factory.hpp" | ||
|
|
||
| #include "../../flag_manager/flag_persistence.hpp" | ||
|
|
||
| #include <launchdarkly/async/promise.hpp> | ||
| #include <launchdarkly/context.hpp> | ||
| #include <launchdarkly/logging/logger.hpp> | ||
|
|
||
| #include <string> | ||
|
|
||
| namespace launchdarkly::client_side::data_sources { | ||
|
|
||
| /** | ||
| * Loads flag data the SDK persisted for this context on a previous run, so | ||
| * that evaluation can begin before the network answers. | ||
| */ | ||
| class FDv2CacheInitializer final : public IFDv2Initializer { | ||
| public: | ||
| /** | ||
| * @param cache Local cache to read. Non-owning. Must outlive this object. | ||
| * @param context The evaluation context to load data for. | ||
| * @param logger Receives diagnostic logging. | ||
| */ | ||
| FDv2CacheInitializer(flag_manager::FlagPersistence* cache, | ||
| Context context, | ||
| Logger const& logger); | ||
|
|
||
| async::Future<FDv2SourceResult> Run() override; | ||
|
|
||
| void Close() override; | ||
|
|
||
| [[nodiscard]] std::string const& Identity() const override; | ||
|
|
||
| private: | ||
| flag_manager::FlagPersistence* const cache_; | ||
| Context const context_; | ||
| Logger logger_; | ||
| }; | ||
|
|
||
| /** | ||
| * Builds fresh FDv2CacheInitializer instances on demand. | ||
| * | ||
| * Thread-safe: Build() may be called from any thread. | ||
| */ | ||
| class FDv2CacheInitializerFactory final : public IFDv2InitializerFactory { | ||
| public: | ||
| FDv2CacheInitializerFactory(flag_manager::FlagPersistence* cache, | ||
| Context context, | ||
| Logger const& logger); | ||
|
|
||
| std::unique_ptr<IFDv2Initializer> Build() override; | ||
|
|
||
| [[nodiscard]] bool IsFromCache() const override { return true; } | ||
|
|
||
| private: | ||
| flag_manager::FlagPersistence* const cache_; | ||
| Context const context_; | ||
| Logger logger_; | ||
| }; | ||
|
|
||
| } // namespace launchdarkly::client_side::data_sources |
Uh oh!
There was an error while loading. Please reload this page.