1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
#![deny(missing_docs)] //! Process supervisor with inter-process communication support using tokio. //! //! Currently only supports Unix, later we plan to add support for Windows using named pipes. //! //! ## Supervisor //! //! Supervisor manages child processes sending socket information using the environment and then switching //! to Unix domain sockets for inter-process communication. Daemon processes are restarted if //! they die without being shutdown by the supervisor. //! //! ```no_run //! use psup_impl::{Error, Result, Task, SupervisorBuilder}; //! //! #[tokio::main] //! async fn main() -> Result<()> { //! let worker_cmd = "worker-process"; //! let mut supervisor = SupervisorBuilder::new() //! .server(|stream, tx| { //! let (reader, mut writer) = stream.into_split(); //! tokio::task::spawn(async move { //! // Handle worker connection here //! // Use the `tx` supervisor control channel //! // to spawn and shutdown workers //! Ok::<(), Error>(()) //! }); //! }) //! .path(std::env::temp_dir().join("supervisor.sock")) //! .add_worker(Task::new(worker_cmd).daemon(true)) //! .add_worker(Task::new(worker_cmd).daemon(true)) //! .build(); //! supervisor.run().await?; //! // Block the process here and do your work. //! Ok(()) //! } //! ``` //! //! ## Worker //! //! Worker reads the socket information from the environment and then connects to the Unix socket. //! //! ```no_run //! use psup_impl::{Error, Result, Worker}; //! //! #[tokio::main] //! async fn main() -> Result<()> { //! // Read supervisor information from the environment //! // and set up the IPC channel with the supervisor //! let worker = Worker::new() //! .client(|stream, id| async { //! let (reader, mut writer) = stream.into_split(); //! // Start sending messages to the supervisor //! Ok::<(), Error>(()) //! }); //! worker.run().await?; //! // Block the process here and do your work. //! Ok(()) //! } //! ``` /// Enumeration of errors. #[derive(Debug, thiserror::Error)] pub enum Error { /// Worker is missing the id environment variable. #[error("Worker PSUP_WORKER_ID variable is not set")] WorkerNoId, /// Input/output errors. #[error(transparent)] Io(#[from] std::io::Error), /// Error whilst sending bind notifications. #[error(transparent)] Oneshot(#[from] tokio::sync::oneshot::error::RecvError), /// Generic variant for errors created in user code. #[error(transparent)] Boxed(#[from] Box<dyn std::error::Error + Send + Sync>), } /// Result type returned by the library. pub type Result<T> = std::result::Result<T, Error>; pub(crate) const WORKER_ID: &str = "PSUP_WORKER_ID"; pub(crate) const SOCKET: &str = "PSUP_SOCKET"; mod supervisor; mod worker; pub use supervisor::{Message, Supervisor, SupervisorBuilder, Task, id}; pub use worker::Worker;