Skip to content

Oracle Transaction Priority Guide - #1852

Open
radovanradic wants to merge 12 commits into
masterfrom
micronaut-data-transaction-priority
Open

radovanradic wants to merge 12 commits into
masterfrom
micronaut-data-transaction-priority

Conversation

@radovanradic

@radovanradic radovanradic commented Sep 1, 2026 •

Copy link
Copy Markdown
Contributor

Oracle Transaction Priority Guide

Adds the guide "Prioritize Oracle Transactions with Micronaut Data JDBC" (micronaut-data-oracle-transaction-priority), covering @OracleTransactional priorities and the OracleTransactionPriorityException added in Micronaut Data 5.2.0.

What the guide builds

A small inventory app where two operations compete for the same row:

  • Stock reconciliation, @OracleTransactional(priority = LOW): locks the item with a derived findByIdForUpdate query (SELECT ... FOR UPDATE) and simulates a slow external count.
  • Customer checkout, @OracleTransactional(priority = HIGH): waits for the same row lock. After the configured wait target, Oracle rolls back the reconciliation and the checkout commits.
  • TransactionPriorityExceptionHandler: maps OracleTransactionPriorityException (ORA-63300/ORA-63302) to 409 Conflict through ErrorResponseProcessor, instead of a 500.
  • Explicit rollback handling: the guide explains why a priority rollback is not retried automatically, and how to retry safely.

Languages

Java, Groovy, Kotlin and Python (Pyronaut).

  • The JVM variants each have their own application.properties.
  • The Python variant uses python/config/application.toml, and the guide text shows TOML config and pyronaut commands for Python.
  • application.properties is not shared, because the shared resources are copied into the Python config/ directory and its copy-to-container path only exists in the JVM layout.

Oracle setup

Test Resources starts gvenzl/oracle-free and copies priority-txns.sql into /container-entrypoint-startdb.d. The script runs as SYSDBA and sets PRIORITY_TXNS_MODE=ROLLBACK, PRIORITY_TXNS_HIGH_WAIT_TARGET=5 and PRIORITY_TXNS_MEDIUM_WAIT_TARGET=10 (SCOPE=MEMORY) for the container database and FREEPDB1.

Tests

The HTTP tests use @MicronautTest(transactional = false), so each request runs its own transaction:

  • A reconciliation without contention commits (RECONCILED).
  • A HIGH checkout rolls back a LOW reconciliation that is holding the lock. The reconciliation request returns 409 with the handler's message, and only the checkout is committed. The test waits for the real row lock first, using a FOR UPDATE NOWAIT probe (ORA-00054).
  • countSeconds outside 1..120 returns 400 Bad Request (Bean Validation).

Verification

  • Gradle Java, Groovy and Kotlin, and Maven Java: tests pass against Oracle Free through Test Resources, locally and in CI.
  • Python: micronautDataOracleTransactionPriorityBuildPython passes locally with Pyronaut 0.0.6 and graalpy3.13-25.4.4 (all tests, against Oracle).
  • Docs: all six variants render with no Asciidoctor warnings.

Known CI failure

The Python project fails in CI with pyenv: command not found / pyronaut: command not found, because the Test Guides workflow doesn't install pyenv, GraalPy or Pyronaut. master fails the same way for every Python guide (for example, micronautSecurityBasicauthBuild in run 36672950473). This needs a separate CI infrastructure fix; it isn't caused by this guide.

micronaut-data-oracle-transaction-priority-gradle-groovy.pdf
micronaut-data-oracle-transaction-priority-gradle-java.pdf
micronaut-data-oracle-transaction-priority-gradle-kotlin.pdf
micronaut-data-oracle-transaction-priority-maven-groovy.pdf
micronaut-data-oracle-transaction-priority-maven-java.pdf
micronaut-data-oracle-transaction-priority-pyronaut-python.pdf

…n priority guide

- Map OracleTransactionPriorityException to 409 Conflict with an ExceptionHandler
- Replace the controller state machine with plain endpoints on the blocking executor
- Use the derived findByIdForUpdate query instead of a native query
- Wait for the real row lock in the test with a FOR UPDATE NOWAIT probe
- Add a test for a reconciliation that commits without contention
- Rewrite the guide text, drop the removed helpWithMicronaut snippet, add license headers
- Port the inventory service, controller, exception handler and tests to Groovy and Kotlin
- Add a Pyronaut Python variant with application.toml and a pytest module
- Move application.properties into the JVM language directories, so the Python
  project does not get a copy-to-container path that only exists in JVM layouts
- Show TOML configuration and Pyronaut commands for Python in the guide text

The Gradle Java, Groovy and Kotlin tests pass against Oracle. The Python tests are
unverified: locally, pyronaut test fails before any guide code runs, because the
installed Pyronaut SDK (0.0.3, GraalPy 25.3.4.1) does not match the GraalPy
25.4.4 used by Micronaut Platform 5.2.0. Existing Python guides fail the same way
locally. pyronaut install and validate-config pass.
- Build a new InventoryItem instead of dataclasses.replace, which does not accept
  the entities that the repository returns
- Send the concurrent reconciliation with CompletableFuture, because the GraalPy
  context does not allow Python threads

With Pyronaut 0.0.6 (GraalPy 25.4.4), micronautDataOracleTransactionPriorityBuildPython
passes: all Python tests pass against Oracle, including the priority rollback.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants