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_);