10#include <fmt/format.h> 
   12#include <userver/cache/cache_update_trait.hpp> 
   13#include <userver/cache/exceptions.hpp> 
   14#include <userver/compiler/demangle.hpp> 
   15#include <userver/components/component_fwd.hpp> 
   16#include <userver/components/loggable_component_base.hpp> 
   17#include <userver/concurrent/async_event_channel.hpp> 
   18#include <userver/dump/helpers.hpp> 
   19#include <userver/dump/meta.hpp> 
   20#include <userver/dump/operations.hpp> 
   21#include <userver/engine/async.hpp> 
   22#include <userver/rcu/rcu.hpp> 
   23#include <userver/utils/assert.hpp> 
   24#include <userver/utils/impl/wait_token_storage.hpp> 
   25#include <userver/utils/meta.hpp> 
   26#include <userver/utils/shared_readable_ptr.hpp> 
   27#include <userver/yaml_config/schema.hpp> 
   29USERVER_NAMESPACE_BEGIN
 
  128  CachingComponentBase(
const ComponentConfig& config, 
const ComponentContext&);
 
  129  ~CachingComponentBase() 
override;
 
  137  utils::SharedReadablePtr<T> 
Get() 
const;
 
  144  template <
class Class>
 
  146      Class* obj, std::string name,
 
  147      void (Class::*func)(
const std::shared_ptr<
const T>&));
 
  152  static yaml_config::Schema GetStaticConfigSchema();
 
  160  void Set(std::unique_ptr<
const T> value_ptr);
 
  166  template <
typename... Args>
 
  167  void Emplace(Args&&... args);
 
  181  virtual std::unique_ptr<
const T> ReadContents(dump::Reader& reader) 
const;
 
  188                              const T* new_value_ptr) 
const;
 
  191  void OnAllComponentsLoaded() 
final;
 
  193  void Cleanup() 
final;
 
  195  void MarkAsExpired() 
final;
 
  197  void GetAndWrite(
dump::
Writer& writer) 
const final;
 
  200  rcu::Variable<std::shared_ptr<
const T>> cache_;
 
  202  utils::impl::WaitTokenStorage wait_token_storage_;
 
  207                                              const ComponentContext& context)
 
  211                     [
this](
auto& function) {
 
  212                       const auto ptr = cache_.ReadCopy();
 
  213                       if (ptr) function(ptr);
 
  215  const auto initial_config = GetConfig();
 
  221  cache_.Assign(
nullptr);
 
  224  wait_token_storage_.WaitForAllTokens();
 
  231    throw cache::EmptyCacheError(
Name());
 
  237template <
typename Class>
 
  239    Class* obj, std::string name,
 
  240    void (Class::*func)(
const std::shared_ptr<
const T>&)) {
 
  241  return event_channel_.DoUpdateAndListen(obj, std::move(name), func, [&] {
 
  250  return event_channel_;
 
  255  return utils::SharedReadablePtr<T>(cache_.ReadCopy());
 
  260  auto deleter = [token = wait_token_storage_.GetToken(),
 
  261                  &cache_task_processor =
 
  262                      GetCacheTaskProcessor()](
const T* raw_ptr) 
mutable {
 
  263    std::unique_ptr<
const T> ptr{raw_ptr};
 
  266    engine::CriticalAsyncNoSpan(cache_task_processor, [ptr = std::move(ptr),
 
  274  const std::shared_ptr<
const T> new_value(value_ptr.release(),
 
  277  if (HasPreAssignCheck()) {
 
  278    auto old_value = cache_.Read();
 
  279    PreAssignCheck(old_value->get(), new_value.get());
 
  282  cache_.Assign(new_value);
 
  283  event_channel_.SendEvent(new_value);
 
  289  Emplace(std::move(value));
 
  293template <
typename... Args>
 
  295  Set(std::make_unique<T>(std::forward<Args>(args)...)
);
 
  300  cache_.Assign(std::make_unique<
const T>());
 
  311  if (!contents) 
throw cache::EmptyCacheError(
Name());
 
  317  auto data = ReadContents(reader);
 
  318  if constexpr (meta::kIsSizable<T>) {
 
  320      SetDataSizeStatistic(std::size(*data));
 
  323  Set(std::move(data));
 
  328                                            const T& contents) 
const {
 
  329  if constexpr (
dump::kIsDumpable<T>) {
 
  330    writer.Write(contents);
 
  338    dump::Reader& reader) 
const {
 
  339  if constexpr (
dump::kIsDumpable<T>) {
 
  341    return std::unique_ptr<
const T>{
new T(reader.Read<T>())};
 
  349  AssertPeriodicUpdateStarted();
 
  359  Set(std::unique_ptr<
const T>{});
 
  364yaml_config::Schema GetCachingComponentBaseSchema();
 
  370  return impl::GetCachingComponentBaseSchema();
 
  375    const T*, [[
maybe_unused]] 
const T* new_value_ptr) 
const {
 
  378      fmt::format(
"{} type does not support std::size(), add implementation of " 
  379                  "the method size() for this type or " 
  380                  "override cache::CachingComponentBase::PreAssignCheck.",
 
  381                  compiler::GetTypeName<T>()));
 
  383  if constexpr (meta::kIsSizable<T>) {
 
  384    if (!new_value_ptr || std::size(*new_value_ptr) == 0) {
 
  385      throw cache::EmptyDataError(
Name());