From 7633985535c849901df3c36594b93eb72fb1075d Mon Sep 17 00:00:00 2001 From: Russell Gilbert Date: Fri, 13 Mar 2026 15:47:48 +0000 Subject: [PATCH] Rust: Establishes core organ communication framework Introduces `OrganFactory` to manage the creation and spawning of organs, running each in its own thread. `OrganSocket` provides the Brain's interface for sending timestamped commands to specific organs. Configures new MPSC channels within the Brain to handle bidirectional communication with its organs, enabling command dispatch and feedback reception. The Heart is integrated as the first example organ within this architecture. --- src/rustylee/src/brain.rs | 26 ++++++++++- src/rustylee/src/organs.rs | 4 +- src/rustylee/src/organs/heart.rs | 25 +++++++++-- src/rustylee/src/organs/organ_factory.rs | 56 ++++++++++++++++++++++++ src/rustylee/src/organs/organ_socket.rs | 32 ++++++++++++++ 5 files changed, 137 insertions(+), 6 deletions(-) create mode 100644 src/rustylee/src/organs/organ_factory.rs create mode 100644 src/rustylee/src/organs/organ_socket.rs diff --git a/src/rustylee/src/brain.rs b/src/rustylee/src/brain.rs index e61eb84..98c0f5f 100644 --- a/src/rustylee/src/brain.rs +++ b/src/rustylee/src/brain.rs @@ -1,24 +1,41 @@ use tracing::{debug, info}; use std::sync::mpsc::{Receiver, Sender}; +use std::thread::JoinHandle; use crate::lifecycle::{LifeState, LifecycleCommand, LifecycleCommandResponse, LifecycleReceipt}; use crate::lifecycle::LifeState::{Dying, Buried, Genisys}; +use crate::organs::organ_factory::OrganFactory; +use crate::organs::organ_socket::OrganSocket; +use crate::protocols::{BrainMessage, OrganCommand, OrganCommandEnvelope}; pub struct Brain { state:LifeState, divine_rx : Receiver, - divine_tx: Sender + divine_tx: Sender, + organ_rx: Receiver, + organ_tx: Sender, + organ_sockets: Vec, } impl Brain { pub fn new(divine_rx: Receiver, divine_tx: Sender) -> Self { + let (organ_tx, organ_rx) = std::sync::mpsc::channel::(); + Self { state: LifeState::Dead, divine_rx, divine_tx, + organ_rx, + organ_tx, + organ_sockets: Vec::new() } } pub fn run(&mut self) { + self.execute_brain_loop(); + self.build_organs(); + } + + fn execute_brain_loop(&mut self) { loop { while let Ok(command) = self.divine_rx.try_recv() { self.handle_divine_command(command) @@ -92,5 +109,12 @@ impl Brain { let _ = self.divine_tx.send(receipt); } + fn build_organs(& mut self) { + info!("Building organs..."); + + let factory = OrganFactory::new(self.organ_tx.clone()); + + info!("{} organs have been built and wired in.", self.organ_sockets.len()); + } } diff --git a/src/rustylee/src/organs.rs b/src/rustylee/src/organs.rs index 6833b1a..161060c 100644 --- a/src/rustylee/src/organs.rs +++ b/src/rustylee/src/organs.rs @@ -1,2 +1,4 @@ pub mod heart; -pub mod organ; \ No newline at end of file +pub mod organ; +pub mod organ_socket; +pub mod organ_factory; \ No newline at end of file diff --git a/src/rustylee/src/organs/heart.rs b/src/rustylee/src/organs/heart.rs index 98f34a8..6c3bcc6 100644 --- a/src/rustylee/src/organs/heart.rs +++ b/src/rustylee/src/organs/heart.rs @@ -1,12 +1,29 @@ use std::sync::mpsc; +use std::sync::mpsc::{Receiver, Sender}; use std::time::{SystemTime, UNIX_EPOCH}; use tracing::{info, instrument}; use crate::protocols::{BrainMessage, OrganCommandEnvelope, OrganResponse}; pub struct Heart { id: u32, - rx: mpsc::Receiver, - tx: mpsc::Sender, + brain_command_rx: mpsc::Receiver, + feedback_to_brain_tx: mpsc::Sender, +} + +impl Heart { + pub(crate) fn run_loop(&mut self) { + todo!() + } +} + +impl Heart { + pub(crate) fn new(id: u32, rx: Receiver, tx: Sender) -> Self { + Self { + id, + brain_command_rx: rx, + feedback_to_brain_tx: tx, + } + } } impl Heart { @@ -14,7 +31,7 @@ impl Heart { pub fn start(self) { info!("Heart listener active"); - while let Ok(envelope) = self.rx.recv() { + while let Ok(envelope) = self.brain_command_rx.recv() { // 1. Process the command (Logic goes here later) let response = OrganResponse::Ok; @@ -33,7 +50,7 @@ impl Heart { // 4. Trace the reply and send info!(?reply, "Sending response to Brain"); - let _ = self.tx.send(reply); + let _ = self.feedback_to_brain_tx.send(reply); } } } \ No newline at end of file diff --git a/src/rustylee/src/organs/organ_factory.rs b/src/rustylee/src/organs/organ_factory.rs new file mode 100644 index 0000000..8775d6e --- /dev/null +++ b/src/rustylee/src/organs/organ_factory.rs @@ -0,0 +1,56 @@ +use std::sync::mpsc::{self, Receiver, Sender}; +use std::thread; +use crate::organs::organ_socket::OrganSocket; +use crate::organs::heart::Heart; // Assuming Heart is our first organ +use crate::protocols::{OrganCommandEnvelope, BrainMessage}; + +pub struct OrganFactory { + brain_tx: Sender, +} + +impl OrganFactory { + pub(crate) fn new(brain_sender: Sender) -> Self { + Self { + brain_tx: brain_sender, + } + } +} + +impl OrganFactory { + pub fn build_organs( + // The Brain's "Inbox" mouth - we'll clone this for each organ + brain_tx: Sender + ) -> Vec { + let mut sockets = Vec::new(); + + // Let's spawn a Heart as an example (ID: 1) + // In a real factory, you might loop through a config list here + let heart_socket = Self::spawn_heart(1, brain_tx.clone()); + sockets.push(heart_socket); + + // Add more organs here... + // let lung_socket = Self::spawn_lung(2, brain_tx.clone()); + + tracing::info!(count = sockets.len(), "Organ collection built and threads spawned"); + + sockets + } + + fn spawn_heart(id: u32, feedback_to_brain_tx: Sender) -> OrganSocket { + let (brain_command_to_organ_tx, brain_command_to_organ_rx) = + Self::get_organ_channels(); + + let socket = OrganSocket::new(id, brain_command_to_organ_tx); + + thread::spawn(move || { + let mut heart = Heart::new(id, brain_command_to_organ_rx, feedback_to_brain_tx); + heart.run_loop(); + }); + + socket + } + + fn get_organ_channels() -> (Sender, Receiver) { + mpsc::channel::() + } +} \ No newline at end of file diff --git a/src/rustylee/src/organs/organ_socket.rs b/src/rustylee/src/organs/organ_socket.rs new file mode 100644 index 0000000..11ee018 --- /dev/null +++ b/src/rustylee/src/organs/organ_socket.rs @@ -0,0 +1,32 @@ +use std::time::{SystemTime, UNIX_EPOCH}; +use std::sync::mpsc::Sender; +use crate::protocols::{OrganCommand, OrganCommandEnvelope}; + +pub struct OrganSocket { + pub id: u32, + tx: Sender, +} + +impl OrganSocket { + pub fn new(id: u32, tx: Sender) -> Self { + Self { id, tx } + } + + pub fn send(&self, command: OrganCommand) { + // Here's the "Stamping" logic. + // The Brain just says "Beat", the Socket adds the "Metadata". + let now = SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap_or_default() + .as_millis() as u64; + + let envelope = OrganCommandEnvelope { + command, + issued_at: now, + }; + + if let Err(e) = self.tx.send(envelope) { + tracing::error!(organ_id = self.id, error = %e, "Socket delivery failed"); + } + } +} \ No newline at end of file