factor out last async mutex
This commit is contained in:
@@ -20,13 +20,17 @@ use http::{Method, Request, Response, StatusCode};
|
|||||||
use http_body::Body;
|
use http_body::Body;
|
||||||
use http_body_util::BodyExt;
|
use http_body_util::BodyExt;
|
||||||
use prometheus_http_client::{AlertStatus, ExtractLabels};
|
use prometheus_http_client::{AlertStatus, ExtractLabels};
|
||||||
use std::{collections::HashMap, fmt::Write, net::SocketAddr, path::PathBuf, time::Duration};
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
|
fmt::Write,
|
||||||
|
net::SocketAddr,
|
||||||
|
path::PathBuf,
|
||||||
|
sync::Mutex,
|
||||||
|
time::Duration,
|
||||||
|
};
|
||||||
use tokio::{
|
use tokio::{
|
||||||
join,
|
join,
|
||||||
sync::{
|
sync::mpsc::{UnboundedReceiver, UnboundedSender, unbounded_channel},
|
||||||
Mutex,
|
|
||||||
mpsc::{UnboundedReceiver, UnboundedSender, unbounded_channel},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
use tokio_util::{bytes::Buf, sync::CancellationToken};
|
use tokio_util::{bytes::Buf, sync::CancellationToken};
|
||||||
use tracing::{debug, error, info, warn};
|
use tracing::{debug, error, info, warn};
|
||||||
@@ -216,7 +220,9 @@ impl SignalAlertMessage {
|
|||||||
pub struct Gateway {
|
pub struct Gateway {
|
||||||
config: GatewayConfig,
|
config: GatewayConfig,
|
||||||
signal_alert_mq_tx: UnboundedSender<SignalAlertMessage>,
|
signal_alert_mq_tx: UnboundedSender<SignalAlertMessage>,
|
||||||
signal_alert_mq_rx: Mutex<UnboundedReceiver<SignalAlertMessage>>,
|
/// Alert receiver, wrapped in Option so it can be taken by run().
|
||||||
|
/// This ensures run() can only be called once.
|
||||||
|
signal_alert_mq_rx: Mutex<Option<UnboundedReceiver<SignalAlertMessage>>>,
|
||||||
token: CancellationToken,
|
token: CancellationToken,
|
||||||
prometheus: Option<Prometheus>,
|
prometheus: Option<Prometheus>,
|
||||||
/// Log handler for processing log messages from all origins.
|
/// Log handler for processing log messages from all origins.
|
||||||
@@ -246,7 +252,7 @@ impl Gateway {
|
|||||||
Self {
|
Self {
|
||||||
config,
|
config,
|
||||||
signal_alert_mq_tx,
|
signal_alert_mq_tx,
|
||||||
signal_alert_mq_rx: Mutex::new(signal_alert_mq_rx),
|
signal_alert_mq_rx: Mutex::new(Some(signal_alert_mq_rx)),
|
||||||
token,
|
token,
|
||||||
prometheus,
|
prometheus,
|
||||||
log_handler,
|
log_handler,
|
||||||
@@ -255,13 +261,23 @@ impl Gateway {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Run the gateway main loop, reconnecting to signal-cli on errors.
|
/// Run the gateway main loop, reconnecting to signal-cli on errors.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
/// Panics if `Gateway::run` is called more than once on a given `Gateway`.
|
||||||
pub async fn run(&self) {
|
pub async fn run(&self) {
|
||||||
|
let mut alert_rx = self
|
||||||
|
.signal_alert_mq_rx
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.take()
|
||||||
|
.expect("Gateway::run can only be called once");
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
if self.token.is_cancelled() {
|
if self.token.is_cancelled() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Err(err) = self.connect_and_run().await {
|
if let Err(err) = self.connect_and_run(&mut alert_rx).await {
|
||||||
error!("Error with signal-cli, reconnecting: {err}");
|
error!("Error with signal-cli, reconnecting: {err}");
|
||||||
tokio::time::sleep(Duration::from_secs(5)).await;
|
tokio::time::sleep(Duration::from_secs(5)).await;
|
||||||
}
|
}
|
||||||
@@ -269,7 +285,10 @@ impl Gateway {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Connect to signal-cli and run the main loop.
|
/// Connect to signal-cli and run the main loop.
|
||||||
async fn connect_and_run(&self) -> Result<(), Box<dyn std::error::Error>> {
|
async fn connect_and_run(
|
||||||
|
&self,
|
||||||
|
alert_rx: &mut UnboundedReceiver<SignalAlertMessage>,
|
||||||
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
if let Some(path) = &self.config.signal_cli_socket_path {
|
if let Some(path) = &self.config.signal_cli_socket_path {
|
||||||
info!(
|
info!(
|
||||||
@@ -277,13 +296,13 @@ impl Gateway {
|
|||||||
path.display()
|
path.display()
|
||||||
);
|
);
|
||||||
let client = connect_ipc(path).await?;
|
let client = connect_ipc(path).await?;
|
||||||
return Ok(self.do_run(&client).await?);
|
return Ok(self.do_run(&client, alert_rx).await?);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(addr) = &self.config.signal_cli_tcp_addr {
|
if let Some(addr) = &self.config.signal_cli_tcp_addr {
|
||||||
info!("Connecting to signal-cli via TCP: {addr}");
|
info!("Connecting to signal-cli via TCP: {addr}");
|
||||||
let client = connect_tcp(addr).await?;
|
let client = connect_tcp(addr).await?;
|
||||||
return Ok(self.do_run(&client).await?);
|
return Ok(self.do_run(&client, alert_rx).await?);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This shouldn't happen due to one_of_fields validation
|
// This shouldn't happen due to one_of_fields validation
|
||||||
@@ -388,13 +407,13 @@ impl Gateway {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn do_run(&self, signal_cli: &impl RpcClient) -> Result<(), RpcClientError> {
|
async fn do_run(
|
||||||
|
&self,
|
||||||
|
signal_cli: &impl RpcClient,
|
||||||
|
alert_rx: &mut UnboundedReceiver<SignalAlertMessage>,
|
||||||
|
) -> Result<(), RpcClientError> {
|
||||||
self.update_trust(signal_cli).await;
|
self.update_trust(signal_cli).await;
|
||||||
|
|
||||||
let mut signal_alert_mq_rx = self
|
|
||||||
.signal_alert_mq_rx
|
|
||||||
.try_lock()
|
|
||||||
.expect("Mutex should not be contended");
|
|
||||||
let mut signal_rx = signal_cli
|
let mut signal_rx = signal_cli
|
||||||
.subscribe_receive(Some(self.config.signal_account.clone()))
|
.subscribe_receive(Some(self.config.signal_account.clone()))
|
||||||
.await?;
|
.await?;
|
||||||
@@ -405,7 +424,7 @@ impl Gateway {
|
|||||||
info!("Stop requested");
|
info!("Stop requested");
|
||||||
return Ok(());
|
return Ok(());
|
||||||
},
|
},
|
||||||
outbound_admin_msg = signal_alert_mq_rx.recv() => {
|
outbound_admin_msg = alert_rx.recv() => {
|
||||||
if let Some(msg) = outbound_admin_msg {
|
if let Some(msg) = outbound_admin_msg {
|
||||||
info!("Sending alert: {}", msg.get_summary());
|
info!("Sending alert: {}", msg.get_summary());
|
||||||
// Prepend origin line if present
|
// Prepend origin line if present
|
||||||
@@ -435,7 +454,7 @@ impl Gateway {
|
|||||||
attachments,
|
attachments,
|
||||||
}.send(signal_cli).await?;
|
}.send(signal_cli).await?;
|
||||||
} else {
|
} else {
|
||||||
warn!("signal_alert_mq_rx is closed, halting service");
|
warn!("alert_rx is closed, halting service");
|
||||||
self.token.cancel();
|
self.token.cancel();
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user