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

Standalone transactions #369

Open
aljazerzen opened this issue Dec 17, 2024 · 6 comments · May be fixed by #373
Open

Standalone transactions #369

aljazerzen opened this issue Dec 17, 2024 · 6 comments · May be fixed by #373

Comments

@aljazerzen
Copy link
Contributor

aljazerzen commented Dec 17, 2024

Current transaction API allows little control over how the transaction is retried and requires all work to happen within the transaction's closure.

This means that there are use-cases where more granular access to the transaction would be needed.
In #329 (comment) I've proposed the following API:

impl Client {
    fn start_transaction() -> Result<Transaction, Error> { ... }

    /// this is what is called .transaction right now
    fn within_transaction(body: FnMut -> Future<...>) -> Result<...> { ... }
}

impl Transaction {
    /// Commit (can retry only network errors)
    async fn commit() -> Result<...>
}

impl Drop for Transaction {
    /// Does the rollback
}

Apparently, @tiberiusferreira has already implemented this in their fork: tiberiusferreira@0cc5f57#diff-608add6cc9859de62fac8b605b75549b985354b28530c7c1b07180ccd86fd729R416

Internally, it has been pointed out that this API should be similar across all language bindings, so that we don't have to rediscover the wheel for each language.

@tiberiusferreira
Copy link

tiberiusferreira commented Dec 17, 2024

Hey, there are other issues with the current closure approach, or maybe misunderstandings on my part.

  1. You can only return EdgeDB errors from it, but other, user defined, errors may happen and would be useful to return
  2. I'm not sure how to signal that I want to rollback the transaction (and not retry, just return from it) from the closure

BTW, the "standalone" transaction is the model implemented by sqlx allowing users to explicitly commit and rollback , so it will probably be familiar to users coming from it.

@aljazerzen
Copy link
Contributor Author

For 1., I've outlined the workaround in this comment: #329 (comment).

Basically, make the return type of the closure Result<Result<T, YourError>, edgedb_tokio::Error>.

For 2., there is no way of doing that, apart from returning an EdgeDB error.

Which adds a point for standalone transactions.

And yes, sqlx and postgres, both do it this way.


@tiberiusferreira, would you be interested in up-streaming your fork via a PR to this repo? I haven't looked much at the code, but if it implements this API, it would benefit edgedb-rust.

@tiberiusferreira
Copy link

tiberiusferreira commented Dec 17, 2024

would you be interested in up-streaming your fork via a PR to this repo? I haven't looked much at the code, but if it implements this API, it would benefit edgedb-rust.

Oh yeah, for sure. I'll clean it up and make a PR.
Thank you very much!

@aljazerzen
Copy link
Contributor Author

After discussion with the team, we concluded that:

  • the current api (with the closure) is better at guiding the users away from not handling serialization errors.
  • a "standalone transaction" API is needed for some use-cases.
  • we should implement the API as proposed @tiberiusferreira in the linked PR,
  • we should not remove the current API, and keep it as the recommended API.

@tiberiusferreira I've taken your PR, taken parts of it and refactored the rest. The final version is in #373. Thank you for your help with the initial draft here.

@aljazerzen aljazerzen linked a pull request Jan 10, 2025 that will close this issue
@tiberiusferreira
Copy link

Awesome! Thank you for all the work here! Excited about going back to using the official crate!

@aljazerzen
Copy link
Contributor Author

On second thought, I might not merge this features. That's because we have a hypotesis that the current API (with the closure) lacks only a way to abort the transaction and the new API is much easier to write subtle bugs with (since it lacks retries). If this is the case, we should rather add a way to abort the transaction to the current API.

@tiberiusferreira Can I see snippets of your code to see if my theory holds? You might be able to use the current API (if we add a way to abort the transaction). If you don't want to share it publicly, you can message me on Discord (username aljazerzen).

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