feat(recoverable-job): check if old blob (no cdc) still remains: notice only
This commit is contained in:
@@ -374,10 +374,7 @@ impl RecoverableJobHandler for BlobsConsistencyCheck {
|
||||
let last_hash = rows.last().map(|r| r.hash.clone()).expect("non-empty rows");
|
||||
cursor = Some(last_hash.clone());
|
||||
let batch_len = rows.len() as u64;
|
||||
if let Err(e) = store
|
||||
.checkpoint(last_hash.into_bytes(), batch_len)
|
||||
.await
|
||||
{
|
||||
if let Err(e) = store.checkpoint(last_hash.into_bytes(), batch_len).await {
|
||||
return RunOutcome::Failed {
|
||||
message: format!("checkpoint: {e}"),
|
||||
};
|
||||
|
||||
@@ -150,19 +150,27 @@ impl RecoverableJobHandler for DrivesConsistencyCheck {
|
||||
// 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).
|
||||
// NOTE: `storage.drives` has no `name` column. The drive's
|
||||
// display name lives on its root folder (see the schema
|
||||
// comment on `drives.root_folder_id` — "The display name
|
||||
// lives here"). LEFT JOIN storage.folders ON id =
|
||||
// drive.root_folder_id and read `folders.name` as the
|
||||
// drive's human identifier. `COALESCE` handles the
|
||||
// (bug-only) case where root_folder_id is NULL.
|
||||
let rows: Vec<(Uuid, String, i64, i64)> = match sqlx::query_as(
|
||||
r#"
|
||||
SELECT
|
||||
d.id,
|
||||
d.name,
|
||||
d.used_bytes,
|
||||
d.id AS id,
|
||||
COALESCE(rf.name, '?') AS name,
|
||||
d.used_bytes AS used_bytes,
|
||||
COALESCE((
|
||||
SELECT SUM(size)::bigint
|
||||
FROM storage.files
|
||||
WHERE drive_id = d.id
|
||||
AND NOT is_trashed
|
||||
), 0) AS actual_bytes
|
||||
), 0) AS actual_bytes
|
||||
FROM storage.drives d
|
||||
LEFT JOIN storage.folders rf ON rf.id = d.root_folder_id
|
||||
WHERE ($1::uuid IS NULL OR d.id > $1)
|
||||
AND d.created_at < NOW() - INTERVAL '1 hour'
|
||||
ORDER BY d.id
|
||||
|
||||
@@ -435,6 +435,36 @@ impl RecoverableJobHandler for FilesConsistencyCheck {
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
// (4) legacy_uncdc_file: informational — this file
|
||||
// is served via the pre-CDC whole-file blob fallback,
|
||||
// not the modern chunk-manifest path. Not broken;
|
||||
// just misses out on sub-file dedup benefits + never
|
||||
// shares chunks with newer uploads. Severity
|
||||
// `anomaly` (surprising state, no known impact) so
|
||||
// the UI renders it as a notice, not a warning.
|
||||
// Fires when the blob registry has a whole-file row
|
||||
// for this hash but there is no manifest. Recovery
|
||||
// path: `ReingestLegacy` (deferred, see
|
||||
// `docs/plan/recovery.md`).
|
||||
if row.blob_size.is_some() && row.manifest_size.is_none() {
|
||||
finding_count += 1;
|
||||
record_or_log(
|
||||
store,
|
||||
FILES_CONSISTENCY_JOB_NAME,
|
||||
"legacy_uncdc_file",
|
||||
"anomaly",
|
||||
Some(row.id),
|
||||
serde_json::json!({
|
||||
"name": row.name,
|
||||
"path": path,
|
||||
"blob_hash": row.blob_hash,
|
||||
"size": row.size,
|
||||
"note": "pre-CDC whole-file blob; re-ingest for sub-file dedup",
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
||||
// Advance cursor + checkpoint. `batch_len` feeds
|
||||
|
||||
Reference in New Issue
Block a user