You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 38e064e
Browse filesBrowse the repository at this point in the historyBrowse files
fix(mysql): pin READ COMMITTED only on MySQL and only where the PTM accepts it (#129)
Addresses review on #139:
- Spring: pin READ COMMITTED only when the store is MysqlOutboxStore. Postgres already
defaults to it, so other stores keep the template verbatim (no extra round trip, no
behaviour change). Skip pinning with a startup WARN for PTMs that reject custom
isolation levels (JtaTransactionManager, JpaTransactionManager without the
Hibernate/EclipseLink JpaDialect); otherwise every tick would throw
InvalidIsolationLevelException.
- Exposed: ExposedTransactionRunner(database) uses READ COMMITTED only on MySQL/MariaDB
dialects; ExposedTransactionRunner(database, level) sets it explicitly.
- MysqlClaimDoesNotBlockPublishersTest drives a real OutboxProcessor tick with a blocking
deliverer instead of calling claimPending directly, so it follows whatever claim query
the processor runs (e.g. after #120). Adds Hibernate-JPA and DefaultJpaDialect cases.
- New OutboxAutoConfigurationIsolationTest, including a JtaTransactionManager case.
- CHANGELOG: behaviour-change note for Exposed overriding defaultIsolationLevel on MySQL.
README: binlog_format=ROW/MIXED requirement and the JTA/JPA fallback.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: README.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -94,7 +94,7 @@ Runnable, self-contained applications live in [okapi-examples](https://github.co
94
94
-**Duplicate delivery is possible.** A crash between a successful delivery and the status update means the message may be sent again after restart. If processing a message more than once would cause unwanted effects, make the consumer idempotent. okapi sends your payload, your configured headers, and an `x-outbox-id` header to deduplicate on — see [Deduplicating on `x-outbox-id`](#deduplicating-on-x-outbox-id).
95
95
-**Best-effort ordering.** Rows are claimed by `created_at`, oldest first. However, parallel delivery and retries mean messages may reach consumers in a different order. Strict delivery ordering is not guaranteed.
96
96
-**Failure classification is the transport's job.** Each deliverer decides what is retriable. HTTP: 5xx, 429, 408 and connection errors are retriable; other responses and TLS errors are permanent. Kafka: broker-side retriable exceptions are retried; authorization and configuration errors are not.
97
-
-**Scheduler transactions run at `READ COMMITTED`.** The autoconfigured Spring `TransactionRunner` and `ExposedTransactionRunner` both use it. On MySQL this matters: at the default `REPEATABLE READ`, the claim's gap locks would block every concurrent `publish()` until delivery finishes. If you supply your own `TransactionRunner`or a `TransactionTemplate` with an explicit isolation level, keep it at `READ COMMITTED` on MySQL.
97
+
-**On MySQL, scheduler transactions run at `READ COMMITTED`.** The autoconfigured Spring `TransactionRunner`(with `MysqlOutboxStore`) and `ExposedTransactionRunner`(on a MySQL/MariaDB dialect) both use it. At MySQL's default `REPEATABLE READ`, the claim's gap locks would block every concurrent `publish()` until delivery finishes. If you supply your own `TransactionRunner`, an `OutboxStore` of your own, or a `TransactionTemplate` with an explicit isolation level, keep it at `READ COMMITTED` on MySQL. With a `JtaTransactionManager`, or a `JpaTransactionManager` without the Hibernate/EclipseLink `JpaDialect`, okapi cannot set it (startup logs a WARN): configure `transaction_isolation = 'READ-COMMITTED'` on the server or in the JDBC URL instead. `READ COMMITTED` requires `binlog_format=ROW` (the default since MySQL 5.7.7) or `MIXED`; with `STATEMENT`, InnoDB rejects the scheduler's writes with `ERROR 1665`.
98
98
-**Retry budget.**`okapi.processor.max-retries` (default 5) counts retries *after* the first attempt — six attempts in total before a row becomes `FAILED`. `FAILED` is terminal. Retriable messages become eligible again on the next processor poll; there is no per-message backoff.
0 commit comments