3 #include "../../../include/launchdarkly/server_side/integrations/data_reader/kinds.hpp"
4 #include "../../data_components/expiration_tracker/expiration_tracker.hpp"
5 #include "../../data_components/memory_store/memory_store.hpp"
6 #include "../../data_components/status_notifications/data_source_status_manager.hpp"
7 #include "../../data_interfaces/source/idata_reader.hpp"
8 #include "../../data_interfaces/system/idata_system.hpp"
10 #include <launchdarkly/server_side/config/built/data_system/lazy_load_config.hpp>
11 #include <launchdarkly/server_side/integrations/data_reader/iserialized_data_reader.hpp>
13 #include <launchdarkly/data_model/descriptors.hpp>
14 #include <launchdarkly/detail/unreachable.hpp>
15 #include <launchdarkly/logging/logger.hpp>
17 namespace launchdarkly::server_side::data_systems {
30 using ClockType = std::chrono::steady_clock;
31 using TimeFn = std::function<std::chrono::time_point<ClockType>()>;
33 explicit LazyLoad(Logger
const& logger,
42 std::string
const&
Identity()
const override;
44 std::shared_ptr<data_model::FlagDescriptor>
GetFlag(
45 std::string
const& key)
const override;
47 std::shared_ptr<data_model::SegmentDescriptor>
GetSegment(
48 std::string
const& key)
const override;
50 std::unordered_map<std::string, std::shared_ptr<data_model::FlagDescriptor>>
53 std::unordered_map<std::string,
54 std::shared_ptr<data_model::SegmentDescriptor>>
68 void RefreshAllFlags()
const;
69 void RefreshAllSegments()
const;
70 void RefreshFlag(std::string
const& key)
const;
71 void RefreshSegment(std::string
const& key)
const;
73 static std::string CacheTraceMsg(
76 template <
typename TResult>
77 TResult Get(std::string
const& key,
80 std::function<
void(
void)>
const& refresh,
81 std::function<TResult(
void)>
const& get)
const {
82 LD_LOG(logger_, LogLevel::kDebug)
83 <<
Identity() <<
": get " << key <<
" - " << CacheTraceMsg(state);
94 detail::unreachable();
97 template <
typename Item,
typename Evictor>
99 data_components::DataKind
const kind,
100 std::string
const& key,
101 std::function<data_interfaces::IDataReader::SingleResult<Item>(
102 std::string
const&)>
const& getter,
103 Evictor&& evictor)
const {
106 tracker_.
Add(kind, key, ExpiryTime());
108 if (
auto expected_item = getter(key)) {
109 status_manager_.SetState(DataSourceState::kValid);
111 if (
auto optional_item = *expected_item) {
112 cache_.
Upsert(key, std::move(*optional_item));
118 LD_LOG(logger_, LogLevel::kDebug)
119 << kind << key <<
" requested but not found via "
120 << reader_->Identity();
122 LD_LOG(logger_, LogLevel::kDebug)
123 <<
"removed " << kind <<
" " << key <<
" from cache";
127 status_manager_.SetState(
128 DataSourceState::kInterrupted,
129 common::data_sources::DataSourceStatusErrorKind::kUnknown,
130 expected_item.error());
134 LD_LOG(logger_, LogLevel::kError)
135 <<
"failed to refresh " << kind <<
" " << key <<
" via "
136 << reader_->Identity() <<
": " << expected_item.error();
140 template <
typename Item>
142 std::string
const& all_item_key,
143 data_components::DataKind
const item_kind,
145 data_interfaces::IDataReader::CollectionResult<Item>()>
const&
150 auto const updated_expiry = ExpiryTime();
154 tracker_.
Add(all_item_key, updated_expiry);
156 if (
auto all_items = getter()) {
157 status_manager_.SetState(DataSourceState::kValid);
159 for (
auto item : *all_items) {
160 cache_.
Upsert(item.first, std::move(item.second));
161 tracker_.
Add(item_kind, item.first, updated_expiry);
164 status_manager_.SetState(
165 DataSourceState::kInterrupted,
166 common::data_sources::DataSourceStatusErrorKind::kUnknown,
171 LD_LOG(logger_, LogLevel::kError)
172 <<
"failed to refresh all " << item_kind <<
"s via "
173 << reader_->Identity() <<
": " << all_items.error();
177 ClockType::time_point ExpiryTime()
const;
179 Logger
const& logger_;
181 mutable data_components::MemoryStore cache_;
182 std::unique_ptr<data_interfaces::IDataReader> reader_;
184 data_components::DataSourceStatusManager& status_manager_;
186 mutable data_components::ExpirationTracker tracker_;
189 ClockType::duration fresh_duration_;
192 static inline std::string
const kAllFlags =
"allFlags";
193 static inline std::string
const kAllSegments =
"allSegments";
Definition: data_source_status_manager.hpp:16
TrackState
Definition: expiration_tracker.hpp:23
void Add(std::string const &key, TimePoint expiration)
Definition: expiration_tracker.cpp:7
void Upsert(std::string const &key, data_model::FlagDescriptor flag) override
Upsert a flag named by key.
Definition: memory_store.cpp:64
IDataSystem obtains data used for flag evaluations and makes it available to other components.
Definition: idata_system.hpp:11
Definition: lazy_load_system.hpp:28
std::unordered_map< std::string, std::shared_ptr< data_model::SegmentDescriptor > > AllSegments() const override
Get a map of all segments.
Definition: lazy_load_system.cpp:131
std::string const & Identity() const override
Definition: lazy_load_system.cpp:75
std::shared_ptr< data_model::FlagDescriptor > GetFlag(std::string const &key) const override
Get the flag named by key. Returns nullptr if no such flag exists.
Definition: lazy_load_system.cpp:103
std::unordered_map< std::string, std::shared_ptr< data_model::FlagDescriptor > > AllFlags() const override
Get a map of all flags.
Definition: lazy_load_system.cpp:122
bool Initialized() const override
Definition: lazy_load_system.cpp:139
void Initialize() override
Initializes the system. This method will be called before any of the IStore methods are called.
Definition: lazy_load_system.cpp:80
std::shared_ptr< data_model::SegmentDescriptor > GetSegment(std::string const &key) const override
Get the segment named by key. Returns nullptr if no such flag exists.
Definition: lazy_load_system.cpp:112
Definition: lazy_load_config.hpp:10
Definition: lazy_load_system.hpp:62