feat(table): remove orphan files and add sys.remove_orphan_files - #968
Open
zhuxiangyi wants to merge 5 commits into
Open
zhuxiangyi wants to merge 5 commits into
zhuxiangyi wants to merge 5 commits into
Conversation
Port Java's ExpireSnapshotsImpl and SnapshotDeletion. Snapshots are chosen with snapshot.num-retained.min/max, snapshot.time-retained (a snapshot expires once its successor is older than the cut-off), consumer protection, and snapshot.expire.limit. Expiring [earliest, end) deletes data files removed by the deltas of (earliest, end] that the closest earlier tag does not read, changelog files, and manifest lists, manifests, index files, statistics and reassign plans that neither end nor a tag in the range references, then the snapshot files and finally moves the EARLIEST hint. Read failures only ever make a run delete less. Expose it as Table::new_expire_snapshots() and the DataFusion procedure sys.expire_snapshots with Java's arguments.
6 tasks
…ation Extend the file-set invariant to changelog files and index files kept in bucket directories, and add cases for deletion-vector files in both index layouts, changelog and hash index files of a primary-key table, external data files, unreadable deltas, tags and skipping sets (each must delete less, never more), the closest earlier tag among several, a snapshot missing from the range, the slowest of several consumers, and older_than given as a timestamp string.
Port Java's LocalOrphanFilesClean. Files older than older_than (one day ago by default, and never in the future) in the manifest, index and statistics directories, bucket directories and data file external paths are deleted when no snapshot, tag or long-lived changelog of any branch references them; non-snapshot files in snapshot and changelog directories are removed as well. A branch without a schema aborts the run, and unlike Java a missing metadata file of a live snapshot aborts it too instead of exposing that snapshot's files to deletion. Expose it as Table::new_remove_orphan_files() and the DataFusion procedure sys.remove_orphan_files with Java's arguments and result columns (local mode, one table per call).
…in orphan cleanup Check that deletion vectors in bucket directories and global index files that snapshots reference are kept while planted orphans next to them go, that data file external paths are scanned and their referenced files kept, that two levels of partition directories are walked, that temporary changelog files are removed while hint files stay, and that a vanished snapshot is skipped while a live snapshot or a tag with a missing manifest aborts the run.
zhuxiangyi
force-pushed
the
feat/remove-orphan-files
branch
from
September 26, 2026 13:11
545f312 to
dd20d38
Compare
Windows CI hands out 8.3 short temporary paths, from which opendal's local lister cannot strip its canonical root, so listing a temporary table directory panics there. Skip these local file system tests on Windows, like the repository's other local-listing tests.
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.
Purpose
Linked issue: #964 (part 4 of 4)
Failed or interrupted writes leave files that no snapshot references, and nothing in paimon-rust
removes them. This PR ports Java's
LocalOrphanFilesCleanand addsCALL sys.remove_orphan_files.Brief change log
Table::new_remove_orphan_files()/RemoveOrphanFiles(table/orphan_files_clean.rs):Candidates: files last modified before
older_thanin these places:manifest,indexandstatisticsdirectories;partition_keyslevels ofkey=valuedirectories, asJava's
listFileDirsdoes;data-file.external-paths.Non-snapshot files in each branch's
snapshotandchangelogdirectories (temporary files ofinterrupted commits) are removed too, as in Java's
cleanBranchSnapshotDir.Used files: everything referenced by the snapshots, tags, and long-lived changelogs
(
changelog/changelog-*, the snapshot JSON format) of every branch:Files are matched by name, as in Java.
Safety:
older_thandefaults to one day ago and must be in the past;*.managed.blob) are skipped (Java);Unlike Java, which reads a missing manifest as empty, a missing metadata file of a snapshot or
changelog that still exists aborts the run. Otherwise that snapshot's data files would look
unreferenced and be deleted. If the owning snapshot vanished at the same time (concurrent
expiration), it is simply skipped.
dry_runreports without deleting;parallelismbounds concurrent reads and deletions.CALL sys.remove_orphan_files(table, older_than, dry_run, parallelism, mode)returnsdeletedFileCountanddeletedFileTotalLenInBytes, like Java. It supportsmode => 'local'andone table per call;
db.*returns a clear "not supported yet" error."check empty, then delete" races with writers.
Tests
table::orphan_files_clean::tests(13 tests) run on a real local file system, because they needmodification times. Like the repository's other local-listing tests, they are skipped on Windows,
where CI's 8.3 short temporary paths make opendal's local lister panic:
snapshot file) are found by a dry run, then removed. Afterwards the directory holds exactly
the referenced files, the table reads correctly, and a second run finds nothing;
older_thanis rejected;data file is still named by the next delta's DELETE entry, as in Java;
removed, its files become orphans;
kept, while orphans planted next to them are removed;
data-file.external-pathsdirectories are scanned, keeping referenced files and removingorphans;
manifest aborts the run.
as used, not scanning external paths, and walking only one partition level.
tests/procedures.rs:with
parallelismandmode => 'local'removes it and the table stays readable;db.*,mode => 'distributed', a futureolder_than, a baddry_run,and
parallelism => 0.cargo test -p paimon --all-targets --features fulltext,vortexpasses (3835 tests), and so doesclippy with
-D warnings.API and Format
New public API:
Table::new_remove_orphan_files(),RemoveOrphanFiles,OrphanFilesCleanResult;new
sys.remove_orphan_filesprocedure. No format change.Documentation
docs/src/sql.mddocumentsremove_orphan_files: its arguments, what counts as an orphan, andthe safety rules.