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 RefreshInitState()
const;
71 void RefreshFlag(std::string
const& key)
const;
72 void RefreshSegment(std::string
const& key)
const;
74 static std::string CacheTraceMsg(
77 template <
typename TResult>
78 TResult Get(std::string
const& key,
81 std::function<
void(
void)>
const& refresh,
82 std::function<TResult(
void)>
const& get)
const {
83 LD_LOG(logger_, LogLevel::kDebug)
84 <<
Identity() <<
": get " << key <<
" - " << CacheTraceMsg(state);
95 detail::unreachable();
98 template <
typename Item,
typename Evictor>
100 data_components::DataKind
const kind,
101 std::string
const& key,
102 std::function<data_interfaces::IDataReader::SingleResult<Item>(
103 std::string
const&)>
const& getter,
104 Evictor&& evictor)
const {
107 tracker_.
Add(kind, key, ExpiryTime());
109 if (
auto expected_item = getter(key)) {
110 status_manager_.SetState(DataSourceState::kValid);
112 if (
auto optional_item = *expected_item) {
113 cache_.
Upsert(key, std::move(*optional_item));
119 LD_LOG(logger_, LogLevel::kDebug)
120 << kind << key <<
" requested but not found via "
121 << reader_->Identity();
123 LD_LOG(logger_, LogLevel::kDebug)
124 <<
"removed " << kind <<
" " << key <<
" from cache";
128 status_manager_.SetState(
129 DataSourceState::kInterrupted,
130 common::data_sources::DataSourceStatusErrorKind::kUnknown,
131 expected_item.error());
135 LD_LOG(logger_, LogLevel::kError)
136 <<
"failed to refresh " << kind <<
" " << key <<
" via "
137 << reader_->Identity() <<
": " << expected_item.error();
141 template <
typename Item>
143 std::string
const& all_item_key,
144 data_components::DataKind
const item_kind,
146 data_interfaces::IDataReader::CollectionResult<Item>()>
const&
151 auto const updated_expiry = ExpiryTime();
155 tracker_.
Add(all_item_key, updated_expiry);
157 if (
auto all_items = getter()) {
158 status_manager_.SetState(DataSourceState::kValid);
160 for (
auto item : *all_items) {
161 cache_.
Upsert(item.first, std::move(item.second));
162 tracker_.
Add(item_kind, item.first, updated_expiry);
165 status_manager_.SetState(
166 DataSourceState::kInterrupted,
167 common::data_sources::DataSourceStatusErrorKind::kUnknown,
172 LD_LOG(logger_, LogLevel::kError)
173 <<
"failed to refresh all " << item_kind <<
"s via "
174 << reader_->Identity() <<
": " << all_items.error();
178 ClockType::time_point ExpiryTime()
const;
180 Logger
const& logger_;
182 mutable data_components::MemoryStore cache_;
183 std::unique_ptr<data_interfaces::IDataReader> reader_;
185 data_components::DataSourceStatusManager& status_manager_;
187 mutable data_components::ExpirationTracker tracker_;
189 mutable std::optional<bool> initialized_;
191 ClockType::duration fresh_duration_;
194 static inline std::string
const kAllFlags =
"allFlags";
195 static inline std::string
const kAllSegments =
"allSegments";
196 static inline std::string
const kInitialized =
"initialized";