8#include <userver/cache/expirable_lru_cache.hpp>
9#include <userver/cache/lru_cache_config.hpp>
10#include <userver/components/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/cache_control.hpp>
18#include <userver/utils/statistics/entry.hpp>
19#include <userver/yaml_config/schema.hpp>
21USERVER_NAMESPACE_BEGIN
27void RegisterOnStatisticsStorage(
28 const components::ComponentContext& context,
29 const std::string& name,
30 std::function<
void(utils::statistics::Writer&)> func
33dynamic_config::Source FindDynamicConfigSource(
const components::ComponentContext& context);
35bool IsDumpSupportEnabled(
const components::ComponentConfig& config);
37yaml_config::Schema GetLruCacheComponentBaseSchema();
69template <
typename Key,
typename Value,
typename Hash = std::hash<Key>,
typename Equal = std::equal_to<Key>>
73 using Cache = ExpirableLruCache<Key, Value, Hash, Equal>;
74 using CacheWrapper = LruCacheWrapper<Key, Value, Hash, Equal>;
76 LruCacheComponent(
const components::ComponentConfig&,
const components::ComponentContext&);
78 ~LruCacheComponent()
override;
80 CacheWrapper GetCache();
82 static yaml_config::Schema GetStaticConfigSchema();
85 virtual Value DoGetByKey(
const Key& key) = 0;
87 std::shared_ptr<Cache> GetCacheRaw() {
return cache_; }
92 Value GetByKey(
const Key& key);
94 void OnConfigUpdate(
const dynamic_config::Snapshot& cfg);
96 void UpdateConfig(
const LruCacheConfig& config);
98 static constexpr bool kCacheIsDumpable = dump::kIsDumpable<Key> && dump::kIsDumpable<Value>;
100 void GetAndWrite(dump::
Writer& writer)
const override;
101 void ReadAndSet(dump::
Reader& reader)
override;
103 const std::string name_;
104 const LruCacheConfigStatic static_config_;
105 std::shared_ptr<dump::Dumper> dumper_;
106 const std::shared_ptr<Cache> cache_;
109 concurrent::AsyncEventSubscriberScope config_subscription_;
110 testsuite::CacheResetRegistration reset_registration_;
114template <
typename Key,
typename Value,
typename Hash,
typename Equal>
119 Equal>::LruCacheComponent(
const components::ComponentConfig& config,
const components::ComponentContext& context)
120 : ComponentBase(config, context),
121 name_(components::GetCurrentComponentName(context)),
122 static_config_(config),
123 cache_(std::make_shared<Cache>(static_config_.ways, static_config_.GetWaySize()))
125 if (impl::IsDumpSupportEnabled(config)) {
126 dumper_ = std::make_shared<dump::Dumper>(config, context,
static_cast<dump::DumpableEntity&>(*
this));
127 cache_->SetDumper(dumper_);
131 cache_->SetMaxLifetime(static_config_.config.lifetime);
132 cache_->SetBackgroundUpdate(static_config_.config.background_update);
134 if (static_config_.use_dynamic_config) {
136 <<
"Dynamic LRU cache config is enabled, subscribing on "
137 "dynamic-config updates, cache="
140 config_subscription_ =
141 impl::FindDynamicConfigSource(context)
144 LOG_INFO() <<
"Dynamic LRU cache config is disabled, cache=" << name_;
147 impl::RegisterOnStatisticsStorage(context, name_, [
this](utils::statistics::Writer& writer) { writer = *cache_; });
149 reset_registration_ = testsuite::RegisterCache(context,
this, &
LruCacheComponent::DropCache);
152template <
typename Key,
typename Value,
typename Hash,
typename Equal>
154 reset_registration_.Unregister();
155 config_subscription_.Unsubscribe();
158 dumper_->CancelWriteTaskAndWait();
162template <
typename Key,
typename Value,
typename Hash,
typename Equal>
168 return CacheWrapper(cache_, [
this](
const Key& key) {
return GetByKey(key); });
171template <
typename Key,
typename Value,
typename Hash,
typename Equal>
173 cache_->Invalidate();
176template <
typename Key,
typename Value,
typename Hash,
typename Equal>
178 return DoGetByKey(key);
181template <
typename Key,
typename Value,
typename Hash,
typename Equal>
182void LruCacheComponent<Key, Value, Hash, Equal>::OnConfigUpdate(
const dynamic_config::Snapshot& cfg) {
183 const auto config = GetLruConfig(cfg, name_);
185 LOG_DEBUG() <<
"Using dynamic config for LRU cache";
186 UpdateConfig(*config);
188 LOG_DEBUG() <<
"Using static config for LRU cache";
189 UpdateConfig(static_config_.config);
193template <
typename Key,
typename Value,
typename Hash,
typename Equal>
194void LruCacheComponent<Key, Value, Hash, Equal>::UpdateConfig(
const LruCacheConfig& config) {
195 cache_->SetWaySize(config.GetWaySize(static_config_.ways));
196 cache_->SetMaxLifetime(config.lifetime);
197 cache_->SetBackgroundUpdate(config.background_update);
200template <
typename Key,
typename Value,
typename Hash,
typename Equal>
201yaml_config::Schema
LruCacheComponent<Key, Value, Hash, Equal>::GetStaticConfigSchema() {
202 return impl::GetLruCacheComponentBaseSchema();
205template <
typename Key,
typename Value,
typename Hash,
typename Equal>
207 if constexpr (kCacheIsDumpable) {
208 cache_->Write(writer);
210 dump::ThrowDumpUnimplemented(name_);
214template <
typename Key,
typename Value,
typename Hash,
typename Equal>
216 if constexpr (kCacheIsDumpable) {
217 cache_->Read(reader);
219 dump::ThrowDumpUnimplemented(name_);