Expand description
Attachments table operations.
Attachments are normalized into one row per attachment (see migration 74), keyed to their event
(ON DELETE CASCADE) and indexed by content hash. This module is the single source of truth for
attachment persistence; the legacy ["attachments", …] tag in events.tags is left in place on
pre-migration events as an untouched safety net but is never read.
Structs§
- Reusable
Upload - A prior upload of this exact plaintext, reusable by reference: the blob is
already on a Blossom server and
key/noncedecrypt it.
Functions§
- backfill_
downloaded_ by_ hash - Mark every OTHER attachment sharing this content hash as downloaded to the same path — the
download-sharing dedup, now an indexed
WHERE hash = ?instead of aLIKE '%hash%'table scan. Returns the affected event ids so the caller can reconcile in-memory STATE. - clear_
attachment_ download - Mark an attachment not-downloaded (its file went missing). Clears the path.
- downloaded_
attachment_ paths - A downloaded attachment’s on-disk path, for the integrity sweep. Returns (event_id, hash, path)
for every attachment claiming
downloaded=1with a non-empty path — an indexed read, no per-event JSON parse. - downloaded_
paths_ by_ hash - Paths where these bytes already landed: every
downloaded=1row for the hash, wherever the file was saved (collision suffixes included — the name on the message says nothing about the name on disk). Rows are CLAIMS: the caller must hash-verify a path before treating it as the content. - events_
with_ attachment_ hash - The message carrying an attachment with this content hash, newest first.
- find_
by_ webxdc_ topic_ in - The Mini App message carrying
topicin one chat:(event id, attachment). Scoped to the chat because a topic is only a session id there; anyone can paste the same topic onto an app sent from elsewhere. - find_
reusable_ by_ hash - get_
attachments_ for_ event - Attachments for a single event, ordered by
att_index. - get_
attachments_ for_ events - Attachments for a set of events,
event_id → Vec<Attachment>ordered byatt_index. Batched (oneIN (…)query) for a message window, mirroring the reactions/edits loaders. - hash_
referenced_ elsewhere - Whether any OTHER event’s attachment shares this plaintext hash — the local file half of the same refcount: the decrypted file on disk serves every message that names its hash, windowed out of memory or not.
- insert_
attachment_ rows - Upsert a message’s attachment rows onto the given connection or transaction, so
save_messagecan commit them ATOMICALLY with the event row (an event + no attachments would render as a broken file message with no fallback). Upserts on(event_id, att_index). The mutable local state is handled so a re-save never regresses a completed download:downloadedis MONOTONIC (MAX(existing, incoming)), andhash/pathonly take the incoming values when the incoming carries a completed download (downloaded=1) — the nonce→content-hash rewrite the download path performs. So a relay re-delivery (downloaded=0) preserves the downloaded file, its content-hash key, and its path; a completed download persists all three in one pass. Explicit un-download goes throughclear_attachment_download, never here. - rewrite_
downloaded_ paths - Repoint downloaded-file paths from old download directories to a new one (Android download-dir
migration). For each downloaded attachment whose path starts with an old prefix: move it to
new_dir/<filename>if that exists, else mark it not-downloaded. Returns the affected event ids. - set_
attachment_ downloaded - Flip one attachment’s downloaded state — a single-row UPDATE keyed by (event_id, content hash), replacing the old read-modify-write of the whole tags blob.
- urls_
unreferenced_ elsewhere - Of
urls, the ones NO other event’s attachment still points at — the only ones a delete may scrub from Blossom. One blob can back many messages (smart-forward), and the shared copy must outlive every send but the last. DB-backed on purpose: the in-memory STATE windows to recent messages, so a reference in an older message is invisible there. - verify_
local_ copy - The smart-forward ledger read: has this exact plaintext (by SHA-256) ever crossed this account with a decryptable blob behind it?
- verify_
message_ attachments - Run
verify_local_copyover a message’s undownloaded attachments, converting verified claims in place. No-op for messages whose files are unknown (indexed probe misses) or already resident.