QRun-IO/ci-policy: ci / fork-guard (pull_request) Skipped
QRun-IO/ci-policy: native / fork-deny (pull_request) Skipped
QRun-IO/ci-policy: native / dotnet-0 (pull_request) Skipped
QRun-IO/ci-policy: ci / head-profile (pull_request) Skipped
QRun-IO/ci-policy: ci / repository-policy (pull_request) Skipped
QRun-IO/ci-policy: ci / application-template-0 (pull_request) Skipped
QRun-IO/ci-policy: ci / gradle-1 (pull_request) Skipped
QRun-IO/ci-policy: ci / java-core-2-head (pull_request) Skipped
QRun-IO/ci-policy: ci / java-docker-3 (pull_request) Skipped
QRun-IO/ci-policy: ci / java-docker-3-head (pull_request) Skipped
QRun-IO/ci-policy: ci / java-docker-4 (pull_request) Skipped
QRun-IO/ci-policy: ci / java-frontend-browser-5 (pull_request) Skipped
QRun-IO/ci-policy: ci / java-maven-6 (pull_request) Skipped
QRun-IO/ci-policy: ci / java-maven-6-head (pull_request) Skipped
QRun-IO/ci-policy: ci / java-maven-7 (pull_request) Skipped
QRun-IO/ci-policy: ci / java-maven-7-head (pull_request) Skipped
QRun-IO/ci-policy: ci / node-8 (pull_request) Skipped
QRun-IO/ci-policy: ci / node-9 (pull_request) Skipped
QRun-IO/ci-policy: ci / node-10 (pull_request) Skipped
QRun-IO/ci-policy: ci / node-playwright-11 (pull_request) Skipped
QRun-IO/ci-policy: ci / repository-policy-12 (pull_request) Skipped
QRun-IO/ci-policy: ci / source-config-13 (pull_request) Skipped
QRun-IO/ci-policy: ci / source-config-14 (pull_request) Skipped
QRun-IO/ci-policy: ci / android-0 (pull_request) Skipped
QRun-IO/ci-policy: ci / original-business (pull_request) Skipped
QRun-IO/ci-policy: ci / original-mcp (pull_request) Skipped
QRun-IO/ci-policy: ci / original-voyage (pull_request) Skipped
QRun-IO/ci-policy: ci / original-cli (pull_request) Skipped
QRun-IO/ci-policy: ci / not-enrolled (pull_request) Skipped
QRun-IO/ci-policy: ci / Scoped workflow [workflow 1e25bb5a243dfdcd95d4b9a4f780200ff8c8778a] (pull_request) Successful in 12s
QRun-IO/ci-policy: ci / shared-pipeline (pull_request) Skipped
QRun-IO/ci-policy: native / native-result (pull_request) Successful in 9s
QRun-IO/ci-policy: ci / ci-result (pull_request) Successful in 6s
maven / build (push) Successful in 11m4s
build / maven (push) Successful in 11m4s
Replace the default-active Core snapshot profile with the released Core 4.1.0-RC.22 BOM, pin qbit-redis to its first release candidate, and replace the snapshot-era status text with the current 1.0 status. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2.6 KiB
2.6 KiB
Core dependency: after-rollback callbacks
Collaboration's retained-upload and cleanup paths compensate external object storage only after a transaction's rollback is confirmed. They need two methods on com.kingsrook.qqq.backend.core.actions.QBackendTransaction. These are included in QQQ Core 4.1.0-RC.22, which this module imports through the BOM; Core 4.1.0-RC.21 does not declare them.
Required API (reviewed implementation: b6fb2382, third-party-src/qqq-core)
qqq-backend-core, class QBackendTransaction:
public boolean supportsRollbackCallbacks() // default: false
public void addAfterRollbackCallback(Runnable callback) // throws UnsupportedOperationException unless supportsRollbackCallbacks(); Objects.requireNonNull(callback)
protected void runAfterRollbackCallbacks() // run once, in order, then clear; exceptions (incl. LinkageError) logged and swallowed
Pending rollback callbacks are preserved when a required operation marks the transaction rollback-only, and run only after confirmed JDBC rollback. A failed physical commit clears them because its outcome is uncertain. Successful commit discards them.
qqq-backend-module-rdbms, class RDBMSTransaction:
@Override public boolean supportsRollbackCallbacks() // true
@Override public void addAfterRollbackCallback(Runnable callback) // super.add...; then rolledBackSinceCommit = false
// rollback()/close(): after connection.rollback() succeeds -> rolledBackSinceCommit = true; runAfterRollbackCallbacks()
// close() rolls back (and so runs callbacks) unless a rollback already happened since the last commit / callback registration
Callers in this module
attachments/AttachmentsService.storeUpload: refuses an ambient transaction where!supportsRollbackCallbacks(); registers storage compensation.attachments/AttachmentCleanupQueue.beginUpload: registers the same cleanup on bothaddAfterRollbackCallbackandaddAfterCommitCallback.
Core tests to carry with the change
- Base class:
supportsRollbackCallbacks()is false;addAfterRollbackCallbackthrowsUnsupportedOperationException. - RDBMS: callback runs after
rollback(); does not run aftercommit(); runs when a transaction with a registered callback is closed without commit; a callback registered after an earlier rollback still runs on close; a throwing callback does not stop later callbacks. - Integration (already in this module, needs the core):
attachments/AttachmentTransactionsPostgresTest(needs Docker) incl.interruptedUploadSurvivesLostRollbackCallback.