3 个版本
| 新版本 0.1.3 | 2024 年 8 月 23 日 | 
|---|---|
| 0.1.2 | 2024 年 8 月 22 日 | 
| 0.1.1 | 2024 年 8 月 21 日 | 
2128 在 异步 中
110 每月下载量
在 logimesh 中使用
38KB
658 代码行
logimesh
logimesh 是受 面向云应用程序的现代开发 论文启发的 Rust 微组件 2.0 框架。
(这是我的一个业余想法,仅在业余时间开发。)

logimesh 的某些功能
- 客户端同时支持本地调用和远程调用,这意味着用户可以根据上下文动态切换调用方法。
用法
将以下依赖项添加到您的 Cargo.toml 文件中
logimesh = "0.1"
logimesh::component 属性扩展为一个组件项集合。这些生成的类型使得编写具有较少样板代码的服务器变得简单且易于使用。只需实现生成的组件特质,您就可以大步前进!
示例
此示例使用 tokio,因此请将以下依赖项添加到您的 Cargo.toml
[lib]
name = "service"
path = "src/lib.rs"
...
[dependencies]
anyhow = "1.0"
futures = "0.3"
logimesh = { version = "0.1" }
tokio = { version = "1.0", features = ["macros"] }
有关更实际的示例,请参阅 logimesh-example。
首先,让我们设置依赖项和组件定义。
lib.rs 文件
# extern crate futures;
use futures::{
    prelude::*,
};
use logimesh::{
    client, context,
    server::{self, incoming::Incoming, Channel},
};
// This is the component definition. It looks a lot like a trait definition.
// It defines one RPC, hello, which takes one arg, name, and returns a String.
#[logimesh::component]
trait World {
    /// Returns a greeting for name.
    async fn hello(name: String) -> String;
}
此组件定义生成一个名为 World 的特质。接下来,我们需要为我们的 Server 结构体实现它。
# extern crate futures;
# use futures::{
#     prelude::*,
# };
# use logimesh::{
#     client, context,
#     server::{self, incoming::Incoming},
# };
# // This is the component definition. It looks a lot like a trait definition.
# // It defines one RPC, hello, which takes one arg, name, and returns a String.
# #[logimesh::component]
# trait World {
#     /// Returns a greeting for name.
#     async fn hello(name: String) -> String;
# }
/// This is the type that implements the generated World trait. It is the business logic
/// and is used to start the server.
#[derive(Clone)]
struct CompHello;
impl World for CompHello {
    // Each defined rpc generates an async fn that serves the RPC
    async fn hello(self, _: context::Context, name: String) -> String {
        format!("Hello, {name}!")
    }
}
server.rs 文件
use clap::Parser;
use futures::future;
use futures::prelude::*;
use logimesh::server::incoming::Incoming;
use logimesh::server::{self, Channel};
use logimesh::tokio_serde::formats::Json;
use service::{CompHello, World};
use std::net::{IpAddr, Ipv6Addr};
#[derive(Parser)]
struct Flags {
    /// Sets the port number to listen on.
    #[clap(long)]
    port: u16,
}
async fn spawn(fut: impl Future<Output = ()> + Send + 'static) {
    tokio::spawn(fut);
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let flags = Flags::parse();
    let server_addr = (IpAddr::V6(Ipv6Addr::LOCALHOST), flags.port);
    // JSON transport is provided by the json_transport logimesh module. It makes it easy
    // to start up a serde-powered json serialization strategy over TCP.
    let mut listener = logimesh::serde_transport::tcp::listen(&server_addr, Json::default).await?;
    println!("Listening on port {}", listener.local_addr().port());
    listener.config_mut().max_frame_length(usize::MAX);
    listener
        // Ignore accept errors.
        .filter_map(|r| future::ready(r.ok()))
        .map(server::BaseChannel::with_defaults)
        // Limit channels to 1 per IP.
        .max_channels_per_key(2, |t| t.transport().peer_addr().unwrap().ip())
        // serve is generated by the component attribute. It takes as input any type implementing
        // the generated World trait.
        .map(|channel| {
            let server = CompHello;
            channel.execute(server.logimesh_serve()).for_each(spawn)
        })
        // Max 10 channels.
        .buffer_unordered(10)
        .for_each(|_| async {})
        .await;
    Ok(())
}
client.rs 文件
use clap::Parser;
use logimesh::client::stub::LRConfig;
use logimesh::client::stub::TransportCodec::Json;
use logimesh::context;
use logimesh::discover::service_lookup_from_addresses;
use service::{CompHello, World as _};
use std::net::SocketAddr;
use std::time::Duration;
use tokio::time::sleep;
#[derive(Parser)]
struct Flags {
    /// Sets the server address to connect to.
    #[clap(long)]
    server_addr: SocketAddr,
    /// Sets the name to say hello to.
    #[clap(long)]
    name: String,
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let flags = Flags::parse();
    let client = CompHello
        .logimesh_client(
            LRConfig::new("p.s.m".into(), 
            service_lookup_from_addresses(vec![flags.server_addr.to_string()])).with_transport_codec(Json),
        )
        .await?;
    let hello = client.hello(context::current(), format!("{}1", flags.name)).await;
    match hello {
        Ok(hello) => println!("{hello:?}"),
        Err(e) => tracing::warn!("{:?}", anyhow::Error::from(e)),
    }
    Ok(())
}
依赖项
~240–680KB
~16K SLoC