ruvswarm_core/
task.rs

1//! Task definitions and task distribution logic
2
3#[cfg(not(feature = "std"))]
4use alloc::{
5    boxed::Box,
6    string::{String, ToString},
7    vec::Vec,
8};
9
10use core::fmt;
11
12/// Unique identifier for a task
13#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
14pub struct TaskId(pub String);
15
16impl TaskId {
17    /// Create a new task ID
18    pub fn new(id: impl Into<String>) -> Self {
19        TaskId(id.into())
20    }
21}
22
23impl fmt::Display for TaskId {
24    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25        write!(f, "{}", self.0)
26    }
27}
28
29/// Task priority levels
30#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
31#[derive(Default)]
32pub enum TaskPriority {
33    /// Low priority task - executed when no higher priority tasks are available
34    Low = 0,
35    /// Normal priority task - default priority level for most tasks
36    #[default]
37    Normal = 1,
38    /// High priority task - prioritized over normal and low priority tasks
39    High = 2,
40    /// Critical priority task - highest priority, executed immediately
41    Critical = 3,
42}
43
44
45/// Task status
46#[derive(Debug, Clone, Copy, PartialEq, Eq)]
47pub enum TaskStatus {
48    /// Task is waiting to be assigned
49    Pending,
50    /// Task has been assigned to an agent
51    Assigned,
52    /// Task is currently being processed
53    Running,
54    /// Task completed successfully
55    Completed,
56    /// Task failed
57    Failed,
58    /// Task was cancelled
59    Cancelled,
60    /// Task timed out
61    TimedOut,
62}
63
64/// Task definition
65#[derive(Debug, Clone)]
66pub struct Task {
67    /// Unique identifier for this task
68    pub id: TaskId,
69    /// Type of task (e.g., "compute", "io", "network")
70    pub task_type: String,
71    /// Priority level for task scheduling
72    pub priority: TaskPriority,
73    /// Task data payload
74    pub payload: TaskPayload,
75    /// List of capabilities required by agents to execute this task
76    pub required_capabilities: Vec<String>,
77    /// Optional timeout in milliseconds for task execution
78    pub timeout_ms: Option<u64>,
79    /// Current number of retry attempts
80    pub retry_count: u32,
81    /// Maximum number of retry attempts allowed
82    pub max_retries: u32,
83}
84
85impl Task {
86    /// Create a new task
87    pub fn new(id: impl Into<String>, task_type: impl Into<String>) -> Self {
88        Task {
89            id: TaskId::new(id),
90            task_type: task_type.into(),
91            priority: TaskPriority::Normal,
92            payload: TaskPayload::Empty,
93            required_capabilities: Vec::new(),
94            timeout_ms: None,
95            retry_count: 0,
96            max_retries: 3,
97        }
98    }
99
100    /// Set task priority
101    #[must_use]
102    pub fn with_priority(mut self, priority: TaskPriority) -> Self {
103        self.priority = priority;
104        self
105    }
106
107    /// Set task payload
108    #[must_use]
109    pub fn with_payload(mut self, payload: TaskPayload) -> Self {
110        self.payload = payload;
111        self
112    }
113
114    /// Add required capability
115    #[must_use]
116    pub fn require_capability(mut self, capability: impl Into<String>) -> Self {
117        self.required_capabilities.push(capability.into());
118        self
119    }
120
121    /// Set timeout
122    #[must_use]
123    pub fn with_timeout(mut self, timeout_ms: u64) -> Self {
124        self.timeout_ms = Some(timeout_ms);
125        self
126    }
127    
128    /// Check if task can be retried
129    pub fn can_retry(&self) -> bool {
130        self.retry_count < self.max_retries
131    }
132    
133    /// Increment retry count
134    pub fn increment_retry(&mut self) {
135        self.retry_count += 1;
136    }
137}
138
139/// Task payload variants
140#[derive(Debug, Clone)]
141pub enum TaskPayload {
142    /// Empty payload
143    Empty,
144    /// Text data
145    Text(String),
146    /// Binary data
147    Binary(Vec<u8>),
148    /// JSON data (as string)
149    Json(String),
150    /// Custom data
151    Custom(Box<dyn CustomPayload>),
152}
153
154/// Trait for custom task payloads
155pub trait CustomPayload: Send + Sync + fmt::Debug {
156    /// Clone the payload
157    fn clone_box(&self) -> Box<dyn CustomPayload>;
158}
159
160impl Clone for Box<dyn CustomPayload> {
161    fn clone(&self) -> Self {
162        self.clone_box()
163    }
164}
165
166/// Task result
167#[derive(Debug, Clone)]
168pub struct TaskResult {
169    /// The unique identifier of the task that was executed
170    pub task_id: TaskId,
171    /// Final status of the task execution
172    pub status: TaskStatus,
173    /// Optional output data produced by the task
174    pub output: Option<TaskOutput>,
175    /// Optional error message if the task failed
176    pub error: Option<String>,
177    /// Total execution time in milliseconds
178    pub execution_time_ms: u64,
179}
180
181impl TaskResult {
182    /// Create a successful task result
183    pub fn success(output: impl Into<TaskOutput>) -> Self {
184        TaskResult {
185            task_id: TaskId::new(""),
186            status: TaskStatus::Completed,
187            output: Some(output.into()),
188            error: None,
189            execution_time_ms: 0,
190        }
191    }
192
193    /// Create a failed task result
194    pub fn failure(error: impl Into<String>) -> Self {
195        TaskResult {
196            task_id: TaskId::new(""),
197            status: TaskStatus::Failed,
198            output: None,
199            error: Some(error.into()),
200            execution_time_ms: 0,
201        }
202    }
203
204    /// Set task ID
205    #[must_use]
206    pub fn with_task_id(mut self, task_id: TaskId) -> Self {
207        self.task_id = task_id;
208        self
209    }
210
211    /// Set execution time
212    #[must_use]
213    pub fn with_execution_time(mut self, time_ms: u64) -> Self {
214        self.execution_time_ms = time_ms;
215        self
216    }
217}
218
219/// Task output variants
220#[derive(Debug, Clone)]
221pub enum TaskOutput {
222    /// Text output
223    Text(String),
224    /// Binary output
225    Binary(Vec<u8>),
226    /// JSON output (as string)
227    Json(String),
228    /// No output
229    None,
230}
231
232impl From<String> for TaskOutput {
233    fn from(s: String) -> Self {
234        TaskOutput::Text(s)
235    }
236}
237
238impl From<&str> for TaskOutput {
239    fn from(s: &str) -> Self {
240        TaskOutput::Text(s.to_string())
241    }
242}
243
244impl From<Vec<u8>> for TaskOutput {
245    fn from(bytes: Vec<u8>) -> Self {
246        TaskOutput::Binary(bytes)
247    }
248}
249
250/// Task distribution strategy
251#[derive(Debug, Clone, Copy, PartialEq, Eq)]
252#[derive(Default)]
253pub enum DistributionStrategy {
254    /// Round-robin distribution
255    RoundRobin,
256    /// Least loaded agent first
257    #[default]
258    LeastLoaded,
259    /// Random distribution
260    Random,
261    /// Priority-based distribution
262    Priority,
263    /// Capability-based distribution
264    CapabilityBased,
265}
266