Add opt-in MongoDB multi-document transactions to GORM for MongoDB#15744
Open
codeconsole wants to merge 2 commits into
Open
Add opt-in MongoDB multi-document transactions to GORM for MongoDB#15744codeconsole wants to merge 2 commits into
codeconsole wants to merge 2 commits into
Conversation
GORM for MongoDB previously treated a transaction as a client-side flush boundary: pending writes were batched and flushed on commit, but each write auto-committed individually and nothing rolled back when a later operation failed. This adds real server-side transactions backed by a com.mongodb.client.ClientSession. When grails.mongodb.transactional is enabled (default false), a GORM transaction starts a ClientSession and MongoDB transaction and every read and write for the session runs within it, committing or aborting atomically. A new MongoTransaction drives the commit (retrying on an UnknownTransactionCommitResult) and the abort, and closes the session afterwards. The feature is opt-in and degrades gracefully: a standalone topology is detected at runtime and falls back to the legacy flush-only behavior with a one-time warning. Identifier generation for native Long ids is intentionally left non-transactional, mirroring the semantics of database sequences.
borinquenkid
left a comment
Member
There was a problem hiding this comment.
Hi @codeconsole,
Please keep an eye on #15678 (GORM: Shared Mapping Registry O(M+N) Scaling), which introduces significant internal structural refactoring to how GormRegistry and MongoDatastore handle tenant routing and fallback resolution.
Since that optimization is targeting 8.0.x-hibernate7, your transaction changes here will be downstream from those modifications. It might be worth checking your diff against those updates to prevent initialization order regressions or multi-tenant signature mismatches when merging into the 8.0 release line.
✅ All tests passed ✅Test SummaryCI / Functional Tests (Java 21, indy=false) > :grails-test-examples-scaffolding:integrationTest
CI / Functional Tests (Java 25, indy=false) > :grails-test-examples-scaffolding:integrationTest
🏷️ Commit: 59d51fd Learn more about TestLens at testlens.app. |
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.
What
Adds opt-in MongoDB multi-document transactions to GORM for MongoDB.
Previously GORM for MongoDB never used a
com.mongodb.client.ClientSession: every driver write was issued session-less and auto-committed, so a GORM transaction was only a client-side flush boundary — writes already flushed within it were not rolled back on failure (no server-side atomicity).With
grails.mongodb.transactional = true, a GORM transaction now starts and drives a realClientSessiontransaction, so all reads and writes commit or roll back atomically:How
MongoTransaction(replaces the flush-onlySessionOnlyTransactionwhen enabled):commit()flushes thencommitTransaction()(with bounded retry onUnknownTransactionCommitResult),rollback()aborts; both close the session. On commit failure the GORM session cache is cleared.AbstractMongoSessionholds the activeClientSession, starts it inbeginTransactionInternal(), and routes every read/write through small helpers that pass the session when a transaction is active and stay session-less otherwise.MongoQuery, and theMongoStaticApi/MongoEntitysurface.DatastoreTransactionManageris unchanged — it already orchestrates flush/commit/rollback; this just supplies aTransactionthat drives a server transaction.Opt-in and fallback
grails.mongodb.transactionaldefaults tofalse) — no behavior change for existing apps.Boundaries
Longcounter) is intentionally left non-transactional, mirroring database sequence semantics.PROPAGATION_REQUIRED) is supported;REQUIRES_NEW/NESTEDare not.Tests
MongoTransactionSpec— commit persists multiple docs; rollback discards them on the server; read-your-writes within a transaction; cross-collection atomic rollback;findOneAndDeleteparticipates in the transaction; nested GORMREQUIRES_NEW.MongoTransactionDisabledSpec— default-off keeps the legacy flush behavior.Targets
8.0.x. Independent of #15743; this is also the prerequisite for a follow-up Spring Data MongoDB interop module.