ores.cpp.nats-event-cache.registrar_wiring

Table of Contents

A header-only free function, warm_and_subscribe_{{entity}}_cache, warming the cache_header archetype's cache class for a set of tenants at startup, then subscribing to the entity's changed-event subject (bound via event_traits, no hardcoded subject string) so the affected tenant's partition is reloaded on every mutation. Meant to be called from a hand-written consumer service registrar (e.g. IAM's registrar.cpp) alongside its other subscriptions — this archetype does not generate or replace that registrar.

See the Template variable reference for the complete list of available variables and their semantics.

Template

The full template source. Edit here and re-tangle with compass build --direct tangle_codegen_templates to regenerate library/templates/cpp_nats_event_cache_registrar.hpp.mustache.

{{! GENERATED FILE — tangled from projects/ores.codegen/library/templates/ores.cpp.nats-event-cache.registrar_wiring.org. Edit the org source. }}
{{{cpp_license}}}
{{#domain_entity}}
#ifndef ORES_{{cache_component_upper}}_{{cache_subcomponent_upper}}_SERVICE_CACHE_{{entity_singular_upper}}_CACHE_REGISTRAR_HPP
#define ORES_{{cache_component_upper}}_{{cache_subcomponent_upper}}_SERVICE_CACHE_{{entity_singular_upper}}_CACHE_REGISTRAR_HPP

#include "ores.eventing.api/domain/entity_change_event.hpp"
#include "ores.eventing.api/domain/event_traits.hpp"
#include "ores.logging/make_logger.hpp"
#include "ores.{{cache_component}}.{{cache_subcomponent}}/service/cache/{{entity_singular}}_cache.hpp"
#include "ores.{{component_include}}/eventing/{{entity_singular}}_changed_event.hpp"
#include "ores.nats/domain/wire_codec.hpp"
#include "ores.nats/service/client.hpp"
#include <memory>
#include <string>
#include <thread>
#include <vector>

namespace ores::{{cache_component}}::service::cache {

namespace {
inline auto& {{entity_singular}}_cache_registrar_lg() {
    static auto instance = ores::logging::make_logger(
        "ores.{{cache_component}}.service.cache.{{entity_singular}}_cache_registrar");
    return instance;
}
} // namespace

/**
 * @brief Warms {{entity_singular}}_cache for every given tenant, then
 * subscribes to the {{entity_singular}} changed-event subject so each
 * affected tenant is reloaded on any mutation. Call once at service
 * startup and keep the returned subscription alive for the service's
 * lifetime.
 */
inline ores::nats::service::subscription warm_and_subscribe_{{entity_singular}}_cache(
    ores::nats::service::client& nats,
    std::shared_ptr<{{entity_singular}}_cache> cache,
    const std::vector<std::string>& tenant_ids) {
    using namespace ores::logging;
    BOOST_LOG_SEV({{entity_singular}}_cache_registrar_lg(), debug)
        << "Warming {{entity_singular}} cache for " << tenant_ids.size() << " tenant(s)";
    for (const auto& tenant_id : tenant_ids)
        (void)cache->load(tenant_id); // warm-up failure is logged; nothing here can react to it

    using ores::eventing::domain::event_traits;
    using ores::{{component}}::eventing::{{entity_singular}}_changed_event;
    return nats.subscribe(
        std::string(event_traits<{{entity_singular}}_changed_event>::name),
        [cache](ores::nats::message msg) {
            using ores::eventing::domain::entity_change_event;
            auto evt = ores::nats::default_wire_codec().decode<entity_change_event>(msg.data);
            if (evt && !evt->tenant_id.empty()) {
                // Offload to a detached thread: load() calls request_sync,
                // which would block the NATS callback thread if called inline.
                std::thread([cache, tid = evt->tenant_id]() { (void)cache->load(tid); }).detach();
            }
        });
}

} // namespace ores::{{cache_component}}::service::cache

#endif
{{/domain_entity}}

See also

Emacs 29.3 (Org mode 9.6.15)