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 canonical created, updated and deleted event subjects (built with event_subject from the entity's entity_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.

1. 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_event.hpp"
#include "ores.eventing.api/domain/entity_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}}_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}} created, updated and deleted
 * event subjects so each affected tenant is reloaded on any mutation.
 * Call once at service startup and keep every returned subscription
 * alive for the service's lifetime.
 */
inline std::vector<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)
        // A warm-up failure is logged; nothing here can react to it.
        (void)cache->load(tenant_id);

    using ores::eventing::domain::entity_event_notification;
    using ores::eventing::domain::event_subject;
    using ores::{{component}}::messaging::{{entity_singular}}_event;

    const auto on_change = [cache](ores::nats::message msg) {
        auto evt = ores::nats::default_wire_codec().decode<entity_event_notification>(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();
        }
    };

    std::vector<ores::nats::service::subscription> subs;
    subs.reserve(3);
    subs.push_back(nats.subscribe(
        event_subject<{{entity_singular}}_event>("created"), on_change));
    subs.push_back(nats.subscribe(
        event_subject<{{entity_singular}}_event>("updated"), on_change));
    subs.push_back(nats.subscribe(
        event_subject<{{entity_singular}}_event>("deleted"), on_change));
    return subs;
}

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

#endif
{{/domain_entity}}

2. See also

Emacs 29.3 (Org mode 9.6.15)