feat: implement orchestrator core (Rust)
Task 1.1: ✅ Cargo.toml with axum, rusqlite, matrix-sdk, serde, etc. Task 1.2: ✅ Directory structure: src/core, src/adapters, src/integrations, src/api Task 1.5: ✅ config.example.toml with full schema Task 2.1: ✅ Data models: Agent, Task, Receipt, Artifact, TaskEvent Task 2.2: ✅ Event Store: SQLite append-only with task/agent tables Task 2.3: ✅ Task state machine: created→assigned→running→completed/failed Task 2.4: ✅ Global task queue with priority ordering Task 2.5: ✅ Background timeout checker Task 2.6: ✅ Retry policy with configurable max_retries Compiles clean (warnings only, no errors). API handler stubs in place for Phase 2.
This commit is contained in:
parent
e983955036
commit
4e01728a67
15 changed files with 5220 additions and 3 deletions
58
src/core/task_queue.rs
Normal file
58
src/core/task_queue.rs
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
use std::sync::Arc;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use super::event_store::EventStore;
|
||||
use super::models::*;
|
||||
use super::state_machine::{StateError, StateMachine};
|
||||
|
||||
/// Global task queue ordered by priority.
|
||||
pub struct TaskQueue {
|
||||
sm: Arc<StateMachine>,
|
||||
store: Arc<Mutex<EventStore>>,
|
||||
}
|
||||
|
||||
impl TaskQueue {
|
||||
pub fn new(sm: Arc<StateMachine>, store: Arc<Mutex<EventStore>>) -> Self {
|
||||
Self { sm, store }
|
||||
}
|
||||
|
||||
/// Enqueue a new task (status = created).
|
||||
pub async fn enqueue(&self, task: Task) -> Result<Task, StateError> {
|
||||
self.sm.create_task(&task).await
|
||||
}
|
||||
|
||||
/// Dequeue the highest-priority task matching the given capabilities.
|
||||
pub async fn dequeue(
|
||||
&self,
|
||||
required_capabilities: &[String],
|
||||
) -> Result<Option<Task>, StateError> {
|
||||
let tasks = {
|
||||
let store = self.store.lock().await;
|
||||
store.query_queued_tasks()?
|
||||
};
|
||||
|
||||
if required_capabilities.is_empty() {
|
||||
return Ok(tasks.into_iter().next());
|
||||
}
|
||||
|
||||
for task in tasks {
|
||||
let all_match = required_capabilities
|
||||
.iter()
|
||||
.all(|cap| {
|
||||
task.labels.iter().any(|l| l == cap) || &task.task_type == cap
|
||||
});
|
||||
if all_match {
|
||||
return Ok(Some(task));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
/// Re-queue a failed/agent_lost task (increment retry_count).
|
||||
pub async fn requeue(&self, task_id: &str) -> Result<Task, StateError> {
|
||||
self.sm
|
||||
.transition(task_id, TaskStatus::Assigned, None, "re-queued after failure")
|
||||
.await
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue