Skip to main content

oris_execution_runtime/
repository.rs

1//! Storage façade for runtime scheduler/lease operations.
2
3use chrono::{DateTime, Utc};
4
5use oris_kernel::event::KernelError;
6use oris_kernel::identity::{RunId, Seq};
7
8use super::models::{
9    AttemptDispatchRecord, BountyRecord, DisputeRecord, LeaseRecord, OrganismRecord, RecipeRecord,
10    SessionMessageRecord, SessionRecord, SwarmTaskRecord, WorkerRecord,
11};
12
13/// Runtime repository contract used by scheduler and lease manager.
14///
15/// Implementations are responsible for making dispatch ownership transitions
16/// explicit:
17/// - `list_dispatchable_attempts` must preserve the repository's dispatch order.
18/// - `upsert_lease` must atomically claim only dispatchable attempts and move
19///   the attempt into leased ownership when the claim succeeds.
20/// - `expire_leases_and_requeue` must reclaim only leases whose expiry is older
21///   than the supplied stale cutoff, so callers can apply a heartbeat grace
22///   window before requeueing work.
23pub trait RuntimeRepository: Send + Sync {
24    /// Return attempts eligible for dispatch at the current time.
25    fn list_dispatchable_attempts(
26        &self,
27        now: DateTime<Utc>,
28        limit: usize,
29    ) -> Result<Vec<AttemptDispatchRecord>, KernelError>;
30
31    /// Create or replace a lease for an attempt.
32    fn upsert_lease(
33        &self,
34        attempt_id: &str,
35        worker_id: &str,
36        lease_expires_at: DateTime<Utc>,
37    ) -> Result<LeaseRecord, KernelError>;
38
39    /// Refresh heartbeat for an existing lease.
40    fn heartbeat_lease(
41        &self,
42        lease_id: &str,
43        heartbeat_at: DateTime<Utc>,
44        lease_expires_at: DateTime<Utc>,
45    ) -> Result<(), KernelError>;
46
47    /// Expire stale leases and requeue affected attempts.
48    fn expire_leases_and_requeue(&self, stale_before: DateTime<Utc>) -> Result<u64, KernelError>;
49
50    /// Transition attempts that exceeded their configured execution timeout.
51    fn transition_timed_out_attempts(&self, _now: DateTime<Utc>) -> Result<u64, KernelError> {
52        Ok(0)
53    }
54
55    /// Returns latest persisted sequence for a run (used by replay wiring).
56    fn latest_seq_for_run(&self, run_id: &RunId) -> Result<Seq, KernelError>;
57
58    // ============== Bounty Methods ==============
59
60    /// Create or update a bounty
61    fn upsert_bounty(&self, bounty: &BountyRecord) -> Result<(), KernelError>;
62
63    /// Get a bounty by ID
64    fn get_bounty(&self, bounty_id: &str) -> Result<Option<BountyRecord>, KernelError>;
65
66    /// List bounties by status
67    fn list_bounties(
68        &self,
69        status: Option<&str>,
70        limit: usize,
71    ) -> Result<Vec<BountyRecord>, KernelError>;
72
73    /// Accept a bounty (transition to accepted)
74    fn accept_bounty(&self, bounty_id: &str, accepted_by: &str) -> Result<(), KernelError>;
75
76    /// Close a bounty (transition to closed)
77    fn close_bounty(&self, bounty_id: &str) -> Result<(), KernelError>;
78
79    // ============== Swarm Methods ==============
80
81    /// Create or update swarm task decomposition
82    fn upsert_swarm_decomposition(&self, task: &SwarmTaskRecord) -> Result<(), KernelError>;
83
84    /// Get swarm task decomposition
85    fn get_swarm_decomposition(
86        &self,
87        parent_task_id: &str,
88    ) -> Result<Option<SwarmTaskRecord>, KernelError>;
89
90    // ============== Worker Methods ==============
91
92    /// Register a worker
93    fn register_worker(&self, worker: &WorkerRecord) -> Result<(), KernelError>;
94
95    /// Get a worker by ID
96    fn get_worker(&self, worker_id: &str) -> Result<Option<WorkerRecord>, KernelError>;
97
98    /// List workers by domain and status
99    fn list_workers(
100        &self,
101        domain: Option<&str>,
102        status: Option<&str>,
103        limit: usize,
104    ) -> Result<Vec<WorkerRecord>, KernelError>;
105
106    /// Update worker heartbeat
107    fn heartbeat_worker(&self, worker_id: &str, heartbeat_at_ms: i64) -> Result<(), KernelError>;
108
109    // ============== Recipe Methods ==============
110
111    /// Create a recipe
112    fn create_recipe(&self, recipe: &RecipeRecord) -> Result<(), KernelError>;
113
114    /// Get a recipe by ID
115    fn get_recipe(&self, recipe_id: &str) -> Result<Option<RecipeRecord>, KernelError>;
116
117    /// Fork a recipe (create a copy with new ID)
118    fn fork_recipe(
119        &self,
120        original_id: &str,
121        new_id: &str,
122        new_author: &str,
123    ) -> Result<Option<RecipeRecord>, KernelError>;
124
125    /// List recipes by author
126    fn list_recipes(
127        &self,
128        author_id: Option<&str>,
129        limit: usize,
130    ) -> Result<Vec<RecipeRecord>, KernelError>;
131
132    // ============== Organism Methods ==============
133
134    /// Express a recipe as an organism
135    fn express_organism(&self, organism: &OrganismRecord) -> Result<(), KernelError>;
136
137    /// Get an organism by ID
138    fn get_organism(&self, organism_id: &str) -> Result<Option<OrganismRecord>, KernelError>;
139
140    /// Update organism status (step progression)
141    fn update_organism(
142        &self,
143        organism_id: &str,
144        current_step: i32,
145        status: &str,
146    ) -> Result<(), KernelError>;
147
148    // ============== Session Methods ==============
149
150    /// Create a collaborative session
151    fn create_session(&self, session: &SessionRecord) -> Result<(), KernelError>;
152
153    /// Get a session by ID
154    fn get_session(&self, session_id: &str) -> Result<Option<SessionRecord>, KernelError>;
155
156    /// Add a message to session history
157    fn add_session_message(&self, message: &SessionMessageRecord) -> Result<(), KernelError>;
158
159    /// Get session message history
160    fn get_session_history(
161        &self,
162        session_id: &str,
163        limit: usize,
164    ) -> Result<Vec<SessionMessageRecord>, KernelError>;
165
166    // ============== Dispute Methods ==============
167
168    /// Open a dispute
169    fn open_dispute(&self, dispute: &DisputeRecord) -> Result<(), KernelError>;
170
171    /// Get a dispute by ID
172    fn get_dispute(&self, dispute_id: &str) -> Result<Option<DisputeRecord>, KernelError>;
173
174    /// Get disputes for a bounty
175    fn get_disputes_for_bounty(&self, bounty_id: &str) -> Result<Vec<DisputeRecord>, KernelError>;
176
177    /// Resolve a dispute
178    fn resolve_dispute(
179        &self,
180        dispute_id: &str,
181        resolution: &str,
182        resolved_by: &str,
183    ) -> Result<(), KernelError>;
184}