NGen
Loading...
Searching...
No Matches
record_backend.hpp
1/*
2Author: Nels Frazier
3Copyright (C) 2025 Lynker
4------------------------------------------------------------------------
5Licensed under the Apache License, Version 2.0 (the "License");
6you may not use this file except in compliance with the License.
7You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11Unless required by applicable law or agreed to in writing, software
12distributed under the License is distributed on an "AS IS" BASIS,
13WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14See the License for the specific language governing permissions and
15limitations under the License.
16------------------------------------------------------------------------
17Abstract record-storage interface.
18
19`RecordBackend` is the engine-agnostic abstraction over "how
20does this `Record` end up persisted and retrievable later."
21Concrete backends implement the interface and choose their own
22storage details; the abstract surface is silent on byte layout.
23
24This file declares the abstract surface and per-method API
25contracts. Cross-cutting design — sub-handle lifetime patterns,
26error categorization, single-in-flight rule, durability,
27identity, recommended call patterns — lives in this directory's
28README.md; that's the discoverable reference for backend
29implementers.
30*/
31#pragma once
32
33#include "id_predicates.hpp"
34#include "record.hpp"
35
36#include <nonstd/expected.hpp>
37
38#include <chrono>
39#include <cstdint>
40#include <memory>
41#include <string>
42#include <vector>
43
44namespace ngen{ namespace serialization{
45
46// Pull `expected` and `make_unexpected` into the library namespace
47// so signatures below stay unqualified. Switching the underlying
48// implementation (e.g. to std::expected when the codebase moves to
49// C++23) is a one-line change here.
50using nonstd::expected;
51using nonstd::make_unexpected;
52
59enum class Durability { relaxed, strict };
60
71 enum class Kind { NotFound, Corrupted, IOError };
73 std::string message;
74
75 BackendError() = default;
76 BackendError(Kind k, std::string m)
77 : kind(k), message(std::move(m)) {}
78};
79
84public:
88 class Writer {
89 public:
90 virtual ~Writer() = default;
91
98 [[nodiscard]] virtual auto write(const RecordView& rv)
99 -> expected<void, BackendError> = 0;
100
107 [[nodiscard]] virtual auto commit()
108 -> expected<void, BackendError> = 0;
109 };
110
117 class Reader {
118 public:
119 virtual ~Reader() = default;
120
124 [[nodiscard]] virtual auto find_latest(const std::string& id)
125 -> expected<Record, BackendError> = 0;
126
130 [[nodiscard]] virtual auto find_at_step(const std::string& id,
131 int64_t time_step)
132 -> expected<Record, BackendError> = 0;
133
138 [[nodiscard]] virtual auto
139 find_at_simulation_timestamp(const std::string& id,
140 int64_t simulation_timestamp)
141 -> expected<Record, BackendError> = 0;
142
148 [[nodiscard]] virtual auto close() -> expected<void, BackendError> {
149 return {};
150 }
151 };
152
153 virtual ~RecordBackend() = default;
154
160 [[nodiscard]] virtual auto
161 writer(std::chrono::system_clock::time_point epoch,
162 Durability durability)
163 -> expected<std::unique_ptr<Writer>, BackendError> = 0;
164
170 [[nodiscard]] virtual auto reader(IdPredicate in_scope = {})
171 -> expected<std::unique_ptr<Reader>, BackendError> = 0;
172
197 [[nodiscard]] virtual auto finalize()
198 -> expected<void, std::vector<BackendError>> = 0;
199
200 // Scoped convenience wrappers — recommended call pattern.
201 // Non-virtual; concrete backends do not override them. See
202 // the README for why they exist and what they enforce.
203
208 template <typename F>
209 [[nodiscard]] auto with_writer(std::chrono::system_clock::time_point epoch,
210 Durability durability, F&& fn)
211 -> expected<void, BackendError>
212 {
213 auto wo = writer(epoch, durability);
214 if (!wo) return make_unexpected(std::move(wo.error()));
215 std::forward<F>(fn)(*wo.value());
216 return wo.value()->commit();
217 }
218
223 template <typename F>
224 [[nodiscard]] auto with_reader(IdPredicate in_scope, F&& fn)
225 -> expected<void, BackendError>
226 {
227 auto ro = reader(std::move(in_scope));
228 if (!ro) return make_unexpected(std::move(ro.error()));
229 std::forward<F>(fn)(*ro.value());
230 return ro.value()->close();
231 }
232};
233
234}} // namespace ngen::serialization
A read handle for one restore session.
Definition record_backend.hpp:117
virtual auto close() -> expected< void, BackendError >
Optional explicit close.
Definition record_backend.hpp:148
virtual auto find_at_step(const std::string &id, int64_t time_step) -> expected< Record, BackendError >=0
Return the record for id at the given simulation step.
virtual auto find_at_simulation_timestamp(const std::string &id, int64_t simulation_timestamp) -> expected< Record, BackendError >=0
Return the record for id at the given simulation timestamp (seconds since Unix epoch).
virtual auto find_latest(const std::string &id) -> expected< Record, BackendError >=0
Return the latest record for id within this Reader's scope.
A writer for one checkpoint event.
Definition record_backend.hpp:88
virtual auto write(const RecordView &rv) -> expected< void, BackendError >=0
Append a record to this checkpoint event.
virtual auto commit() -> expected< void, BackendError >=0
Commit the event: flush pending writes, make them durable (under Durability::strict),...
Abstract storage interface for Records.
Definition record_backend.hpp:83
virtual auto writer(std::chrono::system_clock::time_point epoch, Durability durability) -> expected< std::unique_ptr< Writer >, BackendError >=0
Construct a Writer for one checkpoint event.
auto with_reader(IdPredicate in_scope, F &&fn) -> expected< void, BackendError >
Run fn inside a scoped Reader; calls close() automatically on success.
Definition record_backend.hpp:224
auto with_writer(std::chrono::system_clock::time_point epoch, Durability durability, F &&fn) -> expected< void, BackendError >
Run fn inside a scoped Writer; calls commit() automatically on success.
Definition record_backend.hpp:209
virtual auto reader(IdPredicate in_scope={}) -> expected< std::unique_ptr< Reader >, BackendError >=0
Construct a Reader scoped to records whose id satisfies in_scope.
virtual auto finalize() -> expected< void, std::vector< BackendError > >=0
Lifecycle hook for cross-event cleanup: close process-level open handles, drain async queues,...
std::function< bool(const std::string &id)> IdPredicate
Eligibility predicate over a SerializationRecord's id string.
Definition id_predicates.hpp:56
Durability
Save-time durability requirement.
Definition record_backend.hpp:59
Definition DomainLayer.hpp:13
STL namespace.
Categorized error carried on every abstract-backend method's expected<> error arm.
Definition record_backend.hpp:70
Kind kind
Definition record_backend.hpp:72
BackendError(Kind k, std::string m)
Definition record_backend.hpp:76
Kind
Definition record_backend.hpp:71
std::string message
Definition record_backend.hpp:73
Definition record.hpp:151