Repository navigation
Conversation
Motivation: Akka Projection 1.5.0 added H2 support to the R2DBC projections (akka/akka-projection#914, akka/akka-projection#938), and apache/pekko-persistence-r2dbc#517 added the h2 dialect to the persistence plugin. Modification: Add H2R2dbcOffsetStore with MERGE upserts and CURRENT_TIMESTAMP. With the h2 dialect the projection creates the offset store tables of its own settings before the first connection, like the persistence plugins, instead of upstream's connection-level additional-init schema. Database calls run on the connection factory's h2.use-dispatcher. The executor reads close-calls-exceeding from the connection factory config, since the snapshot deprecates the constructor without it. Build against the pekko-persistence-r2dbc snapshot that includes apache/pekko-persistence-r2dbc#517, add test-only H2 dependencies, an H2 CI job and docs. Result: R2DBC projections can store offsets in an H2 database, with the tables created automatically. Tests: - r2dbc-int-test/test with h2 dialect: 124 succeeded, 0 failed - r2dbc-int-test/test with PostgreSQL: 124 succeeded, 0 failed - checkCodeStyle; mimaReportBinaryIssues, +headerCheckAll, docs/paradox: pass References: Refs apache#662
Motivation: main gained R2dbcSession.withSession (apache#664), which creates an R2dbcExecutor with the constructor that the pekko-persistence-r2dbc snapshot deprecates, so the build fails with warnings as errors. The spy offset store from apache#620 has no H2 case. Modification: R2dbcSession.withSession creates its executor with R2dbcProjectionImpl.createR2dbcExecutor, which takes the logger to keep its own logger name. That also runs H2 sessions on h2.use-dispatcher and reads close-calls-exceeding. Add the H2 case to the spy offset store in R2dbcTimestampOffsetProjectionSpec. Result: The branch compiles and passes with the changes from main. Tests: - r2dbc-int-test/test with h2 dialect: 136 succeeded, 0 failed - r2dbc-int-test/test with PostgreSQL: 136 succeeded, 0 failed - Test/compile, checkCodeStyle; mimaReportBinaryIssues, +headerCheckAll, docs/paradox, ++3.3.8 r2dbc-int-test/Test/compile: pass References: Refs apache#662
Motivation: apache/pekko-persistence-r2dbc#534 added the mariadb dialect to the persistence plugin. R2DBC projections fail on it: the dialect has no offset store, and MariaDB doesn't support the `AS excluded` row alias that the MySQL offset store upserts with. Modification: Add MariaDBR2dbcOffsetStore, the MySQL offset store with VALUES(col) upserts, and select it for the mariadb dialect. Instants need no handling in the projection, as the connection factory of the plugin converts them for the MariaDB driver. Build against the pekko-persistence-r2dbc snapshot that includes apache/pekko-persistence-r2dbc#534, add the MariaDB driver as a test dependency, a MariaDB CI job and docs. Result: R2DBC projections can store offsets in MariaDB with the mariadb dialect. Tests: - MariaDBR2dbcOffsetStoreSpec on MariaDB 12.3.3 (America/New_York): 3 passed; 2 of 3 fail with the MySQL upserts - r2dbc-int-test/test with PostgreSQL and H2: 137 passed, 2 canceled (MariaDB only) - r2dbc-int-test/test with MariaDB and MySQL: event sourced specs fail locally under load on Windows, also on MySQL and the H2 branch - checkCodeStyle, mimaReportBinaryIssues, headerCheckAll, docs/paradox, Scala 3.3.8 and 3.9.0 compile: pass References: Refs apache/pekko-persistence-r2dbc#534
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.
Motivation
apache/pekko-persistence-r2dbc#534 added the
mariadbdialect to the persistence plugin. R2DBC projections can't use it yet:R2dbcOffsetStore.fromConfighas no offset store forDialect.MariaDB.VALUES (...) AS excludedrow alias, which MariaDB doesn't support ([1064] ... near 'AS excluded ON DUPLICATE KEY UPDATE ...').Draft until pekko-persistence-r2dbc is released. This builds against
2.0.0-M1+120-5a212bab-SNAPSHOT, which includes apache/pekko-persistence-r2dbc#534 (and ther2dbc-mariadb1.3.2 bump in apache/pekko-persistence-r2dbc#538). It is stacked on #668, which needs the same snapshot handling (theclose-calls-exceedingexecutor change) and addsDialect.H2to the same matches. Until #668 is merged, the diff here includes its commits; the MariaDB change is the last commit.Modification
R2dbcOffsetStore.fromConfigcreates aMariaDBR2dbcOffsetStoreforDialect.MariaDB. It extendsMySQLR2dbcOffsetStoreand only overrides the offset and management upserts. These useON DUPLICATE KEY UPDATE col = VALUES(col), the same approach asMariaDBSnapshotDaoin core: support MariaDB pekko-persistence-r2dbc#534. Everything else is the MySQL store:NOW(6)consumed timestamp,add(),CONCAT(...) NOT IN (...)delete.java.time.Instant. Nothing in the projection handles that:ConnectionFactoryProviderin the plugin wraps the MariaDB connection pool so thatInstantis bound and read as UTCLocalDateTime, with a UTC session. The projection gets its connections from that provider, so the offset store and the statements of anR2dbcSessionare converted the same way.create_tables_mysql.sql), like the persistence plugin.org.mariadb:r2dbc-mariadb:1.3.2(Apache 2.0), the version pekko-persistence-r2dbc is built against,testonly inr2dbc-int-test. Ther2dbcmodule doesn't reference driver classes.docker-files/docker-compose-mariadb.yml(MariaDB 12.3.3, same as the plugin), with the server inAmerica/New_Yorkso that a non-UTC session would show up as wrong timestamps.r2dbc.mdthat links to the plugin's MariaDB docs.reference.conflistsmariadbas a dialect.TestConfiggets amariadbcase.R2dbcProjectionSpec's test repository gets aVALUES()upsert for MariaDB.R2dbcTimestampOffsetProjectionSpec's spy offset store gets a MariaDB case.MariaDBR2dbcOffsetStoreSpec.Result
R2DBC projections can store offsets in MariaDB 10.11 or later with the
mariadbdialect.Tests
MariaDBR2dbcOffsetStoreSpec(MariaDB 12.3.3 inAmerica/New_York, Windows 11, JDK 25): 3 passed.2026-11-01T01:30Z) or don't exist (2027-03-14T02:30Z) in the server zone. The test checks the stored instant withUNIX_TIMESTAMP, which doesn't depend on the session time zone, and then reads the offset back.2026-11-01 01:30as06:30Zbut still reads it back as01:30, so onlyUNIX_TIMESTAMPcatches it. It rejects2027-03-14 02:30(ERROR 1292). Both checked with themariadbCLI against the test image.timezoneoption, andsessionVariables=time_zone=SYSTEMin the URL left the session in UTC.R2dbcBadGrammarException ... near 'AS excluded ...'.sbt r2dbc-int-test/testagainst PostgreSQL: 137 succeeded, 0 failed, 2 canceled.sbt -Dpekko.persistence.r2dbc.dialect=h2 -Dpekko.projection.r2dbc.dialect=h2 r2dbc-int-test/test: 137 succeeded, 0 failed, 2 canceled.sbt -Dpekko.persistence.r2dbc.dialect=mariadb -Dpekko.projection.r2dbc.dialect=mariadb r2dbc-int-test/test(MariaDB 12.3.3), 3 runs: 137 to 138 of 139 succeeded.EventSourcedPubSubSpec,EventSourcedEndToEndSpecand once aR2dbcTimestampOffsetProjectionSpectest.Too many events stored with the same timestamp ..., buffer size [10], from app timestamps on the Windows clock.EventSourcedPubSubSpecfails the same way locally, on this branch and on r2dbc: support H2 database (port akka-projection #914, #938) #668. CI passes it on r2dbc: support H2 database (port akka-projection #914, #938) #668.sbt -Dpekko.persistence.r2dbc.dialect=mysql -Dpekko.projection.r2dbc.dialect=mysql r2dbc-int-test/test(MySQL 9.5.0): 136 succeeded, 1 failed (EventSourcedPubSubSpec, see above), 2 canceled.++3.3.8!and++3.9.0!r2dbc/compile r2dbc-int-test/Test/compile: pass.sbt "checkCodeStyle; mimaReportBinaryIssues",headerCheckAll,Test/headerCheckAll,docs/paradox: pass.sbt headerCreateAlladded the ASF headers.git diff --check: clean.Notes
VALUES()upserts followMariaDBSnapshotDaoanddocker-compose-mariadb.ymlfollows the plugin's file from core: support MariaDB pekko-persistence-r2dbc#534 (same ASF project).mariadbdialect are used together, unlike the plugin'sMariaDBConnections.requireMatchingDialect, which isprivate[r2dbc]in the plugin's package. The projection dialect defaults to the plugin's, and the plugin's DAOs already check the pairing. A projection set tomysqlon the MariaDB driver fails on the first offset save with the syntax error above.+113to+120also brings in core: snapshots as starting points for eventsBySlices and eventsByPersistenceId pekko-persistence-r2dbc#515 (snapshots as starting points foreventsBySlicesandeventsByPersistenceId). The PostgreSQL and H2 suites pass with it.currentVersionto the release, rebase ontomainonce r2dbc: support H2 database (port akka-projection #914, #938) #668 is merged, re-run CI and mark ready.References
Refs apache/pekko-persistence-r2dbc#534, Refs #668