8#include <userver/cache/expirable_lru_cache.hpp>
9#include <userver/cache/lru_cache_config.hpp>
10#include <userver/components/loggable_component_base.hpp>
11#include <userver/concurrent/async_event_source.hpp>
12#include <userver/dump/dumper.hpp>
13#include <userver/dump/meta.hpp>
14#include <userver/dump/operations.hpp>
15#include <userver/dynamic_config/source.hpp>
16#include <userver/logging/log.hpp>
17#include <userver/testsuite/component_control.hpp>
18#include <userver/utils/statistics/entry.hpp>
19#include <userver/yaml_config/schema.hpp>
21USERVER_NAMESPACE_BEGIN
27testsuite::ComponentControl& FindComponentControl(
30utils::statistics::Entry RegisterOnStatisticsStorage(
31 const components::ComponentContext& context,
const std::string& name,
32 std::function<
void(
utils::statistics::Writer&)> func);
34dynamic_config::Source FindDynamicConfigSource(
37bool IsDumpSupportEnabled(
const components::ComponentConfig& config);
39yaml_config::Schema GetLruCacheComponentBaseSchema();
77template <
typename Key,
typename Value,
typename Hash = std::hash<Key>,
78 typename Equal = std::equal_to<Key>>
83 using Cache = ExpirableLruCache<Key, Value, Hash, Equal>;
84 using CacheWrapper = LruCacheWrapper<Key, Value, Hash, Equal>;
86 LruCacheComponent(
const components::ComponentConfig&,
89 ~LruCacheComponent()
override;
91 CacheWrapper GetCache();
96 virtual Value DoGetByKey(
const Key& key) = 0;
101 Value GetByKey(
const Key& key);
103 void OnConfigUpdate(
const dynamic_config::Snapshot& cfg);
105 void UpdateConfig(
const LruCacheConfig& config);
107 static constexpr bool kCacheIsDumpable =
108 dump::kIsDumpable<Key> &&
dump::kIsDumpable<Value>;
110 void GetAndWrite(
dump::
Writer& writer)
const override;
111 void ReadAndSet(
dump::
Reader& reader)
override;
114 std::shared_ptr<Cache> GetCacheRaw() {
return cache_; }
117 const std::string name_;
118 const LruCacheConfigStatic static_config_;
119 std::shared_ptr<
dump::Dumper> dumper_;
120 const std::shared_ptr<Cache> cache_;
121 concurrent::AsyncEventSubscriberScope config_subscription_;
122 utils::statistics::Entry statistics_holder_;
123 std::optional<
testsuite::ComponentInvalidatorHolder> invalidator_holder_;
126template <
typename Key,
typename Value,
typename Hash,
typename Equal>
132 static_config_(config),
133 cache_(std::make_shared<Cache>(static_config_.ways,
134 static_config_.GetWaySize())) {
135 if (
impl::IsDumpSupportEnabled(config)) {
136 dumper_ = std::make_shared<dump::Dumper>(
137 config, context,
static_cast<dump::DumpableEntity&>(*
this));
138 cache_->SetDumper(dumper_);
142 cache_->SetMaxLifetime(static_config_.config.lifetime);
143 cache_->SetBackgroundUpdate(static_config_.config.background_update);
145 if (static_config_.use_dynamic_config) {
146 LOG_INFO() <<
"Dynamic LRU cache config is enabled, subscribing on "
147 "dynamic-config updates, cache="
150 config_subscription_ =
151 impl::FindDynamicConfigSource(context).UpdateAndListen(
152 this,
"cache." + name_,
155 LOG_INFO() <<
"Dynamic LRU cache config is disabled, cache=" << name_;
158 statistics_holder_ = impl::RegisterOnStatisticsStorage(
160 [
this](utils::statistics::Writer& writer) { writer = *cache_; });
162 invalidator_holder_.emplace(
163 impl::FindComponentControl(context), *
this,
164 &LruCacheComponent<Key, Value, Hash, Equal>::DropCache);
167template <
typename Key,
typename Value,
typename Hash,
typename Equal>
169 invalidator_holder_.reset();
170 statistics_holder_.Unregister();
174 dumper_->CancelWriteTaskAndWait();
178template <
typename Key,
typename Value,
typename Hash,
typename Equal>
181 return CacheWrapper(cache_, [
this](
const Key& key) {
return GetByKey(key); });
184template <
typename Key,
typename Value,
typename Hash,
typename Equal>
186 cache_->Invalidate();
189template <
typename Key,
typename Value,
typename Hash,
typename Equal>
191 return DoGetByKey(key);
194template <
typename Key,
typename Value,
typename Hash,
typename Equal>
196 const dynamic_config::Snapshot& cfg) {
197 const auto config = GetLruConfig(cfg, name_);
199 LOG_DEBUG() <<
"Using dynamic config for LRU cache";
200 UpdateConfig(*config);
202 LOG_DEBUG() <<
"Using static config for LRU cache";
203 UpdateConfig(static_config_.config);
207template <
typename Key,
typename Value,
typename Hash,
typename Equal>
209 const LruCacheConfig& config) {
210 cache_->SetWaySize(config.GetWaySize(static_config_.ways));
211 cache_->SetMaxLifetime(config.lifetime);
212 cache_->SetBackgroundUpdate(config.background_update);
215template <
typename Key,
typename Value,
typename Hash,
typename Equal>
218 return impl::GetLruCacheComponentBaseSchema();
221template <
typename Key,
typename Value,
typename Hash,
typename Equal>
224 if constexpr (kCacheIsDumpable) {
225 cache_->Write(writer);
227 dump::ThrowDumpUnimplemented(name_);
231template <
typename Key,
typename Value,
typename Hash,
typename Equal>
234 if constexpr (kCacheIsDumpable) {
235 cache_->Read(reader);
237 dump::ThrowDumpUnimplemented(name_);