with_daemon

Crates.iowith_daemon
lib.rswith_daemon
version
sourcesrc
created_at2024-09-09 17:27:54.219543
updated_at2024-12-31 20:12:54.288465
descriptionAn async client-daemon abstraction framework
homepage
repositoryhttps://github.com/komar007/with_daemon
max_upload_size
id1369546
Cargo.toml error:TOML parse error at line 19, column 1 | 19 | autolib = false | ^^^^^^^ unknown field `autolib`, expected one of `name`, `version`, `edition`, `authors`, `description`, `readme`, `license`, `repository`, `homepage`, `documentation`, `build`, `resolver`, `links`, `default-run`, `default_dash_run`, `rust-version`, `rust_dash_version`, `rust_version`, `license-file`, `license_dash_file`, `license_file`, `licenseFile`, `license_capital_file`, `forced-target`, `forced_dash_target`, `autobins`, `autotests`, `autoexamples`, `autobenches`, `publish`, `metadata`, `keywords`, `categories`, `exclude`, `include`
size0
Michal Trybus (komar007)

documentation

https://docs.rs/with_daemon

README

with_daemon - An async client-daemon abstraction framework

Crates.io License Crates.io Version GitHub branch check runs docs.rs Crates.io MSRV

This crate abstracts away the spawning of and connecting to a daemon required to optimize tasks performed by multiple client instances that run in separate processes.

The daemon runs in a separate detached process from the first time the client is used and provides functionality to multiple instances of the client, taking advantage of the ability to have a common state shared between client handlers.

Usage

See an example from examples/counter.rs:

//! `with_daemon` example: a simple global counter
//!
//! This example demonstrates how to use `with_daemon` in the most basic way.
//!
//! The daemon keeps track of a counter and each call to the client returns the current counter
//! value and increments the counter.
//!
//! When the compiled binary is executed, it spawns the daemon if it's not running yet, and
//! receives the current value from the daemon. This way each execution of the program provides a
//! different integer, until the daemon is manually killed.

use std::{
    error::Error,
    sync::atomic::{AtomicU32, Ordering},
};

use tokio::io::{AsyncReadExt, AsyncWriteExt};

use with_daemon::with_daemon;

fn main() -> Result<(), Box<dyn Error>> {
    env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("off")).init();
    let result = with_daemon(
        "/tmp/with_daemon__example_counter.pid",
        "/tmp/with_daemon__example_counter.sock",
        // In this example the state is just an integer starting from 0.
        //
        // `with_daemon` expects an async function that returns the initial value of the state here.
        // It awaits that function in the daemon process and passes the `Ok` result to each handler.
        //
        // The init function is fallible, and returning `Err` causes `Error::StateFailed` to be
        // returned from `with_daemon`.
        |_| async { Result::<_, String>::Ok(AtomicU32::new(0)) },
        // The handler is given an `Arc` holding the state described above and a stream connected
        // bi-directionally to the client it is handling.
        //
        // Here, it increments the state atomically and writes the value back to the client.
        |state, mut stream| async move {
            let previous = state.fetch_add(1, Ordering::SeqCst);
            let _ = stream.write_u32(previous).await;
        },
        // The client is given a stream connected bi-directionally to an instance of a handler.
        //
        // Here, it only needs to read the result sent to it by the handler.
        |mut stream| async move { stream.read_u32().await },
    )?; // An error above signifies an internal error in `with_daemon`, for example inability to fork,
        // so in the example we just fail when that happens.

    // `result` here is just what our client closure returns, so an I/O error reading from stream.
    println!("result: {}", result?);
    Ok(())
}

See all examples in examples/.

Commit count: 48

cargo fmt