pjfanning opened a new pull request, #515: URL: https://github.com/apache/pekko-persistence-r2dbc/pull/515
### Motivation Port of the akka-persistence-r2dbc "snapshot as starting point" feature and its follow-ups: - [akka/akka-persistence-r2dbc#410](https://github.com/akka/akka-persistence-r2dbc/pull/410) Snapshots as starting point for eventsBySlices - [akka/akka-persistence-r2dbc#412](https://github.com/akka/akka-persistence-r2dbc/pull/412) Snapshot as starting point for eventsByPersistenceId - [akka/akka-persistence-r2dbc#438](https://github.com/akka/akka-persistence-r2dbc/pull/438) Harden EventsBySliceStartingFromSnapshotSpec - [akka/akka-persistence-r2dbc#464](https://github.com/akka/akka-persistence-r2dbc/pull/464) Envelope source is different for durable state - [akka/akka-persistence-r2dbc#469](https://github.com/akka/akka-persistence-r2dbc/pull/469) Mark snapshot envelopes with snapshot source The code is copied from the akka-persistence-r2dbc 1.2.0 release, which is available under the Apache License, Version 2.0 as of 2026-10-24 (its LICENSE change date). New files copied from Akka (`StartingFromSnapshotStage` and three specs) keep the Lightbend copyright line, with the ASF header added by `sbt headerCreate`. Pekko core 2.0.0-M4 already defines `EventsBySliceStartingFromSnapshotsQuery`, `EventsByPersistenceIdStartingFromSnapshotQuery` and their current variants, but the R2DBC read journal doesn't implement them. ### Modification - **Queries:** `eventsBySlicesStartingFromSnapshots`, `currentEventsBySlicesStartingFromSnapshots`, `eventsByPersistenceIdStartingFromSnapshot` and `currentEventsByPersistenceIdStartingFromSnapshot`, in both the scaladsl and javadsl read journals. - **`SnapshotDao`** implements `BySliceQuery.Dao`, with dialect hooks for Postgres, Yugabyte and MySQL (slice condition, bucket SQL, tag encoding, current timestamp). When enabled, it stores the `db_timestamp` and tags of the corresponding event. - **Config (differs from upstream):** Pekko settings are per plugin, so: - `query.start-from-snapshot.enabled` (default off), plus `query.snapshot-table` and `query.snapshot-payload-column-type`. - `snapshot.start-from-snapshot.enabled` defaults to the query setting; `snapshot.journal-table` and `snapshot.buffer-size` are also new. - The read journal derives its `SnapshotSettings` from the query settings. - The snapshot plugin reads the event's timestamp and tags from the journal table itself, since it has no `QueryDao`. - When disabled, the snapshot plugin never uses the new columns. - **#464 / #469:** rows carry their own `source`, and snapshot envelopes have source `SN` (`EnvelopeOrigin.fromSnapshot`). - **Migration tool (Pekko addition):** when enabled, migrated snapshots get the timestamp and tags of the already-migrated event. Upstream left this to a manual `UPDATE`. - **Schema:** the `db_timestamp` and `tags` columns and `snapshot_slice_idx` are added to all `create_tables_*.sql` scripts. New migration scripts are in `ddl-scripts/migration/` for Postgres (covers BYTEA and JSONB), Yugabyte and MySQL. - **Small fixes on top of upstream:** the snapshot by-slice query also bounds by `toTimestamp` when given, and the primary sub-sink in `StartingFromSnapshotStage` is now named `primary`. - **Docs:** query sections with Java and Scala snippets, a snapshot store note, and a migration guide section with a rolling update procedure. ### Result Projections and other consumers can start from snapshots instead of replaying all events. Existing deployments are unaffected until they enable the setting and migrate the schema. ### Tests - New specs: - `StartingFromSnapshotStageSpec`, `EventsBySliceStartingFromSnapshotSpec`, `EventsByPersistenceIdStartingFromSnapshotSpec`: ported from upstream, plus javadsl and `SN` source tests. - `StartFromSnapshotDisabledSpec`: queries are rejected when the feature is disabled; snapshots save and load in a table with the **old** schema. That test fails with `column "db_timestamp" does not exist` if the new columns are written while disabled. - `MigrationToolSpec`: snapshot timestamp equals the event's. It fails without the tool change. - PostgreSQL (docker): `sbt core/test` 391 succeeded, 0 failed; `sbt migration/test` 8 succeeded. - MySQL (docker): the snapshot-related specs pass (44 succeeded). `DurableStateBySliceSpec` fails locally on `upstream/main` too (it passes in CI), so it's environmental and unrelated. - Yugabyte: not run locally; relying on CI. - Migration scripts: applied to a database with the old schema on PostgreSQL and MySQL; existing snapshots got the event's timestamp and tags, and the index was created. - `sbt core/mimaReportBinaryIssues migration/mimaReportBinaryIssues`: no issues. The changed internals are `private[r2dbc]`; MiMa was confirmed to flag a deliberate public removal. - `sbt docs/Test/compile docs/paradox`; `paradoxValidateInternalLinks` reports only the existing `[[R2dbcReadJournal.loadEnvelope]]` error, which is also on `main`. - scalafmt, `javafmtAll`, `headerCheckAll`, `git diff --check`. - The new `.sql` migration scripts have no license header: sbt doesn't manage `.sql`, and the Postgres create scripts have none either. ### References Refs akka/akka-persistence-r2dbc#410, akka/akka-persistence-r2dbc#412, akka/akka-persistence-r2dbc#438, akka/akka-persistence-r2dbc#464, akka/akka-persistence-r2dbc#469 -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
