Giter VIP home page Giter VIP logo

Comments (27)

khuey avatar khuey commented on May 31, 2024

Try conn.prepare(blahblahblah).compat().then(do_stuff)?

from bb8.

Texlo-Dev avatar Texlo-Dev commented on May 31, 2024

Okay. Now, with the following function:

async fn try_cmd(mg: Message, mut args: Args, state: Arc<State>) -> Result<()> {
    state.postgres.run(|mut conn| {
        conn.prepare("SELECT slot_1, slot_2, slot_3 FROM loadouts WHERE user_id = $1")
            .compat()
            .then(|st| {
                let query = conn.query(&st.unwrap(), &[&(mg.author.id.0 as i64)]);
               // Work with query
                Ok(())
            })
    });

    Ok(())
}

I get the following:

error[E0277]: the trait bound `std::result::Result<(), _>: core::future::future::Future` is not satisfied
  --> src/commands/loadout.rs:38:14
   |
38 |             .then(|st| {
   |              ^^^^ the trait `core::future::future::Future` is not implemented for `std::result::Result<(), _>`

error[E0277]: the trait bound `futures_util::future::then::Then<futures_util::compat::compat01as03::Compat01As03<tokio_postgres::impls::Prepare>, std::result::Result<(), _>, [closure@src/commands/loadout.rs:38:19: 41:14 conn:_, mg:_]>: futures::future::Future` is not satisfied
  --> src/commands/loadout.rs:35:20
   |
35 |     state.postgres.run(|mut conn| {
   |                    ^^^ the trait `futures::future::Future` is not implemented for `futures_util::future::then::Then<futures_util::compat::compat01as03::Compat01As03<tokio_postgres::impls::Prepare>, std::result::Result<(), _>, [closure@src/commands/loadout.rs:38:19: 41:14 conn:_, mg:_]>`
   |
   = note: required because of the requirements on the impl of `futures::future::IntoFuture` for `futures_util::future::then::Then<futures_util::compat::compat01as03::Compat01As03<tokio_postgres::impls::Prepare>, std::result::Result<(), _>, [closure@src/commands/loadout.rs:38:19: 41:14 conn:_, mg:_]>`

I'd ultimately want to port this code to async/await if possible. Any suggestions here?

from bb8.

khuey avatar khuey commented on May 31, 2024

You should probably read https://jsdw.me/posts/rust-asyncawait-preview/. I think rather than using the compat method you should import the futures 0.1 Future trait and convert only to a new style future at the outermost layer (the state.postgres.run)

from bb8.

khuey avatar khuey commented on May 31, 2024

Feel free to keep commenting but because this is not actually a bug in bb8 I'm going to close this issue.

from bb8.

Texlo-Dev avatar Texlo-Dev commented on May 31, 2024

@khuey I know this isn't an issue with bb8, but would you have a clue on how to get a solution like async/await working?

From the guide you mentioned, it says that you can use the tokio::await!() to convert an old style future to a new stylle future. So I've done something like this:

fn execute(&self, mg: Message, args: Args, state: Arc<State>) {
        tokio::run_async(async move {
            let mut resp = CommandResponse::new(mg.channel_id.0, state);
            await!(resp.text("Testing my Text").execute()).unwrap();
            tokio::await!(state.postgres.run(async move |mut conn| {
                let stmt = tokio::await!(conn.prepare("SELECT slot_1, slot_2, slot_3 FROM loadouts WHERE user_id = $1"))?;
                let query = conn.query(&stmt, &[&(mg.author.id.0 as i64)]);
                await!(resp.text("Testing my Text").execute())?;
            }))   
            Ok(())
        });
    }

However, I am greeted with this error:

error[E0271]: type mismatch resolving `<impl core::future::future::Future as core::future::future::Future>::Output == ()`
  --> src/commands/help.rs:27:9
   |
27 |         tokio::run_async(async move {
   |         ^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found ()
   |
   = note: expected type `std::result::Result<(), _>`
              found type `()`
   = note: required by `tokio::run_async`

error[E0277]: the trait bound `impl core::future::future::Future: tokio::prelude::Future` is not satisfied
  --> src/commands/loadout.rs:31:42
   |
31 |             tokio::await!(state.postgres.run(async move |mut conn| {
   |                                          ^^^ the trait `tokio::prelude::Future` is not implemented for `impl core::future::future::Future`
   |
   = note: required because of the requirements on the impl of `tokio::prelude::IntoFuture` for `impl core::future::future::Future`

error[E0271]: type mismatch resolving `<impl core::future::future::Future as core::future::future::Future>::Output == ()`
  --> src/commands/loadout.rs:28:9
   |
28 |         tokio::run_async(async move {
   |         ^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found ()
   |
   = note: expected type `std::result::Result<_, _>`
              found type `()`
   = note: required by `tokio::run_async`

Am in misinterpreting something here?

from bb8.

khuey avatar khuey commented on May 31, 2024

You should unwrap (or actually handle errors) from the await! and then get rid of the Ok(()) at the end.

from bb8.

Texlo-Dev avatar Texlo-Dev commented on May 31, 2024

Right now, I'm currently at this error.

error[E0277]: the trait bound `impl core::future::future::Future: tokio::prelude::Future` is not satisfied
  --> src/commands/loadout.rs:44:34
   |
44 |     tokio::await!(state.postgres.run(async move |mut conn| {
   |                                  ^^^ the trait `tokio::prelude::Future` is not implemented for `impl core::future::future::Future`
   |
   = note: required because of the requirements on the impl of `tokio::prelude::IntoFuture` for `impl core::future::future::Future`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277

I feel like its something to do with the run() method not directly returning a future?

from bb8.

khuey avatar khuey commented on May 31, 2024

postgres.run wants an old style future, not the async stuff. I think you can just get rid of the async keyword there and fix up the return value.

from bb8.

Texlo-Dev avatar Texlo-Dev commented on May 31, 2024

Problem with that being, I want to be able to use the await macro inside, since I have async operations that rely on the result from the query.

from bb8.

khuey avatar khuey commented on May 31, 2024

Ok, then follow the steps in the article that I linked about converting from a new style future to an old style one?

from bb8.

Texlo-Dev avatar Texlo-Dev commented on May 31, 2024

Well I ended up doing that.
Now I need to fix to return value to what?

from bb8.

khuey avatar khuey commented on May 31, 2024

Idk, what errors do you have now?

from bb8.

Texlo-Dev avatar Texlo-Dev commented on May 31, 2024
error[E0277]: the trait bound `(): core::future::future::Future` is not satisfied
  --> src/commands/loadout.rs:47:10
   |
47 |         .then(move |st| {
   |          ^^^^ the trait `core::future::future::Future` is not implemented for `()`

error[E0277]: the trait bound `futures_util::future::then::Then<futures_util::compat::compat01as03::Compat01As03<tokio_postgres::impls::Prepare>, (), [closure@src/commands/loadout.rs:47:15: 49:10 conn:_, mg:_]>: tokio::prelude::Future` is not satisfied
  --> src/commands/loadout.rs:44:34
   |
44 |     tokio::await!(state.postgres.run(move |mut conn| {
   |                                  ^^^ the trait `tokio::prelude::Future` is not implemented for `futures_util::future::then::Then<futures_util::compat::compat01as03::Compat01As03<tokio_postgres::impls::Prepare>, (), [closure@src/commands/loadout.rs:47:15: 49:10 conn:_, mg:_]>`
   |
   = note: required because of the requirements on the impl of `tokio::prelude::IntoFuture` for `futures_util::future::then::Then<futures_util::compat::compat01as03::Compat01As03<tokio_postgres::impls::Prepare>, (), [closure@src/commands/loadout.rs:47:15: 49:10 conn:_, mg:_]>`

error: aborting due to 2 previous errors

This is using the compat() way to be able to return a futures 0.1 future.

from bb8.

khuey avatar khuey commented on May 31, 2024

And what's in the then closure?

from bb8.

Texlo-Dev avatar Texlo-Dev commented on May 31, 2024
.then(move |st| {
            let query = conn.query(&st.unwrap, [&(mg.author.id.0 as i64)]);
        })

from bb8.

khuey avatar khuey commented on May 31, 2024

The return value of that closure needs to be a future. Also you're not actually calling unwrap, and you wouldn't need it at all if you used and_then instead of then for this closure.

Try something like

.and_then(move |st| {
    conn.query(&st, [&(mg.author.id.0 as i64)])
})

from bb8.

Texlo-Dev avatar Texlo-Dev commented on May 31, 2024

@khuey Sorry about the delay,
So this is what we have now:

async fn my_cmd(mg: Message, mut args: Args, state: Arc<State>) -> Result<()> {
    let mut resp = CommandResponse::new(mg.channel_id.0, state);
    await!(resp.text("Testing my Text").execute())?;
    tokio::await!(state.postgres.run(move |mut conn| {
        conn.prepare("SELECT slot_1, slot_2, slot_3 FROM loadouts WHERE user_id = $1")
        .compat()
        .and_then(move |st| {
            let query = conn.query(&st, &[&(mg.author.id.0 as i64)]);
        })
    }));
    Ok(())
}

This yields the following:

   |
47 |         .and_then(move |st| {
   |          ^^^^^^^^ the trait `core::future::future::Future` is not implemented for `()`
   |
   = note: required because of the requirements on the impl of `futures_core::future::TryFuture` for `()`

error[E0277]: the trait bound `futures_util::try_future::and_then::AndThen<futures_util::compat::compat01as03::Compat01As03<tokio_postgres::impls::Prepare>, (), [closure@src/commands/loadout.rs:47:19: 49:10 conn:_, mg:_]>: tokio::prelude::Future` is not satisfied
  --> src/commands/loadout.rs:44:34
   |
44 |     tokio::await!(state.postgres.run(move |mut conn| {
   |                                  ^^^ the trait `tokio::prelude::Future` is not implemented for `futures_util::try_future::and_then::AndThen<futures_util::compat::compat01as03::Compat01As03<tokio_postgres::impls::Prepare>, (), [closure@src/commands/loadout.rs:47:19: 49:10 conn:_, mg:_]>`
   |
   = note: required because of the requirements on the impl of `tokio::prelude::IntoFuture` for `futures_util::try_future::and_then::AndThen<futures_util::compat::compat01as03::Compat01As03<tokio_postgres::impls::Prepare>, (), [closure@src/commands/loadout.rs:47:19: 49:10 conn:_, mg:_]>`

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0277`.

So if I understand correctly, I have to return a future in the .and_then() closure as well?

from bb8.

khuey avatar khuey commented on May 31, 2024

Right. Try something like this:

async fn my_cmd(mg: Message, mut args: Args, state: Arc<State>) -> Result<()> {
    let mut resp = CommandResponse::new(mg.channel_id.0, state);
    await!(resp.text("Testing my Text").execute())?;
    let results = tokio::await!(state.postgres.run(move |mut conn| {
        conn.prepare("SELECT slot_1, slot_2, slot_3 FROM loadouts WHERE user_id = $1")
            .then(move |r| {
                match r {
                    Ok(st) => {
                        conn.query(&st, &[&(mg.author.id.0 as i64)])
                            .then(move |r| {
                                match r {
                                    Ok(results) => Ok((results, conn)),
                                    Err(e) => {
                                        eprintln!("Got postgres error on query: {}", e);
                                        Err(((), conn))
                                    }
                                }
                            })
                    }
                    Err(e) => {
                        eprintln!("Got postgres error on prepare: {}", e);
                        Err((), conn)
                    }
                }
            })
    }))?;
    println!("My results are {:?}", results);
    Ok(())
}

from bb8.

khuey avatar khuey commented on May 31, 2024

https://github.com/khuey/bb8/blob/master/postgres/examples/static_select.rs has a working example without async/await, btw, if you haven't seen that.

from bb8.

Texlo-Dev avatar Texlo-Dev commented on May 31, 2024

A brief question:
On the error handling for the first prepare statement, why do you return an Err((), conn)? Won't Rust be expecting a Then with the result of the prepare?

from bb8.

Texlo-Dev avatar Texlo-Dev commented on May 31, 2024

Yeah...it seems like using this library with async/await is going to be much more difficult than I had anticipated.

from bb8.

khuey avatar khuey commented on May 31, 2024

The basic premise of a the run function in bb8 is that you "check out" a connection from a pool, do some stuff with it, and return it when you're done. You can see the type signature of run https://github.com/khuey/bb8/blob/36b635b4741f36af2907fd32fe91b281ca0a2b93/src/lib.rs#L721. run takes a closure that returns something that implements IntoFuture<Item = (T, M::Connection), Error = (E, M::Connection)>.

In old style futures Result<T, E> implements IntoFuture<Item = T, Error = E> so you'll see that a lot. Operations that can fail but happen synchronously take advantage of this: and_then and then combinator closures often produce a Result instead of a "real" future.

from bb8.

Texlo-Dev avatar Texlo-Dev commented on May 31, 2024

@khuey One thing I don't understand.
What is the Either enum that you are using and how do I get it?
It doesn't seem to be part of the futures package.

from bb8.

Texlo-Dev avatar Texlo-Dev commented on May 31, 2024

I don't believe that the PostgreSQL example provided even compiles correctly though. :(

from bb8.

khuey avatar khuey commented on May 31, 2024

Either comes from https://docs.rs/futures/0.1.25/futures/future/enum.Either.html

If you check out this repository and cargo build --all --examples that fails?

from bb8.

Texlo-Dev avatar Texlo-Dev commented on May 31, 2024

It doesn't fail, just thought I saw some syntax errors there. I guess not.

from bb8.

Texlo-Dev avatar Texlo-Dev commented on May 31, 2024

However, I noticed that the futures crate does clash with the futures-preview crate I have installed. Do you know a way to have both installed under different names?

from bb8.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.