-
Notifications
You must be signed in to change notification settings - Fork 4
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
feat: nested transactions #194
Conversation
Codecov Report
@@ Coverage Diff @@
## main #194 +/- ##
==========================================
- Coverage 96.30% 96.17% -0.13%
==========================================
Files 81 81
Lines 2029 2065 +36
Branches 269 269
==========================================
+ Hits 1954 1986 +32
- Misses 70 74 +4
Partials 5 5
Flags with carried forward coverage won't be shown. Click here to find out more.
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left some minor comments but I think the big thing is that Postgres doesn't support nested transactions:
Issuing BEGIN when already inside a transaction block will provoke a warning message. The state of the transaction is not affected. To nest transactions within a transaction block, use savepoints (see SAVEPOINT).
https://www.postgresql.org/docs/current/sql-begin.html
I worry that what's happening is a sequence of commands like this:
BEGIN
statements intended for outer transaction
BEGIN ; warning but ultimately a no-op
statements intended for inner transaction
error occurs
ROLLBACK ; rolls back the outer transaction because Postgres does not support nested txns
COMMIT ; intended to commit outer transaction, but actually a no-op with a warning
That said, I could be wrong about this and need to look at Knex more because it does have some savepoint support (https://github.com/knex/knex/blob/dc6dbbf900c863a9992352ae097040eb6c8d16bd/lib/execution/transaction.js#L110-L120).
@@ -0,0 +1,101 @@ | |||
import { ViewerContext } from '@expo/entity'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test's filename has a typo in "Postgres"
} | ||
|
||
public static async createOrTruncatePostgresTable(knex: Knex): Promise<void> { | ||
await knex.raw('CREATE EXTENSION IF NOT EXISTS "uuid-ossp"'); // for uuid_generate_v4() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tangent: we should upgrade the tests to use Postgres 14 and use gen_random_uuid
packages/entity-database-adapter-knex/src/PostgresEntityQueryContextProvider.ts
Show resolved
Hide resolved
I dug into this some more and am more convinced Knex does the right thing and uses SAVEPOINT and ROLLBACK TO for nested transactions.
I haven't verified this by actually running the code, only reading it, but I'm optimistic. |
Yep, Knex uses savepoints. I verified this by running tests with Also the integration test tests for the case you specify above by doing nested rollbacks and commits in the parent transaction after the nested rollback. |
For the
|
Why
There's a bug in the Expo server of the following nature:
The exact text of the error is
current transaction is aborted
(for postgres database adapter).To fix this, nested transactions are needed so that only the inner transaction rolls back on a postgres error and the outer transaction is allowed to continue.
How
With this PR, the code becomes:
Test Plan
Run the new tests.