Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add example for wrapping PostgresConnectionManager #112

Merged
merged 1 commit into from
Oct 28, 2021

Conversation

film42
Copy link
Contributor

@film42 film42 commented Oct 24, 2021

With this example we show how easy it is to wrap the postgres connection
pool to prepare several queries when a connection is created. Then, once
a connection is checked out, this examples shows how easy it is to use
the custom state to pull a prepared statement.

Inspired by #110 which requests this kind of behavior in bb8 directly,
but for now it's easy to extend any connection manager with custom
needs.

Happy hacktoberfest!

Copy link
Owner

@djc djc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this might be helpful, so thanks for putting it together!

With some style tweaks, I'm happy to merge this.

postgres/examples/custom_state.rs Outdated Show resolved Hide resolved
postgres/examples/custom_state.rs Outdated Show resolved Hide resolved
With this example we show how easy it is to wrap the postgres connection
pool to prepare several queries when a connection is created. Then, once
a connection is checked out, this examples shows how easy it is to use
the custom state to pull a prepared statement.

Inspired by djc#110 which requests this kind of behavior in bb8 directly,
but for now it's easy to extend any connection manager with your custom
needs.
@djc
Copy link
Owner

djc commented Oct 28, 2021

It's actually not alphabetic order but top-down order. But in this case they somewhat coincide.

@djc djc merged commit 687d394 into djc:main Oct 28, 2021
@seanlinsley
Copy link

I'm trying to do something similar to this, but it doesn't seem like it works. For me at least, pool.get() returns a PooledConnection not a CustomPostgresConnection so there's no way to access the statement cache.

@djc
Copy link
Owner

djc commented Oct 30, 2021

I recommend you start from this exact example, which is compile checked in CI and thus should work.

@seanlinsley
Copy link

Ah, it looks like the connection having a type of PooledConnection is expected. I get the same error when trying to specify the type in the example code:

let connection: CustomPostgresConnection = pool.get().await.expect("pool error");

So my issue seems to be more related to #57. It's not clear what type annotations are needed so bb8 pooled connections can be passed to a function. This for example fails with:

no method named query found for struct PooledConnection<'_, M> in the current scope

async fn run_query<M: bb8::ManageConnection>(connection: PooledConnection<'_, M>) {
    connection.query("", &[]).await.unwrap();
}

Sorry if this has been asked somewhere else, but if it has I can't find it.

@djc
Copy link
Owner

djc commented Oct 30, 2021

Your code sample presupposes the existence of a query() method on M::Connection. You'll need to explain to the compiler why it does. For example, M is some specific type, like CustomPostgresConnectionManager, or M::Connection implements some trait that provides a query() method of the appropriate type.

@seanlinsley
Copy link

seanlinsley commented Oct 30, 2021

Right, so how do I do that? 😅 The postgres glue code isn't implementing a trait from the tokio_postgres crate so it's not clear how these function calls are passed through to the postgres connection as it is.

Edit: so, this does work. But now every function call (I have many) is specifying NoTls when the use of TLS would be decided at runtime.

async fn run_query(connection: PooledConnection<'_, CustomPostgresConnectionManager<NoTls>>) {
    connection.query("", &[]).await.unwrap();
}

@djc
Copy link
Owner

djc commented Oct 30, 2021

Make it abstract over dyn MakeTlsConnect<Socket>?

@seanlinsley
Copy link

dyn MakeTlsConnect<Socket> gets me to:

help: specify the associated types: MakeTlsConnect<Socket, Stream = Type, TlsConnect = Type, Error = Type>

I tried multiple versions of that but couldn't work around this error:

(dyn MakeTlsConnect<...> + 'static) cannot be shared between threads safely

I also tried defining a type like #57 (comment) but ran into the same error.

@djc
Copy link
Owner

djc commented Oct 30, 2021

Add a Send bound. But all of this ends up being Rust knowledge/experience, so maybe better on Stack Overflow or users.rust-lang.org.

@seanlinsley
Copy link

Yes I don't have much experience with Rust, but this is a basic usability / documentation issue with bb8. I've tried multiple variations here, including adding Send, and I'm thrown into an ever-deeper hole of errors.

Re: posting this elsewhere, I doubt anyone's going to put in the time to meaningfully help if they're not already familiar with this project.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants