【问题标题】:How to use pooling of database inside function using actix?如何使用actix在函数内部使用数据库池?
【发布时间】:2019-11-25 17:21:37
【问题描述】:

我为 MySQL 数据库创建了一个池,如下所示:

let database_url = env::var("DATABASE_URL").expect("set DATABASE_URL");

let manager = ConnectionManager::<MysqlConnection>::new(database_url);
let pool = r2d2::Pool::builder()
    .build(manager)
    .expect("Failed to create pool.");

像这样包含在 actix 中:

HttpServer::new(move || App::new()
    .data(pool.clone()) // <-- HERE
    .service(
        web::resource("/infos")
          .route(web::post().to(get_infos))
    ))

    .bind("127.0.0.1:8080")?
    .start();

println!("Starting http server: 127.0.0.1:8080");

问题来了,如何在这个 info 函数中使用它:

pub fn get_infos(conn: &MysqlConnection) -> Vec<Book> {
    all_books
        .order(books::id.desc())
        .load::<Book>(conn)
        .expect("error loading the books")
}

直接将 MySQL 连接的一个实例传递给 get_infos 运行良好,但使用池我不知道如何处理它?!有什么帮助吗?

为了更清楚,我的目标是使用 POOLING 而不是只使用一个实例,就像这段代码中的情况一样:

let database_url = env::var("DATABASE_URL").expect("set DATABASE_URL");
let conn = MysqlConnection::establish(&database_url).unwrap();
// And then passing as argument "conn" to get_infos function.

我在前面的代码中启动了 POOL 到 actix: .data(pool.clone()) // <-- HERE

但是如何将它作为参数传递给get_infos函数。

再次提前感谢您的帮助。

【问题讨论】:

    标签: rust rust-actix rust-diesel actix-web


    【解决方案1】:

    对于您的处理程序;只需将池作为参数添加,然后您可以将固定连接传递给下游函数:

    // Data = actix_web::web::Data
    pub fn get_all_books(pool: Data<Pool>) -> HttpResponse {
        let connection = pool.get().expect("Failed to get connection");
        let books = get_infos(&connection);
    
        HttpResponse::Ok().json(books)
    }
    
    pub fn get_infos(connection: &MysqlConnection) -> Vec<Book> {
        all_books
            .order(books::id.desc())
            .load::<Book>(conn)
            .expect("error loading the books")
    }
    

    【讨论】:

    • 谢谢,但正确的方法是这样使用:get_infos(pool: web::Data&lt;Pool&lt;ConnectionManager&lt;MysqlConnection&gt;&gt;&gt;) -&gt; Vec&lt;Book&gt;,然后从路由器传递数据:.data(pool.clone())
    • 如果数据库是同步的,则添加 web::Dataweb::block
    • 最后当然是从函数内部的池中获取连接:let conn = db.get().unwrap(); 就像你一样,我会将其标记为已解决,谢谢。
    【解决方案2】:

    通过控制器传递池的正确答案:

    let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
    let manager = ConnectionManager::<MysqlConnection>::new(database_url);
    let pool = r2d2::Pool::builder()
    .build(manager)
    .expect("Failed to create pool.");
    HttpServer::new(move || {
        App::new()
            .data(pool.clone())
            .route("/", web::get().to(index))
            .configure(todoController::init)
    })
    

    这是有效的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-06
      • 2016-06-02
      • 2019-03-21
      • 2012-05-09
      • 2022-11-19
      • 2017-04-03
      相关资源
      最近更新 更多