mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-12 16:16:55 +00:00
3b6397012b
- Add READY atomic flag to track full initialization status - Implement initialize_safe and start_safe methods with mutex protection - Add wait_until_ready function with configurable timeout - Create initialize_and_start_with_ready_check helper method - Replace sleep-based waiting with proper readiness checks - Add safety checks before sending events - Replace chrono with std::time for time handling - Update error handling to provide clear initialization status This change reduces race conditions in multi-threaded environments and ensures events are only processed when the system is fully ready.
69 lines
2.5 KiB
Rust
69 lines
2.5 KiB
Rust
use crate::ChannelAdapter;
|
|
use crate::Error;
|
|
use crate::EventStore;
|
|
use crate::{Event, Log};
|
|
use std::sync::Arc;
|
|
use std::time::{SystemTime, UNIX_EPOCH};
|
|
use tokio::sync::mpsc;
|
|
use tokio_util::sync::CancellationToken;
|
|
|
|
/// Handles incoming events from the producer.
|
|
///
|
|
/// This function is responsible for receiving events from the producer and sending them to the appropriate adapters.
|
|
/// It also handles the shutdown process and saves any pending logs to the event store.
|
|
pub async fn event_bus(
|
|
mut rx: mpsc::Receiver<Event>,
|
|
adapters: Vec<Arc<dyn ChannelAdapter>>,
|
|
store: Arc<EventStore>,
|
|
shutdown: CancellationToken,
|
|
) -> Result<(), Error> {
|
|
let mut pending_logs = Vec::new();
|
|
let mut current_log = Log {
|
|
event_name: crate::event::Name::Everything,
|
|
key: SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs().to_string(),
|
|
records: Vec::new(),
|
|
};
|
|
|
|
loop {
|
|
tokio::select! {
|
|
Some(event) = rx.recv() => {
|
|
current_log.records.push(event.clone());
|
|
let mut send_tasks = Vec::new();
|
|
for adapter in &adapters {
|
|
if event.channels.contains(&adapter.name()) {
|
|
let adapter = adapter.clone();
|
|
let event = event.clone();
|
|
send_tasks.push(tokio::spawn(async move {
|
|
if let Err(e) = adapter.send(&event).await {
|
|
tracing::error!("Failed to send event to {}: {}", adapter.name(), e);
|
|
Err(e)
|
|
} else {
|
|
Ok(())
|
|
}
|
|
}));
|
|
}
|
|
}
|
|
for task in send_tasks {
|
|
if task.await?.is_err() {
|
|
current_log.records.retain(|e| e.id != event.id);
|
|
}
|
|
}
|
|
if !current_log.records.is_empty() {
|
|
pending_logs.push(current_log.clone());
|
|
}
|
|
current_log.records.clear();
|
|
}
|
|
_ = shutdown.cancelled() => {
|
|
tracing::info!("Shutting down event bus, saving pending logs...");
|
|
if !current_log.records.is_empty() {
|
|
pending_logs.push(current_log);
|
|
}
|
|
store.save_logs(&pending_logs).await?;
|
|
break;
|
|
}
|
|
else => break,
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|