sfackler / rust-postgres

Native PostgreSQL driver for the Rust programming language
Apache License 2.0
3.47k stars 439 forks source link

Asynchronous transaction support improvements #505

Closed djc closed 4 years ago

djc commented 4 years ago

In the process of updating bb8 for async/await, I'm running into some issues trying to test transaction support:

error[E0505]: cannot move out of `connection` because it is borrowed
  --> postgres/examples/txn.rs:31:38
   |
29 |         let txn = match connection.transaction().await {
   |                         ------------------------------
   |                         |
   |                         borrow of `connection` occurs here
   |                         a temporary with access to the borrow is created here ...
30 |             Ok(txn) => txn,
31 |             Err(e) => return Err((e, connection)),
   |                                      ^^^^^^^^^^ move out of `connection` occurs here
32 |         };

If I try to reproduce this problem in a simplified example, I don't see a similar problem:

#[derive(Debug)]
struct A {}

#[derive(Debug)]
struct B<'a> {
    a: &'a mut A,
}

impl A {
    async fn sub(&mut self) -> Result<B<'_>, Error> {
        Ok(B { a: self })
    }
}

enum Error {}

fn take(a: A) {
    unimplemented!()
}

async fn fun() -> () {
    let mut a = A {};
    let b = match a.sub().await {
        Ok(b) => b,
        Err(_) => return take(a),
    };
    println!("{:?}", b)
}

Any thoughts on how to solve this/what the problem is here?

sfackler commented 4 years ago

You shouldn't need to return the connection by value in the error case, just have your method take a reference to the client.

djc commented 4 years ago

That return is used conceptually to return the connection to the pool, though, so I think using ownership to ensure we don't do anything silly around that is preferable.

sfackler commented 4 years ago

Connection pools traditionally continue to own the connections, and just lease out borrows via e.g. smart pointers. e.g. https://docs.rs/r2d2/0.8.6/r2d2/struct.PooledConnection.html

djc commented 4 years ago

Yeah, we're currently discussing using that model in the PR. The bb8 maintainer thinks that it's easier to leak connections using smart pointers like that.

sfackler commented 4 years ago

How would you leak a connection?

djc commented 4 years ago

Not sure! If you want to discuss, maybe participate in https://github.com/khuey/bb8/pull/37.