Only one retention cycle in progress at a time#2797
Merged
pjfanning merged 3 commits intoapache:mainfrom Apr 4, 2026
Merged
Conversation
a6ef064 to
9519350
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
This PR updates the typed persistence retention flow to avoid overlapping retention cycles (snapshot/event deletion), which could otherwise interfere with each other.
Changes:
- Track retention-cycle progress in
BehaviorSetupand add a guard inRunningto avoid starting a new retention cycle while a previous one is still in progress. - Simplify snapshot deletion to delete snapshots up to a max sequence number (dropping the previous lower-bound window logic).
- Update retention-related tests to match the adjusted deletion criteria and retention behavior.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/internal/Running.scala | Adds the “only one retention at a time” guard and wires retention progress tracking into snapshot/event/snapshot deletion flow. |
| persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/internal/BehaviorSetup.scala | Introduces retentionInProgress state and helper methods to track retention lifecycle across async steps. |
| persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/internal/ExternalInteractions.scala | Changes snapshot deletion to always use minSequenceNr = 0L and updates logging/signature accordingly. |
| persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/internal/RetentionCriteriaImpl.scala | Removes now-unused deleteLowerSequenceNr logic from internal retention criteria implementation. |
| persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/internal/EventSourcedBehaviorImpl.scala | Updates BehaviorSetup construction to pass the new retentionInProgress parameter. |
| persistence-typed/src/test/scala/org/apache/pekko/persistence/typed/internal/RetentionCriteriaSpec.scala | Adjusts expectations to match removal of lower-bound deletion logic. |
| persistence-typed-tests/src/test/scala/org/apache/pekko/persistence/typed/scaladsl/EventSourcedBehaviorWatchSpec.scala | Updates test BehaviorSetup construction for the new parameter. |
| persistence-typed-tests/src/test/scala/org/apache/pekko/persistence/typed/scaladsl/EventSourcedBehaviorRetentionSpec.scala | Updates assertions to match snapshot deletion criteria changes (min sequence no longer asserted). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
...typed/src/test/scala/org/apache/pekko/persistence/typed/internal/RetentionCriteriaSpec.scala
Outdated
Show resolved
Hide resolved
persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/internal/Running.scala
Show resolved
Hide resolved
persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/internal/Running.scala
Outdated
Show resolved
Hide resolved
...-typed/src/main/scala/org/apache/pekko/persistence/typed/internal/ExternalInteractions.scala
Show resolved
Hide resolved
8cac580 to
bd445ef
Compare
pjfanning
approved these changes
Mar 29, 2026
Philippus
approved these changes
Mar 30, 2026
Member
|
compilation issues |
Track retention lifecycle steps with mutable retentionInProgress state in BehaviorSetup. Key changes: - Add retentionInProgress flag and 6 progress tracking methods with detailed debug logging to BehaviorSetup. - Skip new retention cycle when previous one has not completed yet, logging at INFO level. Next retention will cover skipped retention. - Simplify internalDeleteSnapshots to always use minSequenceNr=0, preventing leftover snapshots when retention is skipped. - Remove now-unnecessary deleteLowerSequenceNr from SnapshotCountRetentionCriteriaImpl. - Fix upstream logging placeholder mismatch bug in retentionProgressDeleteEventsEnded (2 placeholders, 1 argument). The retention process for SnapshotCountRetentionCriteria: 1. Save snapshot when shouldSnapshotAfterPersist returns SnapshotWithRetention. 2. Delete events (when deleteEventsOnSnapshot=true), in background. 3. Delete snapshots (when isOnlyOneSnapshot=false), in background. Upstream: akka/akka-core@57b750a3dc Cherry-picked from akka/akka-core v2.8.0, which is now Apache licensed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ationale comments - Reformat RetentionCriteriaSpec expected list to multi-line for readability - Change 'Skipping retention' log level from INFO to DEBUG to avoid log noise - Add design rationale comment explaining why snapshot+retention are skipped together (prevents orphaned snapshots that would never be cleaned up) - Add Scaladoc explaining why minSequenceNr=0L is used (simplifies logic, safe for built-in snapshot stores) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
fe8ea15 to
259edc8
Compare
Member
|
compile issue in tests listed above is still there and also this |
…on spec Lines 292 and 298 still used the old two-argument form after the API change to single-argument expectDeleteSnapshotCompleted(Long).
Member
Author
|
@pjfanning Please take a look |
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
Port the upstream "only one retention cycle in progress at a time" guard from akka/akka-core commit
57b750a3dc(which is now Apache licensed) to Pekko's event-sourced persistence.When
SnapshotCountRetentionCriteriais configured, a full retention cycle (snapshot → delete events → delete snapshots) can take significant time. If events are persisted faster than retention completes, overlapping cycles can race against each other, causing non-deterministic ordering of snapshot/event deletions and test flakiness.Modification
Core change —
BehaviorSetup:retentionInProgressflag with lifecycle tracking methods (retentionProgressSaveSnapshotStarted,retentionProgressSaveSnapshotEnded,retentionProgressDeleteEventsStarted,retentionProgressDeleteEventsEnded,retentionProgressDeleteSnapshotsStarted,retentionProgressDeleteSnapshotsEnded)Running.scala:SnapshotWithRetentiontriggers, checksetup.isRetentionInProgress()ExternalInteractions.scala:internalDeleteSnapshots— always delete fromminSequenceNr = 0Linstead of tracking a windowed lower bound. This simplifies the logic and is safe because Pekko's built-in snapshot stores handle range deletions efficiently.fromSequenceNrparameterRetentionCriteriaImpl.scala:deleteLowerSequenceNrmethod (no longer needed)Tests:
EventSourcedBehaviorRetentionSpec— update allexpectDeleteSnapshotCompletedcalls to single-param formRetentionCriteriaSpec— removedeleteLowerSequenceNrassertions, reformat long line to multi-line for readabilityResult
References