#unix-socket #unix #async-io #non-blocking #io #daemon #async

suss

创建单实例Unix套接字服务的集合,由使用它们的任何客户端按需启动

4个版本

0.0.5 2022年8月9日
0.0.4 2022年8月7日
0.0.3 2022年8月7日
0.0.2 2022年8月5日

#45#unix-socket

Download history 2/week @ 2024-03-08 7/week @ 2024-03-22 228/week @ 2024-03-29 1/week @ 2024-04-05 102/week @ 2024-06-07 9/week @ 2024-06-14

每月111次下载

AGPL-3.0或更高

65KB
774

suss

Suss是一个库,用于创建可以相互交互和(可选)按需启动的Unix服务的集合。

此外,只要提供socket_shims::UnixSocketInterface的实现,就可以将其插入不同的异步框架中。如果您根本不在乎异步,则可以使用基于blocking的标准线程池实现,或者编写同步API实现并使用类似pollster的crate来取消异步。

托管在

基本示例

提供一个简单的echo服务的单一接口,通过任何兼容的Unix套接字接口,并具有通过运行命令按需启动的能力。

use suss::prelude::*;
use suss::blocking;
use std::io::{Result as IoResult, BufRead};

struct EchoClient<U: UnixSocketInterface>(U::UnixStream);

impl <U: UnixSocketInterface>  EchoClient<U> {
    pub fn new(u: U::UnixStream) -> Self {
        Self(u)
    }

    pub async fn write_and_receive<'b>(&mut self, in_value: &'b [u8]) -> IoResult<Vec<u8>> {
        U::unix_stream_write_all(&mut self.0, &(in_value.len() as u64).to_be_bytes()).await?;
        U::unix_stream_write_all(&mut self.0, in_value).await?;
        let mut out_length_bytes = [0u8;8];
        U::unix_stream_read_exact(&mut self.0, &mut out_length_bytes).await?;
        let mut out_length = u64::from_be_bytes(out_length_bytes);
        let mut out = vec![0u8;out_length.try_into().unwrap()];
        U::unix_stream_read_exact(&mut self.0, &mut out).await?;
        Ok(out)
    }
}

declare_service!{
    /// This is a very nice echo service!
    EchoService <U> = {
        "my-echo-service" "--server" @ "echo-service.socks" as raw |stream| -> Io<EchoClient<U>> { Ok(EchoClient(stream)) } 
    } impl {U: UnixSocketInterface}
}

fn main() { 
    let reified: ReifiedService<_, suss::socket_shims::StdThreadpoolUSocks, _> = EchoService.reify("/var/run/".as_ref());
    
    futures_lite_block_on(async move {
        let mut service_api = reified.connect_to_running().await.expect("No service running");
        let stdin = std::io::stdin();
        let mut stdin = stdin.lock();
        let mut buf = String::new();
        loop {
            stdin.read_line(&mut buf).unwrap();
            if buf.trim() == "die" {
                break
            };
            let received_line = service_api.write_and_receive(buf.as_bytes()).await.unwrap();
            let valid_utf8 = std::str::from_utf8(&received_line).unwrap();
            println!("{valid_utf8}");
        }
    });
}

使用

此库允许您

  • 在单个位置定义服务列表和Unix套接字名称,以及任意接口,该接口包装裸Unix流作为客户端连接,以及启动服务的方法。
  • 在另一个包中提供服务的实现,或者也许是在同一包的不同模块中。理论上,这将为替代实现或测试实现提供繁荣的土壤,只要服务能够使客户端满意。
  • 在初始连接时自动尝试检测正在运行的服务,并在服务未运行时尝试启动它们,以及内置的生存性检查机制(当然,这种机制稍微侵入性,因为它需要以某种方式向新服务传递参数)。
  • 如果异步 Unix 套接字在您的异步运行时中可用,则使用它,通过可选依赖项(目前可用的有 async-stdtokio 以及基于线程池的 std 回退)。所有这些框架都可以转换到和从标准库 Unix 套接字,因此即使在 suss 保持运行时无关的情况下,您也可以在客户端和服务器实现中自由使用它们。
  • 提供运行时目录作为您服务集合的“命名空间”——这意味着可以按系统范围、按用户、按其他配置运行服务集合,只要您可以为要运行的服务集合提供不同的基本目录路径即可。

依赖项

约2-15MB
约160K SLoC