multiple function calls within single transaction#160
Conversation
WalkthroughThis PR adds support for composing multiple Doobie database function calls within a single transaction. Three new Scala source files introduce ConnectionIO-based methods to function wrappers, a transaction executor in the engine, and comprehensive integration tests validating the transactional composition feature. ChangesTransactional composition of database function calls
Sequence DiagramsequenceDiagram
participant Caller
participant DoobieFunction
participant ConnectionIO
participant DoobieEngine
participant Database
Caller->>DoobieFunction: toConnectionIO(values)
DoobieFunction->>ConnectionIO: return unevaluated program
Caller->>DoobieFunction: toConnectionIO(values2)
DoobieFunction->>ConnectionIO: return unevaluated program
Caller->>ConnectionIO: compose multiple programs
Caller->>DoobieEngine: runConnectionIO(composed)
DoobieEngine->>Database: transact(composed)
Database-->>DoobieEngine: result or rollback
DoobieEngine-->>Caller: F[Result]
🎯 2 (Simple) | ⏱️ ~12 minutes
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
JaCoCo
|
| Overall Project | 59.84% | 🍏 |
|---|
There is no coverage information present for the Files changed
JaCoCo
|
| Overall Project | 71.07% -2.72% |
🍏 |
|---|---|---|
| Files changed | 77.6% | ❌ |
| File | Coverage | |
|---|---|---|
| DoobieEngine.scala | 100% | 🍏 |
| DoobieFunction.scala | 74.13% -4.64% |
❌ |
JaCoCo
|
| Overall Project | 91.42% | 🍏 |
|---|
There is no coverage information present for the Files changed
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@doobie/src/main/scala/za/co/absa/db/fadb/doobie/DoobieFunction.scala`:
- Around line 131-134: The eager evaluation of toFragmentsSeq(values) in
toConnectionIO (and the similar status/single/optional variants) allows
exceptions to escape before entering the ConnectionIO context; change these to
defer evaluation by wrapping the call in the library's effectful delay (e.g.,
ConnectionIO/FC delay) and then flatMap into composeFragments(...).query...
(i.e., replace the val fragments = toFragmentsSeq(values) with a delayed effect
that computes fragments inside ConnectionIO and then .flatMap(fragments =>
composeFragments(fragments).query[R].to[Seq]/.unique/.option/.status) so any
thrown exceptions are captured by the ConnectionIO/MonadError machinery.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: c36cd8b5-9b2d-4f4d-af81-41290e8dfd3b
📒 Files selected for processing (3)
doobie/src/main/scala/za/co/absa/db/fadb/doobie/DoobieEngine.scaladoobie/src/main/scala/za/co/absa/db/fadb/doobie/DoobieFunction.scaladoobie/src/test/scala/za/co/absa/db/fadb/doobie/DoobieTransactionCompositionIntegrationTests.scala
| def toConnectionIO(values: I): ConnectionIO[Seq[R]] = { | ||
| val fragments = toFragmentsSeq(values) | ||
| composeFragments(fragments).query[R].to[Seq] | ||
| } |
There was a problem hiding this comment.
Defer toFragmentsSeq(values) inside ConnectionIO to preserve error semantics.
DoobieFunction.scala eagerly evaluates val fragments = toFragmentsSeq(values) in toConnectionIO (131-134) and similarly in the status, single, and optional variants (also applies to 216-221, 255-258, 356-359). If toFragmentsSeq throws, the exception occurs before the ConnectionIO logic (and any catchNonFatal/MonadError handling in the query path) can capture it, leading to inconsistent behavior.
Replace the eager val fragments = ... with an effectful deferral using the appropriate ConnectionIO/FC “delay” API from this codebase, then flatMap into composeFragments(fragments).query... in all affected methods.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@doobie/src/main/scala/za/co/absa/db/fadb/doobie/DoobieFunction.scala` around
lines 131 - 134, The eager evaluation of toFragmentsSeq(values) in
toConnectionIO (and the similar status/single/optional variants) allows
exceptions to escape before entering the ConnectionIO context; change these to
defer evaluation by wrapping the call in the library's effectful delay (e.g.,
ConnectionIO/FC delay) and then flatMap into composeFragments(...).query...
(i.e., replace the val fragments = toFragmentsSeq(values) with a delayed effect
that computes fragments inside ConnectionIO and then .flatMap(fragments =>
composeFragments(fragments).query[R].to[Seq]/.unique/.option/.status) so any
thrown exceptions are captured by the ConnectionIO/MonadError machinery.
|
Read the code, easy to understand. It is really good and will be useful. Just some random thoughts:
|
Closes #159
Adds support for multiple function calls within single transaction in Doobie module.
Summary by CodeRabbit
New Features
Tests