From 83eae64ff3be65d350f0656c45646c426f3f6d36 Mon Sep 17 00:00:00 2001 From: Val Lorentz Date: Fri, 25 Aug 2023 15:12:02 +0200 Subject: [PATCH] Avoid .unwrap() on IO and user errors Before: ``` Error: Os { code: 2, kind: NotFound, message: "No such file or directory" } ``` After: ``` Error: Failed to read TLS config Caused by: No such file or directory (os error 2) ``` --- Cargo.lock | 4 ++ sable_ipc/src/lib.rs | 23 ++++++++-- sable_ircd/Cargo.toml | 3 +- sable_ircd/src/bin/sable_ircd.rs | 2 +- sable_ircd/src/command/error.rs | 6 +-- sable_ircd/src/server/server_type.rs | 51 +++++++++++++--------- sable_network/Cargo.toml | 1 + sable_network/src/config.rs | 4 +- sable_network/src/policy/error.rs | 4 +- sable_network/src/sync/mod.rs | 1 + sable_network/src/sync/replicated_log.rs | 2 +- sable_server/Cargo.toml | 1 + sable_server/src/management.rs | 4 +- sable_server/src/run.rs | 54 +++++++++++++++++------- sable_server/src/server.rs | 31 +++++++------- sable_server/src/server_type.rs | 17 ++++++-- sable_services/Cargo.toml | 3 +- sable_services/src/bin/sable_services.rs | 2 +- sable_services/src/database/mod.rs | 6 +-- sable_services/src/server/mod.rs | 14 +++--- 20 files changed, 151 insertions(+), 82 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3ddc30a2..a23e346f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1881,6 +1881,7 @@ dependencies = [ name = "sable_ircd" version = "0.1.0" dependencies = [ + "anyhow", "arc-swap", "async-trait", "auth_client", @@ -1927,6 +1928,7 @@ name = "sable_network" version = "0.1.0" dependencies = [ "ambassador", + "anyhow", "arrayvec", "bitflags", "built", @@ -1961,6 +1963,7 @@ dependencies = [ name = "sable_server" version = "0.1.0" dependencies = [ + "anyhow", "async-trait", "chrono", "console-subscriber", @@ -1990,6 +1993,7 @@ dependencies = [ name = "sable_services" version = "0.1.0" dependencies = [ + "anyhow", "async-trait", "bcrypt", "dashmap", diff --git a/sable_ipc/src/lib.rs b/sable_ipc/src/lib.rs index 7723984e..36964564 100644 --- a/sable_ipc/src/lib.rs +++ b/sable_ipc/src/lib.rs @@ -60,7 +60,11 @@ impl Sender { let bytes = DefaultOptions::new() .with_limit(self.max_len) .serialize(data)?; - self.socket.as_ref().unwrap().send(&bytes).await?; + self.socket + .as_ref() + .expect("Tried to send to closed IPC socket") + .send(&bytes) + .await?; Ok(()) } @@ -83,7 +87,11 @@ impl Sender { /// Using the returned FD for anything other than `Self::from_raw_fd` may cause unpredictable /// behaviour in the corresponding `Receiver`. pub unsafe fn into_raw_fd(mut self) -> std::io::Result { - let std_socket = self.socket.take().unwrap().into_std()?; + let std_socket = self + .socket + .take() + .expect("Tried to get write FD of closed IPC socket") + .into_std()?; Ok(std_socket.into_raw_fd()) } } @@ -118,7 +126,10 @@ impl Receiver { } pub async fn recv(&self) -> Result { - let sock = self.socket.as_ref().unwrap(); + let sock = self + .socket + .as_ref() + .expect("Tried to read from closed IPC socket"); loop { sock.readable().await?; @@ -151,7 +162,11 @@ impl Receiver { /// Using the returned FD for anything other than `Self::from_raw_fd` may cause unpredictable /// behaviour in the corresponding `Sender`. pub unsafe fn into_raw_fd(mut self) -> std::io::Result { - let std_socket = self.socket.take().unwrap().into_std()?; + let std_socket = self + .socket + .take() + .expect("Tried to get read FD of closed IPC socket") + .into_std()?; Ok(std_socket.into_raw_fd()) } } diff --git a/sable_ircd/Cargo.toml b/sable_ircd/Cargo.toml index 4dfacccb..36c69754 100644 --- a/sable_ircd/Cargo.toml +++ b/sable_ircd/Cargo.toml @@ -38,4 +38,5 @@ arc-swap = { version = "1.5", features = [ "serde" ] } parking_lot = { version = "0.12", features = [ "serde" ] } async-trait = "0.1.57" structopt = "0.3" -base64 = "0.21" \ No newline at end of file +base64 = "0.21" +anyhow = "1.0" diff --git a/sable_ircd/src/bin/sable_ircd.rs b/sable_ircd/src/bin/sable_ircd.rs index 5ad7bd49..9872fc02 100644 --- a/sable_ircd/src/bin/sable_ircd.rs +++ b/sable_ircd/src/bin/sable_ircd.rs @@ -31,7 +31,7 @@ struct Opts { /// Because the tokio runtime can't survive forking, `main()` loads the application /// configs (in order to report as many errors as possible before daemonising), daemonises, /// initialises the tokio runtime, and begins the async entry point [`sable_main`]. -pub fn main() -> Result<(), Box> { +pub fn main() -> Result<(), anyhow::Error> { let opts = Opts::from_args(); sable_server::run::run_server::( diff --git a/sable_ircd/src/command/error.rs b/sable_ircd/src/command/error.rs index 12aa0fa8..d90bc30d 100644 --- a/sable_ircd/src/command/error.rs +++ b/sable_ircd/src/command/error.rs @@ -12,7 +12,7 @@ use crate::errors::HandlerError; #[derive(Debug)] pub enum CommandError { /// Something returned an `Error` that we don't know how to handle - UnderlyingError(Box), + UnderlyingError(anyhow::Error), /// Something went wrong but we don't have an `Error` impl for it UnknownError(String), /// The command couldn't be processed successfully, and the client has already been @@ -135,12 +135,12 @@ impl From for CommandError { impl From for CommandError { fn from(e: ConnectionError) -> Self { - Self::UnderlyingError(Box::new(e)) + Self::UnderlyingError(e.into()) } } impl From for CommandError { fn from(e: HandlerError) -> Self { - Self::UnderlyingError(Box::new(e)) + Self::UnderlyingError(e.into()) } } diff --git a/sable_ircd/src/server/server_type.rs b/sable_ircd/src/server/server_type.rs index 5ca8c19f..3b7d7b9d 100644 --- a/sable_ircd/src/server/server_type.rs +++ b/sable_ircd/src/server/server_type.rs @@ -1,7 +1,9 @@ use super::*; use crate::connection_collection::ConnectionCollectionState; +use anyhow::Context; use async_trait::async_trait; use client_listener::SavedListenerCollection; +use sable_server::ServerSaveError; /// Saved state of a [`ClientServer`] for later resumption #[derive(serde::Serialize, serde::Deserialize)] @@ -23,16 +25,17 @@ impl sable_server::ServerType for ClientServer { tls_data: &TlsData, node: Arc, history_receiver: UnboundedReceiver, - ) -> Self { + ) -> anyhow::Result { let (action_submitter, action_receiver) = unbounded_channel(); let (auth_sender, auth_events) = unbounded_channel(); let (client_send, client_recv) = unbounded_channel(); - let client_listeners = ListenerCollection::new(client_send).unwrap(); + let client_listeners = ListenerCollection::new(client_send) + .context("Could not initialize listener collection")?; client_listeners .load_tls_certificates(tls_data.key.clone(), tls_data.cert_chain.clone()) - .unwrap(); + .context("Could not load TLS certificates")?; for listener in config.listeners.iter() { let conn_type = if listener.tls { @@ -41,17 +44,23 @@ impl sable_server::ServerType for ClientServer { ConnectionType::Clear }; client_listeners - .add_listener(listener.address.parse().unwrap(), conn_type) - .unwrap(); + .add_listener( + listener.address.parse().with_context(|| { + format!("Invalid listener address: {}", listener.address) + })?, + conn_type, + ) + .context("Cannot add listener")?; } - Self { + Ok(Self { action_receiver: Mutex::new(action_receiver), connection_events: Mutex::new(client_recv), history_receiver: Mutex::new(history_receiver), auth_events: Mutex::new(auth_events), - auth_client: AuthClient::new(auth_sender).unwrap(), + auth_client: AuthClient::new(auth_sender) + .context("Could not initialize auth client")?, action_submitter, command_dispatcher: CommandDispatcher::new(), @@ -60,14 +69,18 @@ impl sable_server::ServerType for ClientServer { client_caps: CapabilityRepository::new(), node: node, listeners: Movable::new(client_listeners), - } + }) } /// Save the server's state for later resumption - async fn save(mut self) -> ClientServerState { - ClientServerState { + async fn save(mut self) -> Result { + Ok(ClientServerState { connections: self.connections.into_inner().save_state(), - auth_state: self.auth_client.save_state().await.unwrap(), + auth_state: self + .auth_client + .save_state() + .await + .map_err(ServerSaveError::IoError)?, client_caps: self.client_caps, listener_state: self .listeners @@ -75,8 +88,8 @@ impl sable_server::ServerType for ClientServer { .unwrap() .save() .await - .expect("failed to save listener state"), - } + .map_err(ServerSaveError::IoError)?, + }) } /// Restore from a previously saved state. @@ -84,15 +97,14 @@ impl sable_server::ServerType for ClientServer { state: ClientServerState, node: Arc, history_receiver: UnboundedReceiver, - ) -> Self { + ) -> std::io::Result { let (auth_send, auth_recv) = unbounded_channel(); let (action_send, action_recv) = unbounded_channel(); let (client_send, client_recv) = unbounded_channel(); - let listeners = ListenerCollection::resume(state.listener_state, client_send) - .expect("failed to restore listener collection"); + let listeners = ListenerCollection::resume(state.listener_state, client_send)?; - Self { + Ok(Self { node, action_receiver: Mutex::new(action_recv), action_submitter: action_send, @@ -102,14 +114,13 @@ impl sable_server::ServerType for ClientServer { &listeners, )), command_dispatcher: command::CommandDispatcher::new(), - auth_client: AuthClient::resume(state.auth_state, auth_send) - .expect("Failed to reload auth client"), + auth_client: AuthClient::resume(state.auth_state, auth_send)?, auth_events: Mutex::new(auth_recv), isupport: Self::build_basic_isupport(), client_caps: state.client_caps, history_receiver: Mutex::new(history_receiver), listeners: Movable::new(listeners), - } + }) } async fn run(self: Arc, shutdown: broadcast::Receiver) { diff --git a/sable_network/Cargo.toml b/sable_network/Cargo.toml index af779639..3b94c4cf 100644 --- a/sable_network/Cargo.toml +++ b/sable_network/Cargo.toml @@ -40,6 +40,7 @@ wildmatch = "2.1" concurrent_log = { version = "0.2.4", features = [ "serde" ] } once_cell = "1.13" ipnet = { version = "2", features = [ "serde" ] } +anyhow = "1.0" [dependencies.serde] version = "1" diff --git a/sable_network/src/config.rs b/sable_network/src/config.rs index 9dc23f63..5b0c018d 100644 --- a/sable_network/src/config.rs +++ b/sable_network/src/config.rs @@ -1,5 +1,5 @@ use serde::Deserialize; -use std::{error::Error, fs::File, io::BufReader, path::PathBuf}; +use std::{fs::File, io::BufReader, path::PathBuf}; use crate::prelude::ConfigError; @@ -16,7 +16,7 @@ pub struct TlsData { } impl TlsConfig { - pub fn load_from_disk(&self) -> Result> { + pub fn load_from_disk(&self) -> Result { let cert_file = File::open(&self.cert_file)?; let mut cert_reader = BufReader::new(cert_file); let cert_chain = rustls_pemfile::certs(&mut cert_reader)?; diff --git a/sable_network/src/policy/error.rs b/sable_network/src/policy/error.rs index 5ed8003a..053f2ff1 100644 --- a/sable_network/src/policy/error.rs +++ b/sable_network/src/policy/error.rs @@ -48,7 +48,7 @@ pub enum PermissionError { Channel(ChannelName, ChannelPermissionError), User(UserPermissionError), Registration(RegistrationPermissionError), - InternalError(Box), + InternalError(anyhow::Error), } impl From for PermissionError { @@ -65,6 +65,6 @@ impl From for PermissionError { impl From for PermissionError { fn from(e: LookupError) -> Self { - Self::InternalError(Box::new(e)) + Self::InternalError(e.into()) } } diff --git a/sable_network/src/sync/mod.rs b/sable_network/src/sync/mod.rs index 436b35b5..73705869 100644 --- a/sable_network/src/sync/mod.rs +++ b/sable_network/src/sync/mod.rs @@ -22,6 +22,7 @@ pub use network::GossipNetwork; pub use network::GossipNetworkState; pub use network::NetworkError; +pub use replicated_log::EventLogSaveError; pub use replicated_log::ReplicatedEventLog; pub use replicated_log::ReplicatedEventLogState; diff --git a/sable_network/src/sync/replicated_log.rs b/sable_network/src/sync/replicated_log.rs index 4cd1cbed..15a3f0bd 100644 --- a/sable_network/src/sync/replicated_log.rs +++ b/sable_network/src/sync/replicated_log.rs @@ -27,7 +27,7 @@ pub enum EventLogSaveError { #[error("{0}")] InternalError(&'static str), #[error("Unknown error: {0}")] - UnknownError(#[from] Box), + UnknownError(#[from] anyhow::Error), } /// Saved state for a [ReplicatedEventLog], used to save and restore across an upgrade diff --git a/sable_server/Cargo.toml b/sable_server/Cargo.toml index 3811b7f8..cc8af1e9 100644 --- a/sable_server/Cargo.toml +++ b/sable_server/Cargo.toml @@ -34,3 +34,4 @@ daemonize = "0.4" nix = "0.24" memfd = "0.4" parking_lot = { version = "0.12", features = [ "serde" ] } +anyhow = "1.0" diff --git a/sable_server/src/management.rs b/sable_server/src/management.rs index 437785f5..c42d9b3c 100644 --- a/sable_server/src/management.rs +++ b/sable_server/src/management.rs @@ -184,7 +184,7 @@ impl ManagementServer { conn: TcpStream, acceptor: Arc, data: Arc, - ) -> Result<(), Box> { + ) -> Result<(), anyhow::Error> { let stream = acceptor.accept(conn).await?; let (_, tls_state) = stream.get_ref(); let client_cert = tls_state @@ -269,7 +269,7 @@ impl ManagementServer { self.command_receiver.recv().await } - pub async fn wait(self) -> Result<(), Box> { + pub async fn wait(self) -> Result<(), anyhow::Error> { Ok(self.server_task.await??) } } diff --git a/sable_server/src/run.rs b/sable_server/src/run.rs index 229cbf25..b8da0c45 100644 --- a/sable_server/src/run.rs +++ b/sable_server/src/run.rs @@ -14,6 +14,7 @@ use std::{ process::Command, }; +use anyhow::Context; use tracing_subscriber::util::SubscriberInitExt; use memfd::*; @@ -75,7 +76,7 @@ async fn do_run_server( tls_data: sable_network::config::TlsData, upgrade_fd: Option, bootstrap_network: Option, -) -> Result<(), Box> +) -> Result<(), anyhow::Error> where ST: ServerType, { @@ -90,11 +91,12 @@ where let state = read_upgrade_state(upgrade_fd); - let server = Server::restore_from(state, sync_config, server_config)?; - - server + Server::restore_from(state, sync_config, server_config) + .context("Could not restore server")? } else { - Server::new(server_config, tls_data, sync_config, bootstrap_network).await + Server::new(server_config, tls_data, sync_config, bootstrap_network) + .await + .context("Could not initialize server")? }; // Run the actual server @@ -117,7 +119,7 @@ where panic!("Couldn't re-execute: {}", err); } ShutdownAction::Upgrade => { - let server_state = server.save().await; + let server_state = server.save().await.context("Could not save server state")?; exec_upgrade(&exe_path, server_conf_path, sync_conf_path, server_state); } @@ -154,7 +156,7 @@ pub fn run_server( foreground: bool, upgrade_fd: Option, bootstrap_config: Option>, -) -> Result<(), Box> +) -> anyhow::Result<()> where ST: ServerType, { @@ -162,12 +164,28 @@ where // configs (in order to report as many errors as possible before daemonising), daemonises, // initialises the tokio runtime, and begins the async entry point [`sable_main`]. - let sync_config = SyncConfig::load_file(&sync_config_path)?; - let server_config = ServerConfig::::load_file(&server_config_path)?; - - let tls_data = server_config.tls_config.load_from_disk()?; - - let bootstrap_conf = bootstrap_config.map(load_network_config).transpose()?; + let sync_config = SyncConfig::load_file(&sync_config_path).with_context(|| { + format!( + "Failed to read sync config from {}", + sync_config_path.as_ref().display() + ) + })?; + let server_config = ServerConfig::::load_file(&server_config_path).with_context(|| { + format!( + "Failed to read server config from {}", + server_config_path.as_ref().display() + ) + })?; + + let tls_data = server_config + .tls_config + .load_from_disk() + .context("Failed to read TLS config")?; + + let bootstrap_conf = bootstrap_config + .map(load_network_config) + .transpose() + .context("Failed to transpose network config")?; if !server_config.log.dir.is_dir() { std::fs::create_dir_all(&server_config.log.dir).expect("failed to create log directory"); @@ -181,10 +199,16 @@ where .working_directory(std::env::current_dir()?); if let Some(stdout) = &server_config.log.stdout { - daemon = daemon.stdout(File::create(&server_config.log.prefix_file(stdout)).unwrap()); + let path = server_config.log.prefix_file(stdout); + daemon = daemon.stdout(File::create(&path).with_context(|| { + format!("Could not create daemon stdout file {}", path.display()) + })?); } if let Some(stderr) = &server_config.log.stderr { - daemon = daemon.stderr(File::create(&server_config.log.prefix_file(stderr)).unwrap()); + let path = server_config.log.prefix_file(stderr); + daemon = daemon.stderr(File::create(&path).with_context(|| { + format!("Could not create daemon stderr file {}", path.display()) + })?); } if let Some(pidfile) = &server_config.log.pidfile { daemon = daemon.pid_file(server_config.log.prefix_file(pidfile)); diff --git a/sable_server/src/server.rs b/sable_server/src/server.rs index e6e43941..ee1d98ae 100644 --- a/sable_server/src/server.rs +++ b/sable_server/src/server.rs @@ -1,5 +1,6 @@ use crate::{config::*, strip_comments::StripComments, *}; +use anyhow::Context; use parking_lot::Mutex; use sable_network::{ config::*, @@ -43,7 +44,7 @@ where ST::Config: DeserializeOwned, { /// Load configuration from a file - pub fn load_file>(filename: P) -> Result> { + pub fn load_file>(filename: P) -> Result { let file = File::open(filename)?; let reader = StripComments::new(file); Ok(serde_json::from_reader(reader)?) @@ -88,7 +89,7 @@ where tls_data: TlsData, net_config: SyncConfig, bootstrap_config: Option, - ) -> Self { + ) -> anyhow::Result { let (server_send, server_recv) = unbounded_channel(); let (history_send, history_recv) = unbounded_channel(); let (remote_send, remote_recv) = unbounded_channel(); @@ -121,14 +122,12 @@ where policy, )); - let server = Arc::new(ST::new( - conf.server, - &tls_data, - Arc::clone(&node), - history_recv, - )); + let server = Arc::new( + ST::new(conf.server, &tls_data, Arc::clone(&node), history_recv) + .context("Could not initialize server")?, + ); - Self { + Ok(Self { node, log, server, @@ -138,7 +137,7 @@ where .load_from_disk() .expect("Couldn't load TLS files"), remote_command_recv: Mutex::new(Some(remote_recv)), - } + }) } /// Run the server, including the log synchronisation, the network state tracking, management @@ -263,7 +262,7 @@ where } /// Save the state of the server, including all its component parts, for resumption after a code upgrade. - pub async fn save(self) -> ServerState { + pub async fn save(self) -> Result, ServerSaveError> { // Order matters here. // // Arc::try_unwrap will fail if there are any other Arcs still referencing the same object. @@ -273,20 +272,20 @@ where let server_state = Arc::try_unwrap(self.server) .unwrap_or_else(|_| panic!("Couldn't unwrap server")) .save() - .await; + .await?; let node_state = Arc::try_unwrap(self.node) .unwrap_or_else(|_| panic!("Couldn't unwrap node")) .save_state(); let log_state = Arc::try_unwrap(self.log) .unwrap_or_else(|_| panic!("Couldn't unwrap event log")) .save_state() - .expect("Couldn't save log state"); + .map_err(server_type::ServerSaveError::EventLogSaveError)?; - ServerState { + Ok(ServerState { node_state, log_state, server_state, - } + }) } /// Restore from a previously-saved application state. @@ -318,7 +317,7 @@ where state.server_state, Arc::clone(&node), history_recv, - )); + )?); Ok(Self { node, diff --git a/sable_server/src/server_type.rs b/sable_server/src/server_type.rs index 159ecaf6..f12881e3 100644 --- a/sable_server/src/server_type.rs +++ b/sable_server/src/server_type.rs @@ -4,12 +4,21 @@ use async_trait::async_trait; use serde::{de::DeserializeOwned, Serialize}; use std::sync::Arc; use tokio::sync::{broadcast, mpsc::UnboundedReceiver}; +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum ServerSaveError { + #[error("{0}")] + IoError(std::io::Error), + #[error("Unknown error: {0}")] + EventLogSaveError(sable_network::sync::EventLogSaveError), +} /// Trait to be implemented by providers of server application logic. /// /// An implementor of this trait can be constructed and used by [`run_server`](crate::run::run_server). #[async_trait] -pub trait ServerType: Send + Sync + 'static { +pub trait ServerType: Send + Sync + Sized + 'static { /// The configuration settings required for this server type type Config: DeserializeOwned; @@ -22,7 +31,7 @@ pub trait ServerType: Send + Sync + 'static { tls_data: &TlsData, node: Arc, history_receiver: UnboundedReceiver, - ) -> Self; + ) -> anyhow::Result; /// Run the application logic. `shutdown_channel` will be signalled with an `ShutdownAction` when /// the server should be stopped. @@ -32,14 +41,14 @@ pub trait ServerType: Send + Sync + 'static { async fn shutdown(self); /// Save state for later resumption - async fn save(self) -> Self::Saved; + async fn save(self) -> Result; /// Restore from saved state fn restore( state: Self::Saved, node: Arc, history_receiver: UnboundedReceiver, - ) -> Self; + ) -> std::io::Result; /// Handle a request originating from a remote server fn handle_remote_command(&self, request: RemoteServerRequestType) -> RemoteServerResponse; diff --git a/sable_services/Cargo.toml b/sable_services/Cargo.toml index 30cbd5a5..cf5d0fe7 100644 --- a/sable_services/Cargo.toml +++ b/sable_services/Cargo.toml @@ -21,4 +21,5 @@ ouroboros = "0.15" bcrypt = "0.13" tracing = "0.1" structopt = "0.3" -dashmap = "5" \ No newline at end of file +dashmap = "5" +anyhow = "1.0" diff --git a/sable_services/src/bin/sable_services.rs b/sable_services/src/bin/sable_services.rs index 0b545df1..126205a1 100644 --- a/sable_services/src/bin/sable_services.rs +++ b/sable_services/src/bin/sable_services.rs @@ -22,7 +22,7 @@ struct Opts { /// Because the tokio runtime can't survive forking, `main()` loads the application /// configs (in order to report as many errors as possible before daemonising), daemonises, /// initialises the tokio runtime, and begins the async entry point [`sable_main`]. -pub fn main() -> Result<(), Box> { +pub fn main() -> Result<(), anyhow::Error> { let opts = Opts::from_args(); sable_server::run::run_server::< diff --git a/sable_services/src/database/mod.rs b/sable_services/src/database/mod.rs index 0f6fb74d..0f19217b 100644 --- a/sable_services/src/database/mod.rs +++ b/sable_services/src/database/mod.rs @@ -14,12 +14,12 @@ pub enum DatabaseError { #[error("Invalid data")] InvalidData, #[error("{0}")] - DbError(#[from] Box), + DbError(#[from] anyhow::Error), } impl DatabaseError { - fn from_inner(inner: T) -> Self { - Self::DbError(Box::new(inner)) + fn from_inner>(inner: T) -> Self { + Self::DbError(inner.into()) } } diff --git a/sable_services/src/server/mod.rs b/sable_services/src/server/mod.rs index cc687148..e7e10584 100644 --- a/sable_services/src/server/mod.rs +++ b/sable_services/src/server/mod.rs @@ -16,9 +16,11 @@ use sable_network::{ rpc::*, }; use sable_server::ServerType; +use sable_server::ServerSaveError; use std::{collections::HashMap, sync::Arc}; +use anyhow::Context; use async_trait::async_trait; use serde::Deserialize; @@ -59,7 +61,7 @@ where _tls_data: &TlsData, node: Arc, history_receiver: UnboundedReceiver, - ) -> Self { + ) -> anyhow::Result { if !config .default_roles .contains_key(&ChannelRoleName::BuiltinOp) @@ -76,14 +78,14 @@ where panic!("Builtin roles not defined"); } - Self { - db: DatabaseConnection::connect(&config.database).unwrap(), + Ok(Self { + db: DatabaseConnection::connect(&config.database).context("Could not connect to database")?, node, history_receiver: Mutex::new(history_receiver), config, sasl_sessions: DashMap::new(), sasl_mechanisms: sasl::build_mechanisms(), - } + }) } async fn shutdown(self) {} @@ -126,13 +128,13 @@ where } } - async fn save(self) {} + async fn save(self) -> Result<(), ServerSaveError> { Ok(()) } fn restore( _state: Self::Saved, _node: Arc, _history_receiver: UnboundedReceiver, - ) -> Self { + ) -> std::io::Result { unimplemented!("services can't hot-upgrade"); }