interprocess_helpers
Wrapper around interprocess::local_socket::tokio for convenient communication
between multiple Rust processes.
Use Cases
Whenever you need two processes to communicate with each other but you can't use stdin and
stdout or other methods. An example would be communication between an elevated app and a non
elevated one on Windows.
This crate also includes a helper function to easily bundle a different rust project with your main app.
In comparison to interprocess,
this crate is a little simpler to use as it abstracts more logic away (at the cost of flexibility).
In contrast to local sockets in interprocess, this
crate also allows the user to have multiple, clonable and sendable writers that send information to another process as
opposed to just one.
Example
A main app (controller) communicates with another app (connector).
Main App (controller):
use interprocess::local_socket::traits::tokio::Stream;
use std::time::Duration;
use tokio::time::sleep;
use interprocess_helpers::{
    ManagedSender, Receiver,
    controller::{connect, get_socket_name},
    end_stream,
};
#[tokio::main(flavor = "current_thread")]
async fn main() -> anyhow::Result<()> {
        let socket_name = &get_socket_name("connector");
        let mut cmd = get_connector_cmd();
    cmd.arg(socket_name);
    let mut child = cmd.spawn()?;
                       tokio::select! {
                  result = connect(socket_name) => {
            let (rx, tx) = result?.split();
                                                let (sender, manager) = ManagedSender::channel(tx, 1);
            let mut receiver = Receiver::from(rx);
            sender.send(b"Ping!".into()).await?;
                                    while let Some(result) = receiver.next().await {
                assert_eq!(result?, "Pong!");
            }
            end_stream(receiver, manager).await?;
            Ok(())
        }
        _ = sleep(Duration::from_secs(20)) => {
            eprintln!("Could not connect: Connection timed out.");
            anyhow::Result::<()>::Ok(())
        }
    }?;
        let status = child.wait()?;
    println!("Connector exit code: {}", status.code().unwrap());
    Ok(())
}
Other App (connector):
use interprocess::local_socket::traits::tokio::Stream;
use std::{env, time::Duration};
use tokio::time::sleep;
use interprocess_helpers::{ManagedSender, Receiver, connector::connect, end_stream};
#[tokio::main(flavor = "current_thread")]
async fn main() -> anyhow::Result<()> {
    let mut args = env::args();
    args.next();
        let socket_name = args.next().unwrap();
            tokio::select! {
                result = connect(&socket_name) => {
            let (rx, tx) = result?.split();
                                                let (sender, manager) = ManagedSender::channel(tx, 1);
            let mut receiver = Receiver::from(rx);
                                                                                                let message = receiver.next().await.unwrap();
            assert_eq!(message?, "Ping!".to_string());
            sender.send(b"Pong!".into()).await?;
            end_stream(receiver, manager).await?;
            Ok(())
        }
        _ = sleep(Duration::from_secs(20)) => {
            panic!("Could not connect: Connection timed out.");
        }
    }
}
License: MIT OR Apache-2.0