a708389d19
Step 1 of docs/plan/derived-blobs.md. Makes "who references this blob hash" an extension point instead of SQL hardcoded in two places (dedup_gc's reap predicate and blobs_consistency's refcount recompute, both naming storage.files and storage.chunk_manifests directly). Adding a blob-owning table without teaching those two risks silent orphaning: GC sees ref_count = 0 and reaps live content. Behaviour is unchanged — this commit only introduces the port and the two sources that reproduce today's SQL. Wiring follows. Two levels, not one. add_reference bumps chunk_manifests.ref_count first and only falls back to storage.blobs.ref_count, so a reference lands on whichever counter its hash names and the two must be recomputed separately. RefLevel is a parameter rather than a property of a source, because storage.files legitimately contributes at both: a manifest-less legacy row references a chunk, a CDC row references a Blob. The NOT EXISTS guard on the chunk-level files term is load-bearing — for a single-chunk file the whole-file hash equals its lone chunk's hash, so without it the row is counted at both levels. SQL fragments rather than a per-hash count. blobs_consistency recomputes with one query per page, the expected count inlined as correlated subqueries; asking each source for a count per hash would turn that into sources x rows round-trips. So sources emit a fragment the registry sums into the existing page query, and count_references exists only for the on-demand path where the candidate set is already filtered to ref_count = 0. Fragments use their own aliases (cnt_f, cnt_m) rather than the sweeps' outer-row aliases (b, m). A fragment reusing `m` would shadow the outer alias in the manifest sweep and silently correlate against itself; there is a test for it. The SQL builders are free functions so the shape can be asserted without constructing a pool — sqlx's connect_lazy still needs a Tokio context, and the fragments are pure string assembly anyway. 9 unit tests. fmt, clippy --all-features --all-targets, build clean. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
35 lines
806 B
Rust
35 lines
806 B
Rust
pub mod auth_ports;
|
|
pub mod authorization_ports;
|
|
pub mod blob_lifecycle;
|
|
pub mod blob_reference_ports;
|
|
pub mod blob_storage_ports;
|
|
pub mod cache_ports;
|
|
pub mod calendar_ports;
|
|
pub mod carddav_ports;
|
|
pub mod chunked_upload_ports;
|
|
pub mod compression_ports;
|
|
pub mod content_index_ports;
|
|
pub mod dedup_ports;
|
|
pub mod email_sender;
|
|
pub mod external_mount_ports;
|
|
pub mod face_ports;
|
|
pub mod favorites_ports;
|
|
pub mod file_lifecycle;
|
|
pub mod file_ports;
|
|
pub mod folder_ports;
|
|
pub mod inbound;
|
|
pub mod music_ports;
|
|
pub mod opaque_ports;
|
|
pub mod outbound;
|
|
pub mod plugin_ports;
|
|
pub mod recent_ports;
|
|
pub mod resource_access_hook;
|
|
pub mod share_ports;
|
|
pub mod storage_ports;
|
|
pub mod thumbnail_ports;
|
|
pub mod transcode_ports;
|
|
pub mod trash_ports;
|
|
pub mod user_lifecycle;
|
|
pub mod video_frame_ports;
|
|
pub mod zip_ports;
|