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
 
  105  CachingComponentBase(
const ComponentConfig& config, 
const ComponentContext&);
 
  106  ~CachingComponentBase() 
override;
 
  121  template <
class Class>
 
  123      Class* obj, std::string name,
 
  124      void (Class::*func)(
const std::shared_ptr<
const T>&));
 
  129  static yaml_config::Schema GetStaticConfigSchema();
 
  132  void Set(std::unique_ptr<
const T> value_ptr);
 
  135  template <
typename... Args>
 
  136  void Emplace(Args&&... args);
 
  149  virtual std::unique_ptr<
const T> ReadContents(dump::Reader& reader) 
const;
 
  153  void OnAllComponentsLoaded() 
final;
 
  155  void Cleanup() 
final;
 
  157  void MarkAsExpired() 
final;
 
  159  void GetAndWrite(
dump::
Writer& writer) 
const final;
 
  165  virtual void PreAssignCheck(
const T* old_value_ptr,
 
  166                              const T* new_value_ptr) 
const;
 
  168  rcu::Variable<std::shared_ptr<
const T>> cache_;
 
  170  utils::impl::WaitTokenStorage wait_token_storage_;
 
  175                                              const ComponentContext& context)
 
  179                     [
this](
auto& function) {
 
  180                       const auto ptr = cache_.ReadCopy();
 
  181                       if (ptr) function(ptr);
 
  183  const auto initial_config = GetConfig();
 
  189  cache_.Assign(
nullptr);
 
  192  wait_token_storage_.WaitForAllTokens();
 
  199    throw cache::EmptyCacheError(
Name());
 
  205template <
typename Class>
 
  207    Class* obj, std::string name,
 
  208    void (Class::*func)(
const std::shared_ptr<
const T>&)) {
 
  209  return event_channel_.DoUpdateAndListen(obj, std::move(name), func, [&] {
 
  218  return event_channel_;
 
  223  return utils::SharedReadablePtr<T>(cache_.ReadCopy());
 
  228  auto deleter = [token = wait_token_storage_.GetToken(),
 
  229                  &cache_task_processor =
 
  230                      GetCacheTaskProcessor()](
const T* raw_ptr) 
mutable {
 
  231    std::unique_ptr<
const T> ptr{raw_ptr};
 
  234    engine::CriticalAsyncNoSpan(cache_task_processor, [ptr = std::move(ptr),
 
  242  const std::shared_ptr<
const T> new_value(value_ptr.release(),
 
  245  if (HasPreAssignCheck()) {
 
  246    auto old_value = cache_.Read();
 
  247    PreAssignCheck(old_value->get(), new_value.get());
 
  250  cache_.Assign(new_value);
 
  251  event_channel_.SendEvent(new_value);
 
  257  Emplace(std::move(value));
 
  261template <
typename... Args>
 
  263  Set(std::make_unique<T>(std::forward<Args>(args)...));
 
  268  cache_.Assign(std::make_unique<
const T>());
 
  279  if (!contents) 
throw cache::EmptyCacheError(
Name());
 
  285  Set(ReadContents(reader));
 
  290                                            const T& contents) 
const {
 
  291  if constexpr (
dump::kIsDumpable<T>) {
 
  292    writer.Write(contents);
 
  300    dump::Reader& reader) 
const {
 
  301  if constexpr (
dump::kIsDumpable<T>) {
 
  303    return std::unique_ptr<
const T>{
new T(reader.Read<T>())};
 
  311  AssertPeriodicUpdateStarted();
 
  321  Set(std::unique_ptr<
const T>{});
 
  326yaml_config::Schema GetCachingComponentBaseSchema();
 
  332  return impl::GetCachingComponentBaseSchema();
 
  337    const T*, [[maybe_unused]] 
const T* new_value_ptr) 
const {
 
  340      fmt::format(
"{} type does not support std::size(), add implementation of " 
  341                  "the method size() for this type or " 
  342                  "override cache::CachingComponentBase::PreAssignCheck.",
 
  343                  compiler::GetTypeName<T>()));
 
  345  if constexpr (meta::kIsSizable<T>) {
 
  346    if (!new_value_ptr || std::size(*new_value_ptr) == 0) {
 
  347      throw cache::EmptyDataError(
Name());