userver: userver/cache/lru_cache_component_base.hpp Source File
Loading...
Searching...
No Matches
lru_cache_component_base.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/cache/lru_cache_component_base.hpp
4/// @brief @copybrief cache::LruCacheComponent
5
6#include <functional>
7
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/dump/dumper.hpp>
12#include <userver/dump/meta.hpp>
13#include <userver/dump/operations.hpp>
14#include <userver/dynamic_config/source.hpp>
15#include <userver/logging/log.hpp>
16#include <userver/testsuite/cache_control.hpp>
17#include <userver/utils/statistics/entry.hpp>
18#include <userver/yaml_config/schema.hpp>
19
20USERVER_NAMESPACE_BEGIN
21
22namespace cache {
23
24namespace impl {
25
26void RegisterOnStatisticsStorage(
27 const components::ComponentContext& context,
28 const std::string& name,
29 std::function<void(utils::statistics::Writer&)> func
30);
31
32dynamic_config::Source FindDynamicConfigSource(const components::ComponentContext& context);
33
34bool IsDumpSupportEnabled(const components::ComponentConfig& config);
35
36yaml_config::Schema GetLruCacheComponentBaseSchema();
37
38} // namespace impl
39
40/// @ingroup userver_components userver_base_classes
41///
42/// @brief Base class for @ref scripts/docs/en/userver/lru_cache.md "LRU and Expirable LRU cache" components.
43///
44/// Provides facilities for creating @ref scripts/docs/en/userver/lru_cache.md "LRU and Expirable LRU caches".
45/// You need to override LruCacheComponent::DoGetByKey to handle cache misses.
46///
47/// Caching components must be configured in service config (see options below)
48/// and may be reconfigured dynamically via @ref components::DynamicConfig.
49///
50/// ## LruCacheComponent Dynamic config
51/// * @ref USERVER_LRU_CACHES
52///
53/// ## Static options of cache::LruCacheComponent :
54/// @include{doc} scripts/docs/en/components_schema/core/src/cache/lru_cache_component_base.md
55///
56/// Options inherited from @ref components::ComponentBase :
57/// @include{doc} scripts/docs/en/components_schema/core/src/components/impl/component_base.md
58///
59/// ## Example usage:
60///
61/// @snippet core/src/cache/lru_cache_component_base_test.hpp Sample lru cache component
62///
63/// Do not forget to @ref userver_components "add the component to component list":
64/// @snippet core/src/cache/lru_cache_component_base_test.cpp Sample lru cache component registration
65///
66/// ## Example config:
67/// @snippet core/src/cache/lru_cache_component_base_test.cpp Sample lru cache component config
68template <typename Key, typename Value, typename Hash = std::hash<Key>, typename Equal = std::equal_to<Key>>
69// NOLINTNEXTLINE(fuchsia-multiple-inheritance)
71public:
72 using Cache = ExpirableLruCache<Key, Value, Hash, Equal>;
73 using CacheWrapper = LruCacheWrapper<Key, Value, Hash, Equal>;
74
75 LruCacheComponent(const components::ComponentConfig&, const components::ComponentContext&);
76
77 ~LruCacheComponent() override;
78
79 CacheWrapper GetCache();
80
81 static yaml_config::Schema GetStaticConfigSchema();
82
83protected:
84 virtual Value DoGetByKey(const Key& key) = 0;
85
86 std::shared_ptr<Cache> GetCacheRaw() { return cache_; }
87
88private:
89 void DropCache();
90
91 Value GetByKey(const Key& key);
92
93 void OnConfigUpdate(const dynamic_config::Snapshot& cfg);
94
95 void UpdateConfig(const LruCacheConfig& config);
96
97 static constexpr bool kCacheIsDumpable = dump::kIsDumpable<Key> && dump::kIsDumpable<Value>;
98
99 void GetAndWrite(dump::Writer& writer) const override;
100 void ReadAndSet(dump::Reader& reader) override;
101
102 const std::string name_;
103 const LruCacheConfigStatic static_config_;
104 const std::shared_ptr<Cache> cache_;
105 std::shared_ptr<dump::Dumper> dumper_;
106};
107
108template <typename Key, typename Value, typename Hash, typename Equal>
110 Key,
111 Value,
112 Hash,
113 Equal>::LruCacheComponent(const components::ComponentConfig& config, const components::ComponentContext& context)
114 : ComponentBase(config, context),
116 static_config_(config),
117 cache_(std::make_shared<Cache>(static_config_.ways, static_config_.GetWaySize()))
118{
119 if (impl::IsDumpSupportEnabled(config)) {
120 dumper_ = std::make_shared<dump::Dumper>(config, context, static_cast<dump::DumpableEntity&>(*this));
121 cache_->SetDumper(dumper_);
122 dumper_->ReadDump();
123 }
124
125 cache_->SetMaxLifetime(static_config_.config.lifetime);
126 cache_->SetBackgroundUpdate(static_config_.config.background_update);
127
128 if (static_config_.use_dynamic_config) {
129 LOG_INFO()
130 << "Dynamic LRU cache config is enabled, subscribing on "
131 "dynamic-config updates, cache="
132 << name_;
133
134 impl::FindDynamicConfigSource(context).UpdateAndListen(
136 this,
137 "cache." + name_,
138 &LruCacheComponent::OnConfigUpdate
139 );
140 } else {
141 LOG_INFO() << "Dynamic LRU cache config is disabled, cache=" << name_;
142 }
143
144 impl::RegisterOnStatisticsStorage(context, name_, [this](utils::statistics::Writer& writer) { writer = *cache_; });
145
146 testsuite::RegisterCacheScope(context, this, &LruCacheComponent::DropCache);
147}
148
149template <typename Key, typename Value, typename Hash, typename Equal>
150LruCacheComponent<Key, Value, Hash, Equal>::~LruCacheComponent() {
151 if (dumper_) {
153 }
154}
155
156template <typename Key, typename Value, typename Hash, typename Equal>
157typename LruCacheComponent<Key, Value, Hash, Equal>::CacheWrapper LruCacheComponent<
158 Key,
159 Value,
160 Hash,
161 Equal>::GetCache() {
162 return CacheWrapper(cache_, [this](const Key& key) { return GetByKey(key); });
163}
164
165template <typename Key, typename Value, typename Hash, typename Equal>
166void LruCacheComponent<Key, Value, Hash, Equal>::DropCache() {
167 cache_->Invalidate();
168}
169
170template <typename Key, typename Value, typename Hash, typename Equal>
171Value LruCacheComponent<Key, Value, Hash, Equal>::GetByKey(const Key& key) {
172 return DoGetByKey(key);
173}
174
175template <typename Key, typename Value, typename Hash, typename Equal>
176void LruCacheComponent<Key, Value, Hash, Equal>::OnConfigUpdate(const dynamic_config::Snapshot& cfg) {
177 const auto config = GetLruConfig(cfg, name_);
178 if (config) {
179 LOG_DEBUG() << "Using dynamic config for LRU cache";
180 UpdateConfig(*config);
181 } else {
182 LOG_DEBUG() << "Using static config for LRU cache";
183 UpdateConfig(static_config_.config);
184 }
185}
186
187template <typename Key, typename Value, typename Hash, typename Equal>
188void LruCacheComponent<Key, Value, Hash, Equal>::UpdateConfig(const LruCacheConfig& config) {
189 cache_->SetWaySize(config.GetWaySize(static_config_.ways));
190 cache_->SetMaxLifetime(config.lifetime);
191 cache_->SetBackgroundUpdate(config.background_update);
192}
193
194template <typename Key, typename Value, typename Hash, typename Equal>
195yaml_config::Schema LruCacheComponent<Key, Value, Hash, Equal>::GetStaticConfigSchema() {
196 return impl::GetLruCacheComponentBaseSchema();
197}
198
199template <typename Key, typename Value, typename Hash, typename Equal>
200void LruCacheComponent<Key, Value, Hash, Equal>::GetAndWrite(dump::Writer& writer) const {
201 if constexpr (kCacheIsDumpable) {
202 cache_->Write(writer);
203 } else {
204 dump::ThrowDumpUnimplemented(name_);
205 }
206}
207
208template <typename Key, typename Value, typename Hash, typename Equal>
209void LruCacheComponent<Key, Value, Hash, Equal>::ReadAndSet(dump::Reader& reader) {
210 if constexpr (kCacheIsDumpable) {
211 cache_->Read(reader);
212 } else {
213 dump::ThrowDumpUnimplemented(name_);
214 }
215}
216
217} // namespace cache
218
219USERVER_NAMESPACE_END