NeoGraph 0.16.0
A C++20 Graph Agent Engine Library — LangGraph for C++
Loading...
Searching...
No Matches
store.h
Go to the documentation of this file.
1
5#pragma once
6
7#include <neograph/api.h>
12
13#include <cstddef>
14#include <asio/awaitable.hpp>
15
16#include <cstdint>
17#include <memory>
18#include <optional>
19#include <stdexcept>
20#include <string>
21#include <string_view>
22#include <vector>
23
24namespace neograph::program {
26struct NEOGRAPH_PROGRAM_API ProgramActivationBinding {
27 ProgramActivation activation;
28 ProgramVersion version;
29};
30
36class NEOGRAPH_PROGRAM_API ProgramStore {
37public:
38 virtual ~ProgramStore() = default;
39
46 [[nodiscard]] virtual asio::awaitable<void> publish_admitted(
47 const ProgramBundle& bundle,
48 const ProgramVersion& version) = 0;
49 [[nodiscard]] virtual asio::awaitable<std::optional<ProgramBundle>> get_bundle(std::string_view id) const = 0;
50 [[nodiscard]] virtual asio::awaitable<std::optional<ProgramVersion>> get_version(std::string_view id) const = 0;
51
58 [[nodiscard]] virtual asio::awaitable<std::optional<ProgramBundle>> get_bundle(
59 std::string_view /*owner_scope*/,
60 std::string_view /*id*/) const {
61 co_return std::nullopt;
62 }
63 [[nodiscard]] virtual asio::awaitable<std::optional<ProgramVersion>> get_version(
64 std::string_view owner_scope,
65 std::string_view id) const {
66 if (owner_scope.empty()) co_return std::nullopt;
67 const auto value = co_await get_version(id);
68 if (!value || value->ownership_scope() != owner_scope) co_return std::nullopt;
69 co_return value;
70 }
71
78 [[nodiscard]] virtual asio::awaitable<std::optional<ProgramActivation>> get_activation(
79 std::string_view /*owner_scope*/) const {
80 return detail::failed_store_call<std::optional<ProgramActivation>>(
81 std::make_exception_ptr(std::logic_error("ProgramStore does not expose activation lifecycle")));
82 }
88 [[nodiscard]] virtual asio::awaitable<std::optional<ProgramActivationBinding>> get_active_binding(
89 std::string_view owner_scope) const {
90 const auto active = co_await get_activation(owner_scope);
91 if (!active) co_return std::nullopt;
92 const auto version = co_await get_version(owner_scope, active->active_version_id());
93 if (!version || version->policy_snapshot().fingerprint() != active->policy_snapshot_hash())
94 throw std::runtime_error("Program activation target is missing or has a mismatched policy");
95 co_return ProgramActivationBinding{*active, *version};
96 }
97 [[nodiscard]] virtual asio::awaitable<ProgramActivationResult> compare_activate(
98 std::string_view /*owner_scope*/,
99 std::uint64_t /*expected_generation*/,
100 std::string_view /*version_id*/,
101 std::string_view /*policy_snapshot_hash*/) {
102 return detail::failed_store_call<ProgramActivationResult>(
103 std::make_exception_ptr(std::logic_error("ProgramStore does not expose activation lifecycle")));
104 }
105 [[nodiscard]] virtual asio::awaitable<std::vector<ProgramVersion>> list_versions(
106 std::string_view /*owner_scope*/) const {
107 return detail::failed_store_call<std::vector<ProgramVersion>>(
108 std::make_exception_ptr(std::logic_error("ProgramStore does not enumerate versions")));
109 }
110 [[nodiscard]] virtual asio::awaitable<ProgramRetentionReport> collect_garbage(
111 std::string_view /*owner_scope*/,
112 const std::vector<std::string>& /*pinned_version_ids*/) {
113 return detail::failed_store_call<ProgramRetentionReport>(
114 std::make_exception_ptr(std::logic_error("ProgramStore does not expose retention lifecycle")));
115 }
116};
117
123class NEOGRAPH_PROGRAM_API SyncProgramStore : public ProgramStore {
124public:
125 // The synchronous operations. Each has the contract of the awaitable operation of the same name.
126 virtual void publish_admitted_sync(const ProgramBundle& bundle, const ProgramVersion& version) = 0;
127 virtual std::optional<ProgramBundle> get_bundle_sync(std::string_view id) const = 0;
128 virtual std::optional<ProgramVersion> get_version_sync(std::string_view id) const = 0;
129 virtual std::optional<ProgramBundle> get_bundle_sync(
130 std::string_view /*owner_scope*/,
131 std::string_view /*id*/) const {
132 return std::nullopt;
133 }
134 virtual std::optional<ProgramVersion> get_version_sync(
135 std::string_view owner_scope,
136 std::string_view id) const {
137 if (owner_scope.empty()) return std::nullopt;
138 const auto value = get_version_sync(id);
139 if (!value || value->ownership_scope() != owner_scope) return std::nullopt;
140 return value;
141 }
142 virtual std::optional<ProgramActivation> get_activation_sync(
143 std::string_view /*owner_scope*/) const {
144 throw std::logic_error("ProgramStore does not expose activation lifecycle");
145 }
146 virtual std::optional<ProgramActivationBinding> get_active_binding_sync(
147 std::string_view owner_scope) const {
148 const auto active = get_activation_sync(owner_scope);
149 if (!active) return std::nullopt;
150 const auto version = get_version_sync(owner_scope, active->active_version_id());
151 if (!version || version->policy_snapshot().fingerprint() != active->policy_snapshot_hash())
152 throw std::runtime_error("Program activation target is missing or has a mismatched policy");
153 return ProgramActivationBinding{*active, *version};
154 }
155 virtual ProgramActivationResult compare_activate_sync(
156 std::string_view /*owner_scope*/,
157 std::uint64_t /*expected_generation*/,
158 std::string_view /*version_id*/,
159 std::string_view /*policy_snapshot_hash*/) {
160 throw std::logic_error("ProgramStore does not expose activation lifecycle");
161 }
162 virtual std::vector<ProgramVersion> list_versions_sync(
163 std::string_view /*owner_scope*/) const {
164 throw std::logic_error("ProgramStore does not enumerate versions");
165 }
166 virtual ProgramRetentionReport collect_garbage_sync(
167 std::string_view /*owner_scope*/,
168 const std::vector<std::string>& /*pinned_version_ids*/) {
169 throw std::logic_error("ProgramStore does not expose retention lifecycle");
170 }
171
172 // The awaitable interface, completed by the operations above: at once on the calling thread,
173 // or on a thread of a bounded pool when offloads() is true.
174 [[nodiscard]] asio::awaitable<void> publish_admitted(
175 const ProgramBundle& bundle,
176 const ProgramVersion& version) final;
177 [[nodiscard]] asio::awaitable<std::optional<ProgramBundle>> get_bundle(std::string_view id) const final;
178 [[nodiscard]] asio::awaitable<std::optional<ProgramVersion>> get_version(std::string_view id) const final;
179 [[nodiscard]] asio::awaitable<std::optional<ProgramBundle>> get_bundle(
180 std::string_view owner_scope,
181 std::string_view id) const final;
182 [[nodiscard]] asio::awaitable<std::optional<ProgramVersion>> get_version(
183 std::string_view owner_scope,
184 std::string_view id) const final;
185 [[nodiscard]] asio::awaitable<std::optional<ProgramActivation>> get_activation(
186 std::string_view owner_scope) const final;
187 [[nodiscard]] asio::awaitable<std::optional<ProgramActivationBinding>> get_active_binding(
188 std::string_view owner_scope) const final;
189 [[nodiscard]] asio::awaitable<ProgramActivationResult> compare_activate(
190 std::string_view owner_scope,
191 std::uint64_t expected_generation,
192 std::string_view version_id,
193 std::string_view policy_snapshot_hash) final;
194 [[nodiscard]] asio::awaitable<std::vector<ProgramVersion>> list_versions(
195 std::string_view owner_scope) const final;
196 [[nodiscard]] asio::awaitable<ProgramRetentionReport> collect_garbage(
197 std::string_view owner_scope,
198 const std::vector<std::string>& pinned_version_ids) final;
199
201 bool completes_at_once() const noexcept { return !offloads(); }
202
203protected:
205 virtual bool offloads() const noexcept { return false; }
206};
207
212class NEOGRAPH_PROGRAM_API BlockingProgramStore {
213public:
214 BlockingProgramStore(std::shared_ptr<ProgramStore> store, BlockingStorePolicy policy = {});
217
218 const std::shared_ptr<ProgramStore>& store() const noexcept { return store_; }
219
220 void publish_admitted(const ProgramBundle& bundle, const ProgramVersion& version) const;
221 std::optional<ProgramBundle> get_bundle(std::string_view id) const;
222 std::optional<ProgramVersion> get_version(std::string_view id) const;
223 std::optional<ProgramBundle> get_bundle(std::string_view owner_scope, std::string_view id) const;
224 std::optional<ProgramVersion> get_version(std::string_view owner_scope, std::string_view id) const;
225 std::optional<ProgramActivation> get_activation(std::string_view owner_scope) const;
226 std::optional<ProgramActivationBinding> get_active_binding(std::string_view owner_scope) const;
227 ProgramActivationResult compare_activate(
228 std::string_view owner_scope,
229 std::uint64_t expected_generation,
230 std::string_view version_id,
231 std::string_view policy_snapshot_hash) const;
232 std::vector<ProgramVersion> list_versions(std::string_view owner_scope) const;
233 ProgramRetentionReport collect_garbage(
234 std::string_view owner_scope,
235 const std::vector<std::string>& pinned_version_ids) const;
236
237private:
238 std::shared_ptr<ProgramStore> store_;
239 SyncProgramStore* sync_ = nullptr;
240 BlockingStorePolicy policy_;
241};
242
243class NEOGRAPH_PROGRAM_API InMemoryProgramStore final : public SyncProgramStore {
244public:
245 InMemoryProgramStore();
246 InMemoryProgramStore(InMemoryProgramStore&&) noexcept;
247 InMemoryProgramStore& operator=(InMemoryProgramStore&&) noexcept;
248 InMemoryProgramStore(const InMemoryProgramStore&) = delete;
249 InMemoryProgramStore& operator=(const InMemoryProgramStore&) = delete;
250 ~InMemoryProgramStore() override;
251
252 void publish_admitted_sync(const ProgramBundle& bundle, const ProgramVersion& version) override;
253 std::optional<ProgramBundle> get_bundle_sync(std::string_view id) const override;
254 std::optional<ProgramVersion> get_version_sync(std::string_view id) const override;
255 std::optional<ProgramBundle> get_bundle_sync(std::string_view owner_scope,
256 std::string_view id) const override;
257 std::optional<ProgramVersion> get_version_sync(std::string_view owner_scope,
258 std::string_view id) const override;
259 std::optional<ProgramActivation>
260 get_activation_sync(std::string_view owner_scope) const override;
261 std::optional<ProgramActivationBinding>
262 get_active_binding_sync(std::string_view owner_scope) const override;
263 ProgramActivationResult compare_activate_sync(std::string_view owner_scope,
264 std::uint64_t expected_generation,
265 std::string_view version_id,
266 std::string_view policy_snapshot_hash) override;
267 std::vector<ProgramVersion> list_versions_sync(std::string_view owner_scope) const override;
268 ProgramRetentionReport collect_garbage_sync(
269 std::string_view owner_scope,
270 const std::vector<std::string>& pinned_version_ids) override;
271
272private:
273 struct Impl;
274 std::unique_ptr<Impl> impl_;
275};
276
277} // namespace neograph::program
Owner-scoped activation records for immutable Program versions.
ProgramActivationResult
Result of an atomic owner-scoped activation compare-and-swap.
Definition activation.h:20
NEOGRAPH_API export/import macro for shared-library builds.
Immutable, content-addressed Program compilation artifacts.
A ProgramStore for a caller that cannot suspend: the catalog and the synchronous Program API.
Definition store.h:212
BlockingProgramStore(ProgramStore &store, BlockingStorePolicy policy={})
A view of a store that outlives it.
Atomic storage of admitted Program bundles and versions, as the catalog uses it (#556).
Definition store.h:36
virtual asio::awaitable< std::optional< ProgramBundle > > get_bundle(std::string_view, std::string_view) const
Owner-qualified lookups.
Definition store.h:58
virtual asio::awaitable< void > publish_admitted(const ProgramBundle &bundle, const ProgramVersion &version)=0
Atomically publish one admitted bundle/version tuple.
virtual asio::awaitable< std::optional< ProgramActivation > > get_activation(std::string_view) const
Owner-scoped activation lifecycle.
Definition store.h:78
virtual asio::awaitable< std::optional< ProgramActivationBinding > > get_active_binding(std::string_view owner_scope) const
Return one coherent activation/version tuple.
Definition store.h:88
Base of a ProgramStore whose backend is synchronous: the in-memory store, SQLite and PostgreSQL.
Definition store.h:123
asio::awaitable< std::optional< ProgramBundle > > get_bundle(std::string_view owner_scope, std::string_view id) const final
Owner-qualified lookups.
asio::awaitable< std::optional< ProgramActivationBinding > > get_active_binding(std::string_view owner_scope) const final
Return one coherent activation/version tuple.
bool completes_at_once() const noexcept
True when every awaitable operation completes at once on the calling thread, not on a pool thread.
Definition store.h:201
virtual bool offloads() const noexcept
True for a backend that blocks for long: each operation then runs on a pool thread.
Definition store.h:205
asio::awaitable< void > publish_admitted(const ProgramBundle &bundle, const ProgramVersion &version) final
Atomically publish one admitted bundle/version tuple.
asio::awaitable< std::optional< ProgramActivation > > get_activation(std::string_view owner_scope) const final
Owner-scoped activation lifecycle.
How a Program store call is awaited, and how a synchronous caller waits for one (#556).
When a Blocking...Store may wait for a store call that does not complete at once.
Definition store_call.h:39
Coherent owner-scoped activation pointer and its admitted immutable target.
Definition store.h:26
Counts immutable records removed by reference-aware collection.
Definition activation.h:68
Immutable stored binding between a Program bundle and admission receipts.