Standalone: delete snapshotted history by default in new data directories#5555
Open
cloutiertyler wants to merge 5 commits into
Open
Standalone: delete snapshotted history by default in new data directories#5555cloutiertyler wants to merge 5 commits into
cloutiertyler wants to merge 5 commits into
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.
|
Could i manully trigger stdb to create a new snapshot? |
Deleting history on upgrade would surprise operators of existing deployments, some of whom may rely on the full transaction history. Instead of making deletion the hardcoded default, ship it via the config.toml template: standalone writes the template into every newly created data directory, and the template now sets policy = "delete". A config without a [retention] section, as found in data directories created by earlier versions, behaves as policy = "keep", preserving the previous behavior. The Rust-level default of RetentionPolicy is Keep accordingly.
Move the snapshot cutoff computation, snapshot deletion, and commitlog segment selection into the snapshot and commitlog crates, so that the cloud archiver can share the implementation instead of duplicating it: - SnapshotRepository::nth_latest_snapshot computes the retention cutoff - SnapshotRepository::prune_snapshots_before deletes snapshots strictly before the cutoff, sweeping leftovers of interrupted runs - commitlog::segments_older_than selects the segments whose entire contents precede a transaction offset prune_history and the commitlog compressor now use these helpers.
Contributor
Author
|
@kdletters Not currently, no. There is no CLI command or HTTP endpoint to request a snapshot manually. Snapshots are taken automatically in two situations:
If your goal is more frequent snapshots, for example so that the A manual trigger, e.g. a |
2 tasks
Retention is a property of a database rather than of the server, so the server-wide RetentionConfig should eventually become the default that per-database settings override. Record how that should be wired up and how the options interact, next to the config type.
The server config is a default only: a database setting, when present, always wins, and neither level bounds the other. Include the resolution matrix and the policy-transition semantics.
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. Deletion is the default for newly created data directories, while existing data directories keep their history on upgrade.
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 a deployment that enables deletion reclaims disk space at the next restart 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:The default is applied through the
config.tomltemplate, which standalone writes into every newly created data directory and which setspolicy = "delete". A config without a[retention]section behaves aspolicy = "keep", so data directories created by earlier versions keep their history when the server is upgraded; their operators can opt in by adding the section. The Rust-level default ofRetentionPolicyisKeepaccordingly.Cloud is unaffected, as it does not use
LocalPersistenceProvideroutside of tests.Implementation notes
spacetimedb-snapshot: newSnapshotRepository::nth_latest_snapshot(computes the retention cutoff) andSnapshotRepository::prune_snapshots_before(deletes snapshots strictly before the cutoff, renaming before removal so a partially deleted snapshot is never mistaken for a valid one, and sweeping leftovers of interrupted runs). These are shared with the cloud archiver'sdeletepolicy in the companion private PR, replacing its previously duplicated logic.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. Also a newsegments_older_thanhelper selecting the segments whose entire contents precede a transaction offset, now used by the compressor task, the pruner, and the cloud archiver.spacetimedb-durability:Local::remove_segmentsdelegating to the commitlog.spacetimedb-engine:RetentionConfig/RetentionPolicynext to the existingDurabilityConfig, plusprune_historyand thesnapshot_watching_history_prunertask inrelational_db, built on the helpers above.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; the shippedconfig.tomltemplate enables deletion; a config without the section keeps history.