Standalone: delete snapshotted history by default#5555
Open
cloutiertyler wants to merge 1 commit into
Open
Conversation
SpacetimeDB Standalone previously kept the entire commitlog and all snapshots on disk forever, so the data directory grew without bound (see #5542). This adds a retention policy for historical data, i.e. data that is no longer needed to restart the database, and makes deletion the default for standalone. Whenever a new snapshot is taken (and once at startup), a background task now deletes all but the most recent snapshots, along with all commitlog segments whose entire contents precede the oldest retained snapshot. Snapshots above the durable commitlog offset are never counted or deleted, since only durable snapshots can be restored from. The behavior is configurable via a new [retention] section in the standalone config.toml: [retention] policy = "delete" # or "keep" for the previous behavior retain-snapshots = 2 Closes #5542.
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.
Description of Changes
Closes #5542.
SpacetimeDB Standalone previously kept the entire commitlog and all snapshots on disk forever, so the data directory grew without bound. As @gefjon explained on the issue, commitlog segments whose entire contents precede the most recent snapshot are not needed to restart the database, and neither are older snapshots. SpacetimeDB-cloud archives this historical data to cold storage, but standalone had no lifecycle management at all.
This PR adds a retention policy for historical data and makes deletion the default for standalone.
Behavior
A new background task (spawned by
LocalPersistenceProvider, replacing the commitlog compressor when deletion is enabled) runs once at startup and then whenever a new snapshot is created. It:retain-snapshotsmost recent snapshots (default 2) and deletes all older ones, andsnapshot_watching_commitlog_compressor(a segment is named for the first transaction it contains, so the last segment starting at or before the snapshot offset is kept).The commitlog is retained from the oldest retained snapshot onwards, so the database can be restored from any retained snapshot even if the newest one turns out to be unreadable. The initial run at startup means existing deployments reclaim disk space on upgrade without waiting for the next snapshot.
Because snapshots are captured from committed, not necessarily durable, state, and restore only considers snapshots at or below the durable commitlog offset, the pruner ignores snapshots above the durable offset entirely: they neither count towards the retention limit nor are they ever deleted. This mirrors the "decided snapshot" gating that cloud archival applies, and guarantees a restorable snapshot plus its commitlog suffix always survive a crash.
Snapshot deletion renames the directory to
.archived_snapshotbefore removing it (the same mechanism cloud archival uses), so a prune interrupted mid-deletion can never leave a partially deleted directory that looks like a valid snapshot; leftovers are swept on the next run. When deletion is enabled, local snapshot compression is disabled, since compressing snapshots that will be deleted after the next snapshot is wasted work.Configuration
A new
[retention]section in the standaloneconfig.toml, documented in the config template and in the standalone configuration reference docs:Note that this changes default behavior: standalone users who want to preserve the full transaction history must now set
policy = "keep". Cloud is unaffected, as it does not useLocalPersistenceProvideroutside of tests.Implementation notes
spacetimedb-commitlog: newCommitlog::remove_segments, mirroringcompress_segments. It refuses to remove the writable head segment, removes oldest first so a failure partway through cannot leave a gap in the log, and keeps the in-memory segment list consistent.spacetimedb-durability:Local::remove_segmentsdelegating to the commitlog.spacetimedb-engine:RetentionConfig/RetentionPolicynext to the existingDurabilityConfig, plusprune_historyand thesnapshot_watching_history_prunertask inrelational_db.spacetimedb-standalone: config plumbing, config template, and docs.API and ABI breaking changes
None.
StandaloneOptionsgains aretentionfield.Expected complexity level and risk
retain-snapshotsdurable snapshots exist, never touches the segment containing the oldest retained snapshot or anything after it, never touches snapshots above the durable offset, and the head segment cannot be removed at the commitlog layer.Testing
remove_segmentsunit test in the commitlog crate: refuses the writable segment, removes exactly the requested segments, and the log remains traversable afterwards.prune_historytest in the engine crate against a real fs-backedLocaldurability with tiny segments: no-op below the retention threshold, deletes exactly the stale snapshots and segments, cleans up leftover.archived_snapshotdirectories, ignores snapshots above the durable offset, and the remaining commitlog covers the oldest retained snapshot through the latest transaction.[retention]parses, and the default (both an empty config and the shippedconfig.tomltemplate) isdeletewithretain-snapshots = 2.