6

I created a pool for MySQL database like this:

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.");

Included inside actix like this:

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");

Here come the problem, how it's possible to use it inside this info function:

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

Passing directly one instance of MySQL connection to get_infos working well, but using pool I have no idea on how to process it ?! Any help please ?

For more clarification, my goal is to use POOLING instead of using one instance only like it's the case in this code:

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.

I initiated the POOL to actix in the previous code: .data(pool.clone()) // <-- HERE

But how to pass it as parameter to get_infos function.

Thanks again in advance for your help.

Cliff Anger
  • 195
  • 2
  • 11

2 Answers2

3

For your handlers; just add the pool as a parameter, then you can pass a pinned connection to downstream functions:

// 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")
}
Martin Gallagher
  • 4,444
  • 2
  • 28
  • 26
  • Thanks, but the right way is to use it like this: `get_infos(pool: web::Data>>) -> Vec` and then from the router passing data: `.data(pool.clone())` – Cliff Anger Jul 20 '19 at 18:16
  • Adding `web::Data` and `web::block` if the DB is synchronous. – Cliff Anger Jul 20 '19 at 18:17
  • And finally of course getting the connection from the pool inside the function: `let conn = db.get().unwrap();` just like you did, I will mark it as solved, thank you. – Cliff Anger Jul 20 '19 at 18:23
0

the right answer with passing the pool through the controller :

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)
})

this is working.

ben
  • 740
  • 7
  • 16