diff --git a/src/infrastructure/services/drives_consistency_service.rs b/src/infrastructure/services/drives_consistency_service.rs index 1216a8bb..071d61b4 100644 --- a/src/infrastructure/services/drives_consistency_service.rs +++ b/src/infrastructure/services/drives_consistency_service.rs @@ -144,6 +144,12 @@ impl RecoverableJobHandler for DrivesConsistencyCheck { // query. LEFT JOIN via correlated subquery gets us both // sides in one round-trip; the storage_reconcile sweep // uses the same shape. + // Grace window: skip drives created within the last hour. + // A drive being created RIGHT NOW may still have its first + // upload's `used_bytes` counter not-yet-incremented while + // the `files` row is already visible — that would false- + // positive as `stale_used_bytes`. 1h matches the window + // `blobs_consistency` uses; same rationale (writes-in-flight). let rows: Vec<(Uuid, String, i64, i64)> = match sqlx::query_as( r#" SELECT @@ -158,6 +164,7 @@ impl RecoverableJobHandler for DrivesConsistencyCheck { ), 0) AS actual_bytes FROM storage.drives d WHERE ($1::uuid IS NULL OR d.id > $1) + AND d.created_at < NOW() - INTERVAL '1 hour' ORDER BY d.id LIMIT $2 "#, diff --git a/src/infrastructure/services/files_consistency_service.rs b/src/infrastructure/services/files_consistency_service.rs index 94a9bd83..20dc866b 100644 --- a/src/infrastructure/services/files_consistency_service.rs +++ b/src/infrastructure/services/files_consistency_service.rs @@ -278,6 +278,14 @@ impl RecoverableJobHandler for FilesConsistencyCheck { LEFT JOIN storage.blobs b ON b.hash = f.blob_hash LEFT JOIN storage.chunk_manifests m ON m.file_hash = f.blob_hash WHERE ($1::uuid IS NULL OR f.id > $1) + -- Grace: skip files < 1h old. Delta-upload inserts + -- chunks with ref_count=0 BEFORE the commit that + -- inserts the file row + manifest, so the normal + -- path is race-free — but replace/overwrite flows + -- have narrow windows where a mid-transaction scan + -- could see `missing_blob` or `chunk_missing`. + -- Same grace shape as `blobs_consistency`. + AND f.created_at < NOW() - INTERVAL '1 hour' ORDER BY f.id LIMIT $2 "#, diff --git a/src/infrastructure/services/folders_consistency_service.rs b/src/infrastructure/services/folders_consistency_service.rs index 7bc993b4..4a87bafe 100644 --- a/src/infrastructure/services/folders_consistency_service.rs +++ b/src/infrastructure/services/folders_consistency_service.rs @@ -222,6 +222,13 @@ impl RecoverableJobHandler for FoldersConsistencyCheck { FROM storage.folders f LEFT JOIN storage.folders parent ON parent.id = f.parent_id WHERE ($1::uuid IS NULL OR f.id > $1) + -- Grace: skip folders < 1h old. The + -- `trg_folders_cascade_path` trigger runs on the + -- writer's transaction, so a folder created RIGHT + -- NOW could momentarily show a `path_mismatch` + -- window before the cascade lands. Same grace + -- shape as `blobs_consistency`. + AND f.created_at < NOW() - INTERVAL '1 hour' ORDER BY f.id LIMIT $2 "#,