liminal-server 0.25.4

Standalone server for the liminal messaging bus
Documentation
use std::thread::{self, JoinHandle};

use crate::ServerError;

#[derive(Debug)]
/// Owns the reclaim-release worker until it is joined.
pub struct ReclaimRelease {
    worker: Option<JoinHandle<()>>,
    failure: Option<String>,
}

impl ReclaimRelease {
    pub(crate) fn start(work: impl FnOnce() + Send + 'static) -> Result<Self, ServerError> {
        let worker = thread::Builder::new()
            .name(super::RELEASE_THREAD.to_owned())
            .spawn(work)
            .map_err(|error| refusal(format!("spine reclaim release could not start: {error}")))?;
        Ok(Self {
            worker: Some(worker),
            failure: None,
        })
    }

    pub(crate) fn finish(&mut self) -> Result<(), ServerError> {
        if let Some(failure) = &self.failure {
            return Err(refusal(failure.clone()));
        }
        if let Some(worker) = self.worker.take()
            && worker.join().is_err()
        {
            let message = "spine reclaim release panicked during shutdown";
            self.failure = Some(message.to_owned());
            return Err(refusal(message));
        }
        Ok(())
    }
}

impl Drop for ReclaimRelease {
    fn drop(&mut self) {
        if let Err(error) = self.finish() {
            tracing::error!(%error, "spine reclaim release teardown failed");
        }
    }
}

fn refusal(message: impl Into<String>) -> ServerError {
    ServerError::ListenerAccept {
        message: message.into(),
    }
}