Asynchronous 当路由处理程序是异步的时,如何使用Warp实现共享应用程序状态?

Asynchronous 当路由处理程序是异步的时,如何使用Warp实现共享应用程序状态?,asynchronous,rust,mutex,crud,rust-warp,Asynchronous,Rust,Mutex,Crud,Rust Warp,我有一个生锈的应用程序使用。它实现了一个RESTful CRUD API。我需要每个路由处理程序(即,最终由warp过滤器调用的函数)能够访问和(在大多数情况下)改变共享应用程序状态 我要编译它的唯一方法是为每条路线克隆一个Arc: /*internal_state是先前从转储文件加载的,类型为“state”*/ let状态:Arc=Arc::new(互斥体::new(内部_状态)); 让索引_book_state:Arc=state.clone(); 让我们创建_book_state:Arc=

我有一个生锈的应用程序使用。它实现了一个RESTful CRUD API。我需要每个路由处理程序(即,最终由warp过滤器调用的函数)能够访问和(在大多数情况下)改变共享应用程序状态

我要编译它的唯一方法是为每条路线克隆一个
Arc

/*internal_state是先前从转储文件加载的,类型为“state”*/
let状态:Arc=Arc::new(互斥体::new(内部_状态));
让索引_book_state:Arc=state.clone();
让我们创建_book_state:Arc=state.clone();
让我们读一读书的状态:Arc=state.clone();
让我们创建_order_state:Arc=state.clone();
让我们读取命令状态:Arc=state.clone();
让我们更新_order_state:Arc=state.clone();
让我们销毁命令状态:Arc=state.clone();
/*定义订单簿的CRUD路由*/
让book\u prefix=warp::path!(“书”);
让index\u book\u route=book\u前缀
.和(warp::get())
.and(warp::any().map(move | | index_book_state.clone())
,然后(handler::index\u book\u handler);
让我们创建\u book\u路由=book\u前缀
.和(warp::post())
.和(warp::body::json())
.and(warp::any().map(move | | create_book_state.clone()))
,然后(handler::create\u book\u handler);
让我们读一读这本书吧!(“书”/String)
.和(warp::get())
.and(warp::any().map(move | | read_book_state.clone()))
,然后(handler::read\u book\u handler);
/*为订单定义CRUD路由*/
让我们创建_order_route=warp::path!(“书”/String)
.和(warp::post())
.和(warp::body::json())
.and(warp::any().map(move | | create _order_state.clone()))
,然后(handler::create_order_handler);
让我们读一读_order_route=warp::path!(“书”/String/“订单”/String)
.和(warp::get())
.and(warp::any().map(move | | read _order_state.clone()))
,然后(handler::read\u order\u handler);
让我们更新_order_route=warp::path!(“书”/String/“订单”/String)
.和(warp::put())
.和(warp::body::json())
.and(warp::any().map(move | | update _order_state.clone()))
,然后(handler::update\u order\u handler);
让我们销毁\u order\u route=warp::path!(“书”/String/“订单”/String)
.和(warp::delete())
.and(warp::any().map(move | | destroy_order_state.clone())
.和_then(handler::destroy _order _handler);
/*汇总我们所有的订单路线*/
让我们预定路线=
索引图书路线。或(创建图书路线)。或(阅读图书路线);
/*汇总我们所有的订单路线*/
让订单\路线=创建订单\路线
.或(读取订单路径)
.或(更新订单和路线)
.或(销毁订单或路线);
/*汇总我们所有的路线*/
let routes=预订路线。或(订购路线);
  • 我怀疑这实际上是正确的行为(尽管编译和运行)

  • 对于一个相对简单的需求来说,这看起来非常丑陋

  • 最重要的是,在我的路由处理程序中,我需要调用
    async
    函数,因此需要将处理程序本身标记为
    async
    ,等等。当我将处理程序标记为
    async
    时,编译器会抱怨未来无法跨线程发送

  • 当路由处理程序本身是异步的时,如何实现共享应用程序状态

    路由处理程序的签名(它们都是相同的):

    /*匹配POST之类的路由`http://example.com/[市场]/`*/
    pub async fn create_order_处理程序(市场:String,请求:CreateOrderRequest,状态:Arc,rpc_端点:String)->Result
    
    您可以通过共享所有权(如
    Arc
    )和线程安全的内部可变性(如
    互斥锁
    RwLock
    或原子锁)来共享状态:

    使用std::sync::{Arc,Mutex};
    使用warp::Filter;
    #[tokio::main]
    异步fn main(){
    让state=Arc::new(Mutex::new(0));
    让market=warp::path!(“market”/String).map({
    让state=state.clone();
    移动|市场|{
    *state.lock().unwrap()+=1;
    格式!(“市场:{}”,市场)
    }
    });
    让plaza=warp::path!(“plaza”/String).map({
    让state=state.clone();
    搬家|广场|{
    让state=*state.lock().unwrap();
    格式!(“Plaza:{}({})”,Plaza,state)
    }
    });
    出租路线=市场或(广场);
    服务(路线)。运行([127,0,0,1],3030))。等待;
    }
    
    %curl 127.0.0.1:3030/市场/一
    市场:一
    %卷曲127.0.0.1:3030/广场/一
    广场:一(1)
    
    要执行异步工作,请使用:

    使用std::{
    绝对正确,
    sync::{Arc,Mutex},
    };
    使用warp::Filter;
    #[tokio::main]
    异步fn main(){
    让state=Arc::new(Mutex::new(0));
    让market=warp::path!(“market”/String)。然后({
    让state=state.clone();
    移动|市场|{
    让state=state.clone();
    异步移动{
    *state.lock().unwrap()+=1;
    Ok::(格式!(“市场:{}”,市场))
    }
    }
    });
    让plaza=warp::path!(“plaza”/String)。然后({
    让state=state.clone();
    搬家|广场|{
    让state=state.clone();
    异步移动{
    让state=*state.lock().unwrap();
    Ok::(格式!(“Plaza:{}({})”,Plaza,state))
    }
    }
    });
    出租路线=市场或(广场);
    服务(路线)。运行([127,0,0,1],3030))。等待;
    }
    
    这些甚至可以是单独的功能:

    使用std::{
    绝对正确,
    同步::{Arc,Mutex},
    };
    使用warp::Filter;
    #[tokio::main]
    异步fn main(){
    让state=Arc::new(Mutex::new(0));
    让市场=扭曲::路径!(“市场
    
    [dependencies]
    warp = "0.3.0"
    tokio = { version = "1.2.0", features = ["full"] }