Repository navigation
fix(jdbc): begin non-auto-commit transactions lazily (#99) - #125
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
setAutoCommit(false)no longer sendsBEGIN, andcommit()androllback()no longer begin the next transaction. An idle non-auto-commit connection holds no Hrana stream, so sqld can no longer expire a stream under it. The next statement begins the transaction.Protocol basis. Hrana over HTTP closes idle streams after inactivity and requires serial baton use, so a stream held from
setAutoCommit(false)is a resource with a ten second lifetime, not a transaction handle.Contract. Hrana 3 is the source of truth for transport, values, and metadata.
java.sqlis the source of truth for the JDBC surface. xerial/sqlite-jdbc is a behavioral reference and conformance foundation, never a copy target.Fixes #99
Type of Change
Pending-begin semantics
setAutoCommit(false)records the state and sends nothing. The pending-begin state is derived as!autoCommit && baton == null. A second boolean would be a second source of truth for a fact the baton already carries.BEGINin its own pipeline, checks the result, and only then sends the statement on the new baton.BEGINis never pipelined with the statement, because Hrana over HTTP executes every request in a pipeline even after an earlier one fails.commit()orrollback()with no work sends nothing and succeeds. Probed against xerial 3.53.4.0:commit()with no work, a repeatedcommit(), androllback()with no work all succeed there.commit()orrollback()after work sends the command, then closes the stream. On a server or transport error the baton stays, so the retry and rollback-on-the-same-stream behavior from Failed COMMIT or ROLLBACK leaves a stale baton, so the transaction cannot be rolled back #98 is unchanged.setAutoCommit(true)andclose()send nothing from a pending begin.Divergence
IMMEDIATEorEXCLUSIVEtransaction takes its write lock at the first statement, not atsetAutoCommit(false)orcommit(). xerial begins eagerly because it owns the transaction locally. Hrana over HTTP expires an idle stream, so an eager begin cannot be held.TransactionLifecycleITtest names now state the lazy timing.COMMITthenCLOSE) instead of one. Combining them into one pipeline would destroy the stream whenCOMMITfails and remove the Failed COMMIT or ROLLBACK leaves a stale baton, so the transaction cannot be rolled back #98 guarantee that the caller can roll back on the same stream.Evidence
Base
8c9381b856b9f9ba42fb3e28de5a0cd816de0509, head2495f95f8cf06646ee5c1ae0ea11c03eb67fcf00.Red at base:
./mvnw -pl libsql-jdbc test -Dtest=LibsqlConnectionTestgivesTests run: 27, Failures: 9, Errors: 1. The failures are the eagerBEGIN, the eager re-begin after commit and rollback, and requests sent from a pending begin by commit, rollback, andsetAutoCommit(true)../mvnw -pl libsql-itests -am verify -Dit.test=TransactionLifecycleITgives 2 errors, bothThe stream has expired due to inactivity, onaStatementAndCommitAfterAnIdlePeriodLongerThanTheStreamTimeoutSucceedandanIdleConnectionHoldsNoStreamAfterCommit.Green at head:
LibsqlConnectionTest:Tests run: 27, Failures: 0, Errors: 0.TransactionLifecycleIT:Tests run: 6, Failures: 0, Errors: 0../mvnw -pl libsql-itests -am verify: 211 unit and 24 integration tests, BUILD SUCCESS../mvnw -pl libsql-conformance -am verify: 115 tests, 1 skipped, BUILD SUCCESS../mvnw -pl libsql-conformance -am -Pxerial-control verify: 100 tests, 1 skipped, BUILD SUCCESS../mvnw spotless:check: BUILD SUCCESS../mvnw test: 211 tests, BUILD SUCCESS../mvnw -pl libsql-jdbc -am package -DskipTests: BUILD SUCCESS.HikariCpIntegrationITrun on its own: 1 test, BUILD SUCCESS.Perf
Hrana pipeline round trips for
setAutoCommit(false),commit(), fifteen idle seconds, then oneSELECT, counted with a scripted client:BEGIN, thenSELECT). Total 2.The head sends no request during the idle window and totals fewer round trips than the base. With one INSERT before the commit the base totals 4 and the head totals 6, from the commit close described in the divergence note.
Checklist
./mvnw spotless:check)../mvnw clean verifyequivalent run above).setAutoCommitcontract javadoc).