Fix snapshot promotion and add temporary snapshot cleanup

Preserve the last good shared snapshot until a replacement is fully staged, and proactively remove stale snapshot_temp_* directories left behind by interrupted snapshot attempts. This prevents orphaned temp snapshots from accumulating while avoiding false cleanup errors after successful promotion.

Changelog-Fixed: Fixed issue where temporary files would not get cleaned up
Closes: https://github.com/damus-io/damus/issues/3684
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit is contained in:
Daniel D’Aquino
2026-03-16 03:03:56 -07:00
parent 0a801b01cb
commit 2ea9cdd416
2 changed files with 110 additions and 18 deletions
@@ -579,6 +579,39 @@ class DatabaseSnapshotManagerTests: XCTestCase {
let snapshottedNoteIds = await snapshotTask.value
XCTAssertEqual(expectedNoteIds, snapshottedNoteIds, "Snapshot should contain both profile notes")
}
func testPerformSnapshot_RemovesStaleTemporarySnapshotDirectories() async throws {
let fileManager = FileManager.default
let staleTempSnapshotURL = fileManager.temporaryDirectory
.appendingPathComponent("snapshot_temp_\(UUID().uuidString)", conformingTo: .directory)
try fileManager.createDirectory(at: staleTempSnapshotURL, withIntermediateDirectories: true)
try fileManager.setAttributes(
[.modificationDate: Date().addingTimeInterval(-(60 * 60 * 25))],
ofItemAtPath: staleTempSnapshotURL.path
)
XCTAssertTrue(fileManager.fileExists(atPath: staleTempSnapshotURL.path))
try await manager.performSnapshot()
XCTAssertFalse(fileManager.fileExists(atPath: staleTempSnapshotURL.path), "Stale temporary snapshot directory should be cleaned up before snapshotting")
}
func testPerformSnapshot_KeepsRecentTemporarySnapshotDirectories() async throws {
let fileManager = FileManager.default
let recentTempSnapshotURL = fileManager.temporaryDirectory
.appendingPathComponent("snapshot_temp_\(UUID().uuidString)", conformingTo: .directory)
try fileManager.createDirectory(at: recentTempSnapshotURL, withIntermediateDirectories: true)
defer {
try? fileManager.removeItem(at: recentTempSnapshotURL)
}
try await manager.performSnapshot()
XCTAssertTrue(fileManager.fileExists(atPath: recentTempSnapshotURL.path), "Recent temporary snapshot directory should not be cleaned up")
}
}