Skip to main content

vibe_code/
signals.rs

1//! Defines unique identifiers and system-wide signals for communication.
2//!
3//! This module provides the core vocabulary for different parts of the system
4//! to talk to each other. It includes unique IDs for nodes and queues, and an
5//! enum of `SystemSignal`s that report important events like a node being
6//! overloaded or a task finishing.
7
8use crate::task::TaskId;
9use std::fmt;
10use std::sync::atomic::{AtomicUsize, Ordering};
11
12/// A unique identifier for a `VibeNode`.
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
14pub struct NodeId(pub usize);
15
16/// An atomic counter to generate unique node IDs.
17static NEXT_NODE_ID: AtomicUsize = AtomicUsize::new(1);
18
19impl NodeId {
20    /// Creates a new, unique `NodeId`.
21    pub fn new() -> Self {
22        NodeId(NEXT_NODE_ID.fetch_add(1, Ordering::Relaxed))
23    }
24}
25
26impl Default for NodeId {
27    fn default() -> Self {
28        Self::new()
29    }
30}
31
32impl fmt::Display for NodeId {
33    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34        write!(f, "Node({})", self.0)
35    }
36}
37
38/// A unique identifier for a `VibeQueue`.
39#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
40pub struct QueueId(usize);
41
42/// An atomic counter to generate unique queue IDs.
43static NEXT_QUEUE_ID: AtomicUsize = AtomicUsize::new(1);
44
45impl QueueId {
46    /// Creates a new, unique `QueueId`.
47    pub fn new() -> Self {
48        QueueId(NEXT_QUEUE_ID.fetch_add(1, Ordering::Relaxed))
49    }
50}
51
52impl Default for QueueId {
53    fn default() -> Self {
54        Self::new()
55    }
56}
57
58impl fmt::Display for QueueId {
59    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60        write!(f, "Queue({})", self.0)
61    }
62}
63
64/// Represents operational events that are passed within the system.
65///
66/// These signals provide real-time feedback from nodes to the central system,
67/// allowing it to monitor health and make load-balancing decisions.
68#[derive(Debug, Clone)]
69pub enum SystemSignal {
70    /// Sent when a node's task queue is nearing its capacity.
71    NodeOverloaded {
72        node_id: NodeId,
73        queue_id: Option<QueueId>,
74    },
75    /// Sent when a previously overloaded node has cleared enough space in its queue.
76    NodeIdle {
77        node_id: NodeId,
78        queue_id: Option<QueueId>,
79    },
80    /// Sent by a worker just before it begins executing a task.
81    TaskDequeuedByWorker { node_id: NodeId, task_id: TaskId },
82    /// Sent by a worker after it has finished executing a task.
83    TaskProcessed {
84        node_id: NodeId,
85        task_id: TaskId,
86        /// The total time it took to execute the task, in microseconds.
87        duration_micros: u64,
88    },
89}
90
91impl SystemSignal {
92    /// A convenience method to get the `NodeId` from any signal type.
93    pub fn get_node_id(&self) -> NodeId {
94        match self {
95            SystemSignal::NodeOverloaded { node_id, .. } => *node_id,
96            SystemSignal::NodeIdle { node_id, .. } => *node_id,
97            SystemSignal::TaskDequeuedByWorker { node_id, .. } => *node_id,
98            SystemSignal::TaskProcessed { node_id, .. } => *node_id,
99        }
100    }
101}