conduit 0.6.0
Modern C++23 header-only event-dispatching / event-transport library
Loading...
Searching...
No Matches
event_type_registry.hpp
Go to the documentation of this file.
1#pragma once
2
18
19#include <conduit/event.hpp>
20#include <conduit/exception.hpp>
21
22#include <concepts>
23#include <optional>
24#include <shared_mutex>
25#include <string>
26#include <string_view>
27#include <vector>
28
29#include <parcel/parcel.h>
30
31namespace conduit {
32
38 std::string_view name;
39 std::string_view kind_id;
40 parcel::cell_type_descriptor_t descriptor;
41
43 [[nodiscard]] parcel::DisplayInfo display_info() const {
44 return descriptor->display_info();
45 }
46
48 [[nodiscard]] parcel::json_t schema() const {
49 return descriptor->to_json();
50 }
51};
52
59public:
60 EventTypeRegistry() = default;
61
64 template <typename T>
66 static_assert(std::derived_from<T, parcel::ICell>,
67 "EventTypeRegistry::add<T>: T must be a parcel ICell-derived event type");
68 std::unique_lock lock(mu_);
69 registry_.register_kind(T::descriptor());
70 return *this;
71 }
72
75 [[nodiscard]] std::vector<EventTypeInfo> types() const {
76 std::shared_lock lock(mu_);
77 std::vector<EventTypeInfo> out;
78 for (const auto& desc : registry_.all()) {
79 const std::string_view kind = desc->kind();
80 if (!kind.starts_with(event_kind_prefix)) {
81 continue;
82 }
83 out.push_back(EventTypeInfo{
84 .name = kind.substr(event_kind_prefix.size()),
85 .kind_id = kind,
86 .descriptor = desc,
87 });
88 }
89 return out;
90 }
91
94 [[nodiscard]] std::optional<EventTypeInfo> find(const std::string_view name_or_kind) const {
95 std::shared_lock lock(mu_);
96 const auto desc = resolve(name_or_kind);
97 if (!desc) {
98 return std::nullopt;
99 }
100 const std::string_view kind = desc->kind();
101 return EventTypeInfo{
102 .name = kind.substr(event_kind_prefix.size()),
103 .kind_id = kind,
104 .descriptor = desc,
105 };
106 }
107
109 [[nodiscard]] bool contains(const std::string_view name_or_kind) const {
110 std::shared_lock lock(mu_);
111 return resolve(name_or_kind) != nullptr;
112 }
113
116 [[nodiscard]] parcel::json_t schema(const std::string_view name_or_kind) const {
117 std::shared_lock lock(mu_);
118 const auto desc = resolve(name_or_kind);
119 if (!desc) {
120 throw UnknownEventTypeError{"EventTypeRegistry::schema: unknown event type '" +
121 std::string{name_or_kind} + "'"};
122 }
123 return desc->to_json();
124 }
125
126private:
130 [[nodiscard]] parcel::cell_type_descriptor_t
131 resolve(const std::string_view name_or_kind) const {
132 if (name_or_kind.starts_with(event_kind_prefix)) {
133 return registry_.find(name_or_kind);
134 }
135 std::string kind;
136 kind.reserve(event_kind_prefix.size() + name_or_kind.size());
137 kind.append(event_kind_prefix).append(name_or_kind);
138 return registry_.find(kind);
139 }
140
141 mutable std::shared_mutex mu_;
142 parcel::ParcelRegistry registry_;
143};
144
147[[nodiscard]] inline EventTypeRegistry& global_event_types() {
148 static EventTypeRegistry r;
149 return r;
150}
151
155template <typename T>
158 global_event_types().add<T>();
159 }
160};
161
163[[nodiscard]] inline std::vector<EventTypeInfo> registered_event_types() {
164 return global_event_types().types();
165}
166
167} // namespace conduit
168
175#define CONDUIT_REGISTER_EVENT(Ident) \
176 inline const ::conduit::EventTypeRegistrar<Ident> conduit_event_type_registrar_##Ident {}
Catalog of conduit event types.
Definition event_type_registry.hpp:58
std::optional< EventTypeInfo > find(const std::string_view name_or_kind) const
Look up a type by bare name ("order.created") or full kind ("conduit:event:order.created").
Definition event_type_registry.hpp:94
std::vector< EventTypeInfo > types() const
All registered event types (descriptors whose kind starts with event_kind_prefix; parcel builtins are...
Definition event_type_registry.hpp:75
bool contains(const std::string_view name_or_kind) const
Whether a type with the given name or kind is registered.
Definition event_type_registry.hpp:109
EventTypeRegistry & add()
Register the descriptor for event type T (derived from conduit::Event<T, Name>, hence an ICell-derive...
Definition event_type_registry.hpp:65
parcel::json_t schema(const std::string_view name_or_kind) const
Per-type JSON schema for the given name or kind.
Definition event_type_registry.hpp:116
Raised by EventTypeRegistry::schema when the requested name or kind is not registered.
Definition exception.hpp:63
Event<Self, Name> library base built on parcel::SelfStructCell.
Root exception hierarchy for the conduit library.
Definition builder.hpp:22
EventTypeRegistry & global_event_types()
Program-wide event type catalog.
Definition event_type_registry.hpp:147
std::vector< EventTypeInfo > registered_event_types()
Snapshot of every type registered in the program-wide catalog.
Definition event_type_registry.hpp:163
constexpr std::string_view event_kind_prefix
Wire-kind prefix shared by every conduit event type.
Definition event.hpp:21
Identity + shape for one registered event type.
Definition event_type_registry.hpp:37
std::string_view name
Bare event name, e.g. "order.created".
Definition event_type_registry.hpp:38
std::string_view kind_id
Full wire kind, e.g. "conduit:event:order.created".
Definition event_type_registry.hpp:39
parcel::DisplayInfo display_info() const
Cell-level display info, lifted straight from the descriptor.
Definition event_type_registry.hpp:43
parcel::json_t schema() const
Per-type JSON schema: {kind, display_info, category, fields:[…]}.
Definition event_type_registry.hpp:48
parcel::cell_type_descriptor_t descriptor
Definition event_type_registry.hpp:40
Self-registering object: constructing one registers T into global_event_types().
Definition event_type_registry.hpp:156
EventTypeRegistrar() noexcept
Definition event_type_registry.hpp:157