meerkat_core/
runtime_epoch.rs1use std::sync::Arc;
10use std::sync::atomic::{AtomicU64, Ordering};
11
12use serde::{Deserialize, Serialize};
13use uuid::Uuid;
14
15use crate::completion_feed::CompletionSeq;
16use crate::ops_lifecycle::OpsLifecycleRegistry;
17use crate::types::SessionId;
18
19#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
26pub struct RuntimeEpochId(pub Uuid);
27
28impl RuntimeEpochId {
29 pub fn new() -> Self {
31 Self(Uuid::now_v7())
32 }
33
34 pub fn from_uuid(uuid: Uuid) -> Self {
36 Self(uuid)
37 }
38}
39
40impl Default for RuntimeEpochId {
41 fn default() -> Self {
42 Self::new()
43 }
44}
45
46impl std::fmt::Display for RuntimeEpochId {
47 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
48 write!(f, "{}", self.0)
49 }
50}
51
52pub struct EpochCursorState {
61 pub agent_applied_cursor: AtomicU64,
63 pub runtime_observed_seq: AtomicU64,
65 pub runtime_last_injected_seq: AtomicU64,
67}
68
69impl EpochCursorState {
70 pub fn new() -> Self {
72 Self {
73 agent_applied_cursor: AtomicU64::new(0),
74 runtime_observed_seq: AtomicU64::new(0),
75 runtime_last_injected_seq: AtomicU64::new(0),
76 }
77 }
78
79 pub fn from_recovered(
81 agent_applied_cursor: CompletionSeq,
82 runtime_observed_seq: CompletionSeq,
83 runtime_last_injected_seq: CompletionSeq,
84 ) -> Self {
85 Self {
86 agent_applied_cursor: AtomicU64::new(agent_applied_cursor),
87 runtime_observed_seq: AtomicU64::new(runtime_observed_seq),
88 runtime_last_injected_seq: AtomicU64::new(runtime_last_injected_seq),
89 }
90 }
91
92 pub fn snapshot(&self) -> EpochCursorSnapshot {
94 EpochCursorSnapshot {
95 agent_applied_cursor: self.agent_applied_cursor.load(Ordering::Acquire),
96 runtime_observed_seq: self.runtime_observed_seq.load(Ordering::Acquire),
97 runtime_last_injected_seq: self.runtime_last_injected_seq.load(Ordering::Acquire),
98 }
99 }
100}
101
102impl Default for EpochCursorState {
103 fn default() -> Self {
104 Self::new()
105 }
106}
107
108impl std::fmt::Debug for EpochCursorState {
109 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
110 f.debug_struct("EpochCursorState")
111 .field(
112 "agent_applied_cursor",
113 &self.agent_applied_cursor.load(Ordering::Relaxed),
114 )
115 .field(
116 "runtime_observed_seq",
117 &self.runtime_observed_seq.load(Ordering::Relaxed),
118 )
119 .field(
120 "runtime_last_injected_seq",
121 &self.runtime_last_injected_seq.load(Ordering::Relaxed),
122 )
123 .finish()
124 }
125}
126
127#[derive(Debug, Clone, Serialize, Deserialize)]
129pub struct EpochCursorSnapshot {
130 pub agent_applied_cursor: CompletionSeq,
131 pub runtime_observed_seq: CompletionSeq,
132 pub runtime_last_injected_seq: CompletionSeq,
133}
134
135pub struct SessionRuntimeBindings {
144 pub session_id: SessionId,
147 pub epoch_id: RuntimeEpochId,
150 pub ops_lifecycle: Arc<dyn OpsLifecycleRegistry>,
152 pub cursor_state: Arc<EpochCursorState>,
154}
155
156impl Clone for SessionRuntimeBindings {
157 fn clone(&self) -> Self {
158 Self {
159 session_id: self.session_id.clone(),
160 epoch_id: self.epoch_id.clone(),
161 ops_lifecycle: Arc::clone(&self.ops_lifecycle),
162 cursor_state: Arc::clone(&self.cursor_state),
163 }
164 }
165}
166
167impl std::fmt::Debug for SessionRuntimeBindings {
168 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
169 f.debug_struct("SessionRuntimeBindings")
170 .field("session_id", &self.session_id)
171 .field("epoch_id", &self.epoch_id)
172 .field("ops_lifecycle", &"<dyn OpsLifecycleRegistry>")
173 .field("cursor_state", &self.cursor_state)
174 .finish()
175 }
176}
177
178pub enum RuntimeBuildMode {
185 StandaloneEphemeral,
187 SessionOwned(SessionRuntimeBindings),
190}
191
192impl Clone for RuntimeBuildMode {
193 fn clone(&self) -> Self {
194 match self {
195 Self::StandaloneEphemeral => Self::StandaloneEphemeral,
196 Self::SessionOwned(b) => Self::SessionOwned(b.clone()),
197 }
198 }
199}
200
201impl std::fmt::Debug for RuntimeBuildMode {
202 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
203 match self {
204 Self::StandaloneEphemeral => write!(f, "StandaloneEphemeral"),
205 Self::SessionOwned(b) => f
206 .debug_tuple("SessionOwned")
207 .field(&b.session_id)
208 .field(&b.epoch_id)
209 .finish(),
210 }
211 }
212}