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