2
#[macro_use]
extern crate diesel;

use diesel::result::Error;

use actix_web::web;
use diesel::{PgConnection, QueryDsl, RunQueryDsl};
use r2d2::{Pool, PooledConnection};
use r2d2_diesel::ConnectionManager;
use schema::tests::dsl::*;

pub mod schema;

pub type MyDBConnectionManager = ConnectionManager<PgConnection>;
pub type MyPool = Pool<MyDBConnectionManager>;
pub type MyDBConnection = PooledConnection<MyDBConnectionManager>;

struct S { }

impl S {
    async fn download_and_store_object(pool: web::Data<MyPool>) -> Result<(), Error>
    {
        let conn_ = pool.get().expect("couldn't get db connection from pool");
        let conn = &conn_;

        let v_data_size: Option<i64> = web::block(move || -> Result<_, Error> {
            Ok(tests.select(b).get_result::<Option<i64>>(&**conn)?)
        }).await.unwrap();

        Ok(())

    }
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    Ok(())
}
`NonNull<pq_sys::pg_conn>` cannot be shared between threads safely
within `PooledConnection<ConnectionManager<PgConnection>>`, the trait `Sync` is not implemented for `NonNull<pq_sys::pg_conn>`
required because of the requirements on the impl of `std::marker::Send` for `&PooledConnection<ConnectionManager<PgConnection>>`
required because it appears within the type `[closure@src/main.rs:26:51: 28:10]`rustcE0277

Schema:

table! {
    tests (seq) {
        seq -> Int4,
        a -> Nullable<Bytea>,
        b -> Nullable<Int8>,
    }
}

What is the error? And how to correct it?

porton
  • 5,214
  • 11
  • 47
  • 95
  • I think you should simply clone the pool handle and get a new connection for each request (since they will be done within threads). – Netwave Jan 23 '22 at 19:07
  • @Netwave You comment answers my previous question (and has nothing to do with the above question). – porton Jan 23 '22 at 19:09
  • 1
    yes indeed. Sorry, but they are kind of related. The problem is that the connectiion cannot be shared between threads (referendces to it). So, you would have to wrap it in an `Arc` (most probably) to do so. But even so it would probably not work, why?, because your method signature expect a `&conn` not a `Arc`. The solution is move the pool handle, and ask for a connection inside the closure itself. – Netwave Jan 23 '22 at 19:14
  • @Netwave Yes, moving pool handle variant compiled. – porton Jan 23 '22 at 19:16

1 Answers1

2

As said in the comments, Conn can not be shared between threads, so in this case you would need to move the Pool handle, and get a connection from within the clusure itself:

#[macro_use]
extern crate diesel;

use diesel::result::Error;

use actix_web::web;
use diesel::{PgConnection, QueryDsl, RunQueryDsl};
use r2d2::{Pool, PooledConnection};
use r2d2_diesel::ConnectionManager;
use schema::tests::dsl::*;

pub mod schema;

pub type MyDBConnectionManager = ConnectionManager<PgConnection>;
pub type MyPool = Pool<MyDBConnectionManager>;
pub type MyDBConnection = PooledConnection<MyDBConnectionManager>;

struct S { }

impl S {
    async fn download_and_store_object(pool: web::Data<MyPool>) -> Result<(), Error>
    {

        let v_data_size: Option<i64> = web::block(move || -> Result<_, Error> {
            let conn = pool.get().expect("couldn't get db connection from pool");

            Ok(tests.select(b).get_result::<Option<i64>>(&conn)?)
        }).await.unwrap();

        Ok(())

    }
}
Netwave
  • 40,134
  • 6
  • 50
  • 93