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 QueryExecutor trait #338

Merged
merged 4 commits into from
Aug 28, 2024
Merged

Conversation

CodesInChaos
Copy link
Contributor

@CodesInChaos CodesInChaos commented Aug 28, 2024

The trait enables writing functions that don't care if they're executed in a transaction or directly on a client.

Handling of Send needs to be discussed. Currently I'm not constraining anything to Send, but perhaps the returned futures need to be, but that might require adding constraints to some of the generic arguments (e.g. QueryResult) as well.

Closes #339

@edgedb-cla
Copy link

edgedb-cla bot commented Aug 28, 2024

All commit authors signed the Contributor License Agreement.
CLA signed

@CodesInChaos CodesInChaos force-pushed the query-executor branch 2 times, most recently from cc62585 to 129d062 Compare August 28, 2024 09:12
The trait enables writing functions that don't care if they're executed in a transaction or directly on a client
@aljazerzen
Copy link
Contributor

This looks good.

For reference, postgres crate has similar trait, named GenericClient. I think that QueryExecutor is a better name. Other db clients that I've checked (mysql, tiberious, sqlite) don't have such traits.

@aljazerzen
Copy link
Contributor

I think we'd need to bump MSRV from 1.72 to 1.75 for "async fn returning impl Trait".

This is a reasonable, since 1.75 is 8 versions before current stable (1.80.1).

/// In particular &Client and &mut Transaction
pub trait QueryExecutor {
/// see [Client::query]
fn query<R, A>(self, query: &str, arguments: &A) -> impl Future<Output = Result<Vec<R>, Error>>
Copy link
Contributor

Choose a reason for hiding this comment

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

Handling of Send needs to be discussed. Currently I'm not constraining anything to Send, but perhaps the returned futures need to be, but that might require adding constraints to some of the generic arguments (e.g. QueryResult) as well.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think this future should be required to be Send.

Imagine that for some reason, the query results contains a Rc. Imagine that during poll of the future this Rc is somehow mutated & moved across threads. That is not ok.

This is obscure and unlikely to happen and also not a concern of this PR - it should be QueryResult that enforces this constraint.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think adding +Sync to the return value requires adding +Sync on QueryResult, or it won't compile. I can easily make that change.

But for some reason neither Client nor Transaction had that constraint on QueryResult (which isn't a problem per-se, since the trait having stricter constraints isn't a problem). Does that mean that Client/Transaction only work on single threaded executors?

But I have little experience with async, so I don't fully understand how Sync interacts with it.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think adding +Sync

You mean Send, right?

Does that mean that Client/Transaction only work on single threaded executors?

No, it means that the future that these function return can be sent between threads. It is a requirement that these function are implemented in a way that can be multi-threaded.

This requirement is a good thing, but it could be too strict for some cases.

Copy link
Contributor Author

@CodesInChaos CodesInChaos Aug 28, 2024

Choose a reason for hiding this comment

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

You mean Send, right?

yes

It looks like constraining the Futures in the trait to Send requires constraining QueryResult to be Send as well. I've added those constraints to the PR.

Copy link
Contributor

Choose a reason for hiding this comment

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

That's right: for concrete types, Rust compiler can infer if they are Send (and Sync) or not. It's only for generics or dyn types that you need to add an explicit Send.

@aljazerzen aljazerzen merged commit 3c4cc04 into edgedb:master Aug 28, 2024
4 checks passed
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.

Add a trait to abstract over query executors (Client, Transaction)
2 participants