This commit is contained in:
2026-04-25 22:53:36 +02:00
parent b034fdf1c4
commit 60b8841895
8 changed files with 695 additions and 15 deletions

View File

@@ -48,6 +48,11 @@ pub struct WsManager {
std::option::Option<tokio::sync::mpsc::Sender<crate::KbWsDetectionNotificationEnvelope>>,
>,
detection_relay_abort_handle: tokio::sync::Mutex<std::option::Option<tokio::task::AbortHandle>>,
transaction_resolution_relay_sender: tokio::sync::Mutex<
std::option::Option<tokio::sync::mpsc::Sender<crate::KbWsTransactionResolutionEnvelope>>,
>,
transaction_resolution_relay_abort_handle:
tokio::sync::Mutex<std::option::Option<tokio::task::AbortHandle>>,
}
impl WsManager {
@@ -97,6 +102,8 @@ impl WsManager {
event_tx,
detection_relay_sender: tokio::sync::Mutex::new(None),
detection_relay_abort_handle: tokio::sync::Mutex::new(None),
transaction_resolution_relay_sender: tokio::sync::Mutex::new(None),
transaction_resolution_relay_abort_handle: tokio::sync::Mutex::new(None),
})
}
@@ -202,6 +209,15 @@ impl WsManager {
if let Some(sender) = sender_option {
client.set_detection_notification_forwarder(sender).await;
}
let tx_resolution_sender_option = {
let sender_guard = self.transaction_resolution_relay_sender.lock().await;
sender_guard.clone()
};
if let Some(sender) = tx_resolution_sender_option {
client
.set_transaction_resolution_notification_forwarder(sender)
.await;
}
let connect_result = client.connect().await;
if let Err(error) = connect_result {
return Err(error);
@@ -236,6 +252,9 @@ impl WsManager {
return Ok(false);
}
client.clear_detection_notification_forwarder().await;
client
.clear_transaction_resolution_notification_forwarder()
.await;
let disconnect_result = client.disconnect().await;
if let Err(error) = disconnect_result {
return Err(error);
@@ -433,6 +452,82 @@ impl WsManager {
};
Ok(client.connection_state().await)
}
/// Attaches one shared transaction-resolution relay to all managed clients.
pub async fn attach_transaction_resolution_relay(
&self,
database: std::sync::Arc<crate::KbDatabase>,
http_pool: std::sync::Arc<crate::HttpEndpointPool>,
http_role: std::string::String,
queue_capacity: usize,
) -> Result<(), crate::KbError> {
{
let sender_guard = self.transaction_resolution_relay_sender.lock().await;
if sender_guard.is_some() {
return Err(crate::KbError::InvalidState(
"websocket transaction resolution relay is already attached".to_string(),
));
}
}
let persistence = crate::KbDetectionPersistenceService::new(database);
let resolver =
crate::KbTransactionResolutionService::new(http_pool, persistence, http_role);
let relay = crate::KbWsTransactionResolutionRelay::new(resolver);
let (sender, receiver) = crate::KbWsTransactionResolutionRelay::channel(queue_capacity);
let relay_task = relay.spawn(receiver);
let relay_abort_handle = relay_task.abort_handle();
{
let mut sender_guard = self.transaction_resolution_relay_sender.lock().await;
*sender_guard = Some(sender.clone());
}
{
let mut abort_guard = self.transaction_resolution_relay_abort_handle.lock().await;
*abort_guard = Some(relay_abort_handle);
}
let clients = {
let clients_guard = self.clients.lock().await;
let mut values = std::vec::Vec::new();
for managed in clients_guard.values() {
values.push(managed.client.clone());
}
values
};
for client in clients {
client
.set_transaction_resolution_notification_forwarder(sender.clone())
.await;
}
Ok(())
}
/// Detaches the shared transaction-resolution relay from all managed clients.
pub async fn detach_transaction_resolution_relay(&self) -> Result<(), crate::KbError> {
let clients = {
let clients_guard = self.clients.lock().await;
let mut values = std::vec::Vec::new();
for managed in clients_guard.values() {
values.push(managed.client.clone());
}
values
};
for client in clients {
client
.clear_transaction_resolution_notification_forwarder()
.await;
}
{
let mut sender_guard = self.transaction_resolution_relay_sender.lock().await;
*sender_guard = None;
}
let abort_handle_option = {
let mut abort_guard = self.transaction_resolution_relay_abort_handle.lock().await;
abort_guard.take()
};
if let Some(abort_handle) = abort_handle_option {
abort_handle.abort();
}
Ok(())
}
}
impl Drop for WsManager {
@@ -449,6 +544,12 @@ impl Drop for WsManager {
abort_handle.abort();
}
}
let tx_resolution_abort_result = self.transaction_resolution_relay_abort_handle.try_lock();
if let Ok(mut abort_guard) = tx_resolution_abort_result {
if let Some(abort_handle) = abort_guard.take() {
abort_handle.abort();
}
}
}
}