// src/consensus/raft.rs use super::state::{RaftState, NodeState}; use crate::FutrumError; use std::sync::Arc; use tokio::sync::RwLock; use tokio::time::Duration; use uuid::Uuid; use rand; pub struct RaftConsensus { state: Arc>, node_id: String, peers: Vec, election_timeout: Duration, heartbeat_interval: Duration, enabled: bool, should_stop: Arc>, } impl RaftConsensus { pub fn new(enabled: bool, election_timeout_ms: u64, heartbeat_interval_ms: u64) -> Result { let node_id = Uuid::new_v4().to_string(); Ok(Self { state: Arc::new(RwLock::new(RaftState::new(node_id.clone()))), node_id, peers: Vec::new(), election_timeout: Duration::from_millis(election_timeout_ms), heartbeat_interval: Duration::from_millis(heartbeat_interval_ms), enabled, should_stop: Arc::new(RwLock::new(false)), }) } // Тихая версия запуска - БЕЗ ВЫВОДА В КОНСОЛЬ pub async fn start_silent(&self) -> Result<(), FutrumError> { if !self.enabled { return Ok(()); } let state = self.state.clone(); let node_id = self.node_id.clone(); let should_stop = self.should_stop.clone(); let election_timeout = self.election_timeout; let heartbeat_interval = self.heartbeat_interval; tokio::spawn(async move { let mut iteration_count = 0; while !*should_stop.read().await { iteration_count += 1; // ОГРАНИЧИВАЕМ активность - работаем только каждые 100 итераций if iteration_count % 100 != 0 { tokio::time::sleep(Duration::from_millis(10)).await; continue; } let current_state = { state.read().await.current_state }; match current_state { NodeState::Follower => { if Self::should_start_election_silent(&should_stop).await && !*should_stop.read().await { state.write().await.current_state = NodeState::Candidate; } } NodeState::Candidate => { if !*should_stop.read().await { let _ = Self::start_election_silent(state.clone()).await; } } NodeState::Leader => { // Минимальная активность в режиме лидера } } tokio::time::sleep(Duration::from_millis(10)).await; } }); Ok(()) } async fn should_start_election_silent(should_stop: &Arc>) -> bool { // Увеличиваем таймаут для уменьшения активности let timeout = rand::random::() % 1000 + 500; // 500-1500ms вместо 150-450ms tokio::time::sleep(Duration::from_millis(timeout.min(100))).await; true } async fn start_election_silent(state: Arc>) -> Result<(), FutrumError> { let mut state_guard = state.write().await; state_guard.current_term += 1; state_guard.voted_for = Some(state_guard.node_id.clone()); state_guard.vote_count = 1; if state_guard.vote_count > 0 { state_guard.current_state = NodeState::Leader; } Ok(()) } pub async fn is_leader(&self) -> bool { if !self.enabled { return false; } self.state.read().await.current_state == NodeState::Leader } pub async fn get_current_term(&self) -> u64 { self.state.read().await.current_term } pub async fn stop(&self) { *self.should_stop.write().await = true; } } impl Clone for RaftConsensus { fn clone(&self) -> Self { Self { state: self.state.clone(), node_id: self.node_id.clone(), peers: self.peers.clone(), election_timeout: self.election_timeout, heartbeat_interval: self.heartbeat_interval, enabled: self.enabled, should_stop: self.should_stop.clone(), } } }