Open5

試行:1つのバイナリで異なるフレームワークを同時に動作できるか

Neruneruna7Neruneruna7

まずは,actix-webを2つ同時に動かせるか

仮説:2つ非同期関数を用意して,joinhandleとかで両方待つようにするとできる

main.rs
use actix_web::{
    web::{self, block},
    App, HttpRequest, HttpServer,
};
use tracing_actix_web::TracingLogger;

// #[instrument]
async fn index(req: HttpRequest) -> &'static str {
    println!("index");
    "Hello world!"
}

async fn dopanic() -> &'static str {
    println!("dopanic");
    panic!("dopanic");
    "dopanic"
}

#[tokio::main]
async fn main() -> std::io::Result<()> {
    // 2つの非同期を実行し,joinでまつ
    let (a, b) = tokio::join!(actix_body1(), actix_body2());

    a?;
    b?;
    Ok(())
}

async fn actix_body1() -> std::io::Result<()> {
    println!("actix_body1");
    HttpServer::new(|| {
        App::new()
            // enable logger
            .service(web::resource("/index.html").to(|| async { "Hello world!" }))
            .service(web::resource("/").to(index))
            .service(web::resource("/dopanic").to(dopanic))
    })
    .bind(("127.0.0.1", 8080))?
    .run()
    .await
}

async fn actix_body2() -> std::io::Result<()> {
    println!("actix_body2");
    HttpServer::new(|| {
        App::new()
            // enable logger
            .service(web::resource("/index.html").to(|| async { "Hello world!" }))
            .service(web::resource("/").to(index))
            .service(web::resource("/dopanic").to(dopanic))
    })
    .bind(("127.0.0.1", 8081))?
    .run()
    .await
}

成功 join!マクロで並べるとできた
3つ以上も可能だろう

パニックからのリカバリも問題なさそうだ

Neruneruna7Neruneruna7

仮説:actix-webとpoiseという異なるフレームワークでも,同様に動作可能

dependanciesにactix-webとpoiseの両方を追加
tokio::mainマクロのところでエラー
エラーメッセージ

proc macro `main` not expanded: No proc-macros present for crate

マクロがないと言っている?(そんなはずはない)
何かが衝突している?

失敗
1つのクレートにまとめて突っ込んだのがよくないのか?

Neruneruna7Neruneruna7

仮説:ワークスペースを使って分離することで解決できる可能性
tokio部分をcoreに,actixをactix_body,poiseをpoise_bodyにクレート分割

core
fn main() -> std::io::Result<()> {
    // 2つの非同期を実行し,joinでまつ
    tokio::runtime::Builder::new_multi_thread()
        .enable_all()
        .build().expect("runtime build failed")
        .block_on(async {
            // let (a, b) = tokio::join!(actix_body::body(), poise_body::body());
            // a?;
            // b?;
            Ok(())
        })
}
actix_body
use actix_web::{web, App, HttpRequest, HttpServer};

pub async fn body() -> std::io::Result<()> {
    println!("actix_body1");
    HttpServer::new(|| {
        App::new()
            // enable logger
            .service(web::resource("/index.html").to(|| async { "Hello world!" }))
            .service(web::resource("/").to(index))
            .service(web::resource("/dopanic").to(dopanic))
    })
    .bind(("127.0.0.1", 8080))?
    .run()
    .await
}

async fn index(_req: HttpRequest) -> &'static str {
    println!("index");
    "Hello world!"
}

async fn dopanic() -> &'static str {
    println!("dopanic");
    panic!("dopanic");
    "dopanic"
}
poise_body
pub async fn body() -> std::io::Result<()> {
    println!("poise_body");
    Ok(())
}

  • ワークスペースのメンバー coreのみ
    • とおる
  • coreとpoise
    • とおらない
  • coreとactix
    • とおる

???

tokio::mainマクロがエラーでまくる

マクロの内容を自力で書く

-> コンパイルエラー
マクロの時と同じ
マクロと同じことを自力で書くメリットはなさそう

失敗

ダメみたいだ.

poise単体で別のクレートつくってテスト
通らない

Neruneruna7Neruneruna7

エラーを軽く見てみたが,依存ライブラリをビルドしているときに,リンクに失敗している様子

error: linking with `cc` failed: exit status: 1
Neruneruna7Neruneruna7

仮説: poise_body側に問題があり,そこを修正することで動作する可能性
そもそも現在のpoise_bodyは非常に単純な,ほぼprintlnのみのコードしかない
仮説破棄