1use actionqueue_core::budget::BudgetDimension;
8use actionqueue_core::ids::{ActorId, LedgerEntryId, RunId, TaskId, TenantId};
9use actionqueue_core::platform::{Capability, Role};
10use actionqueue_core::run::run_instance::RunInstance as CoreRunInstance;
11use actionqueue_core::subscription::{EventFilter, SubscriptionId};
12use actionqueue_core::task::task_spec::TaskSpec;
13
14use crate::recovery::reducer::{AttemptHistoryEntry, LeaseMetadata, RunStateHistoryEntry};
15
16#[derive(Debug, Clone, PartialEq, Eq)]
22#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
23pub struct Snapshot {
24 pub version: u32,
30 pub timestamp: u64,
34 pub metadata: SnapshotMetadata,
36 pub tasks: Vec<SnapshotTask>,
38 pub runs: Vec<SnapshotRun>,
40 #[cfg_attr(feature = "serde", serde(default))]
42 pub engine: SnapshotEngineControl,
43 #[cfg_attr(feature = "serde", serde(default))]
45 pub dependency_declarations: Vec<SnapshotDependencyDeclaration>,
46 #[cfg_attr(feature = "serde", serde(default))]
48 pub budgets: Vec<SnapshotBudget>,
49 #[cfg_attr(feature = "serde", serde(default))]
51 pub subscriptions: Vec<SnapshotSubscription>,
52 #[cfg_attr(feature = "serde", serde(default))]
54 pub actors: Vec<SnapshotActor>,
55 #[cfg_attr(feature = "serde", serde(default))]
57 pub tenants: Vec<SnapshotTenant>,
58 #[cfg_attr(feature = "serde", serde(default))]
60 pub role_assignments: Vec<SnapshotRoleAssignment>,
61 #[cfg_attr(feature = "serde", serde(default))]
63 pub capability_grants: Vec<SnapshotCapabilityGrant>,
64 #[cfg_attr(feature = "serde", serde(default))]
66 pub ledger_entries: Vec<SnapshotLedgerEntry>,
67}
68
69#[derive(Debug, Clone, PartialEq, Eq, Default)]
71#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
72pub struct SnapshotEngineControl {
73 pub paused: bool,
75 pub paused_at: Option<u64>,
77 pub resumed_at: Option<u64>,
79}
80
81#[derive(Debug, Clone, PartialEq, Eq)]
86#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
87pub struct SnapshotDependencyDeclaration {
88 pub task_id: TaskId,
90 pub depends_on: Vec<TaskId>,
92 pub declared_at: u64,
94}
95
96#[derive(Debug, Clone, PartialEq, Eq)]
101#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
102pub struct SnapshotMetadata {
103 pub schema_version: u32,
108 pub wal_sequence: u64,
113 pub task_count: u64,
115 pub run_count: u64,
117}
118
119#[derive(Debug, Clone, PartialEq, Eq)]
121#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
122pub struct SnapshotTask {
123 pub task_spec: TaskSpec,
125 pub created_at: u64,
127 pub updated_at: Option<u64>,
129 #[cfg_attr(feature = "serde", serde(default))]
131 pub canceled_at: Option<u64>,
132}
133
134#[derive(Debug, Clone, PartialEq, Eq)]
136#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
137pub struct SnapshotRun {
138 pub run_instance: CoreRunInstance,
144 pub state_history: Vec<SnapshotRunStateHistoryEntry>,
146 pub attempts: Vec<SnapshotAttemptHistoryEntry>,
148 pub lease: Option<SnapshotLeaseMetadata>,
150}
151
152impl SnapshotRun {
153 pub fn run_id(&self) -> RunId {
155 self.run_instance.id()
156 }
157}
158
159#[derive(Debug, Clone, PartialEq, Eq)]
161#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
162pub struct SnapshotRunStateHistoryEntry {
163 pub from: Option<actionqueue_core::run::state::RunState>,
165 pub to: actionqueue_core::run::state::RunState,
167 pub timestamp: u64,
169}
170
171impl From<RunStateHistoryEntry> for SnapshotRunStateHistoryEntry {
172 fn from(entry: RunStateHistoryEntry) -> Self {
173 Self { from: entry.from, to: entry.to, timestamp: entry.timestamp }
174 }
175}
176
177#[derive(Debug, Clone, PartialEq, Eq)]
179#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
180pub struct SnapshotAttemptHistoryEntry {
181 pub attempt_id: actionqueue_core::ids::AttemptId,
183 pub started_at: u64,
185 pub finished_at: Option<u64>,
187 pub result: Option<actionqueue_core::mutation::AttemptResultKind>,
189 pub error: Option<String>,
191 #[cfg_attr(feature = "serde", serde(default))]
193 pub output: Option<Vec<u8>>,
194}
195
196impl From<AttemptHistoryEntry> for SnapshotAttemptHistoryEntry {
197 fn from(entry: AttemptHistoryEntry) -> Self {
198 Self {
199 attempt_id: entry.attempt_id,
200 started_at: entry.started_at,
201 finished_at: entry.finished_at,
202 result: entry.result,
203 error: entry.error,
204 output: entry.output,
205 }
206 }
207}
208
209#[derive(Debug, Clone, PartialEq, Eq)]
211#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
212pub struct SnapshotLeaseMetadata {
213 pub owner: String,
215 pub expiry: u64,
217 pub acquired_at: u64,
219 pub updated_at: u64,
221}
222
223impl From<LeaseMetadata> for SnapshotLeaseMetadata {
224 fn from(metadata: LeaseMetadata) -> Self {
225 Self {
226 owner: metadata.owner,
227 expiry: metadata.expiry,
228 acquired_at: metadata.acquired_at,
229 updated_at: metadata.updated_at,
230 }
231 }
232}
233
234#[derive(Debug, Clone, PartialEq, Eq)]
236#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
237pub struct SnapshotBudget {
238 pub task_id: actionqueue_core::ids::TaskId,
240 pub dimension: BudgetDimension,
242 pub limit: u64,
244 pub consumed: u64,
246 pub allocated_at: u64,
248 pub exhausted: bool,
250}
251
252#[derive(Debug, Clone, PartialEq, Eq)]
254#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
255pub struct SnapshotSubscription {
256 pub subscription_id: SubscriptionId,
258 pub task_id: actionqueue_core::ids::TaskId,
260 pub filter: EventFilter,
262 pub created_at: u64,
264 pub triggered_at: Option<u64>,
266 pub canceled_at: Option<u64>,
268}
269
270#[derive(Debug, Clone, PartialEq, Eq)]
272#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
273pub struct SnapshotActor {
274 pub actor_id: ActorId,
275 pub identity: String,
276 pub capabilities: Vec<String>,
277 pub department: Option<String>,
278 pub heartbeat_interval_secs: u64,
279 pub tenant_id: Option<TenantId>,
280 pub registered_at: u64,
281 pub last_heartbeat_at: Option<u64>,
282 pub deregistered_at: Option<u64>,
283}
284
285#[derive(Debug, Clone, PartialEq, Eq)]
287#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
288pub struct SnapshotTenant {
289 pub tenant_id: TenantId,
290 pub name: String,
291 pub created_at: u64,
292}
293
294#[derive(Debug, Clone, PartialEq, Eq)]
296#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
297pub struct SnapshotRoleAssignment {
298 pub actor_id: ActorId,
299 pub role: Role,
300 pub tenant_id: TenantId,
301 pub assigned_at: u64,
302}
303
304#[derive(Debug, Clone, PartialEq, Eq)]
306#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
307pub struct SnapshotCapabilityGrant {
308 pub actor_id: ActorId,
309 pub capability: Capability,
310 pub tenant_id: TenantId,
311 pub granted_at: u64,
312 pub revoked_at: Option<u64>,
313}
314
315#[derive(Debug, Clone, PartialEq, Eq)]
317#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
318pub struct SnapshotLedgerEntry {
319 pub entry_id: LedgerEntryId,
320 pub tenant_id: TenantId,
321 pub ledger_key: String,
322 pub actor_id: Option<ActorId>,
323 pub payload: Vec<u8>,
324 pub timestamp: u64,
325}