Skip to content

[Epic A] (#962) Per-key migration timestamp and the stale-blob sweep #965

Closed

Description

@diffwireauto

Epic A of #962. Plan of record: docs/initiatives/standalone/962-stale-blob-reclamation/PLAN.md.

Builds the engine: a per-key migration timestamp and the sweep that uses it. No UI.

Tasks

Task Pts
A1 · Reproduce the diagnosis as failing tests: a key migrated long ago still has its blob; the marker carries no timestamp; DELETE without VACUUM leaves the file size unchanged. Red before anything is built. 3
A2 · Per-key timestamps: a __msgrows_migrated_at blob mapping key to epoch ms, written when a key is marked. Pre-existing migrated keys are stamped on first sight, not treated as eligible, so no blob is deleted the moment a user updates. 3
A3 · The sweep: for each migrated message-history key older than the 30-day constant, re-run the superset check and delete the blob only on a pass. Restricted to channel_messages_* and messages_*. Wired to run once per launch, after startup settles, never mid-session. 4
A4 · One VACUUM, only if the sweep deleted something, with the reclaimed byte count logged. 3
A5 · Epic verification: the named command, plus the sweep run against a copy of a real database. 1

Decisions this implements

30-day window; sweep once per launch; timestamps in a separate __msgrows_migrated_at blob so the hot __msgrows_migrated path is untouched. Owner, 2026-10-22.

Can't-tell branches, all stopping

Where Can't tell what Does
A key's re-verify finds a blob record with no row whether rows hold this key's history stop — keep the blob, log which records are missing, never retry in a loop
The blob will not decode during re-verify what the blob contains stop — keep it, log it
A migrated key has no timestamp when it migrated stop deleting — stamp it now, let it age 30 days
The key is not channel_messages_* or messages_* whether a row equivalent exists stop — never considered
VACUUM fails whether the file can be compacted proceeds, logging it. Not fail-open on data: the deletes already happened and were each verified; VACUUM affects file size only.

Acceptance

  • A key stamped older than 30 days whose rows hold every blob record loses its blob, and the file shrinks after VACUUM.
  • A key stamped older than 30 days with one blob record missing from rows keeps its blob and names the missing records. This gate must be proved able to fail.
  • A key stamped inside 30 days keeps its blob, tested at 29 days so the boundary is covered.
  • A migrated key with no timestamp is stamped, not deleted.
  • contacts, discovered_contacts and path_history_ keys are never considered, asserted by name.
  • An unmigrated history key keeps its blob.
  • Every kept blob is byte-identical after VACUUM, compared by hash, with the unmigrated history keys asserted present by name and the row count unchanged.

Named command: flutter test test/storage/ plus flutter analyze.

Agent Mail: TealGlen

Activity

  1. added a commit that references this issue on Oct 23, 2026
  2. added 3 commits that reference this issue on Oct 24, 2026
  3. diffwireauto commented on Oct 24, 2026

    @diffwireauto
    MemberAuthor

    Merged to dev via #973 (dev head 5b061924), CI 10/10 green. Content verified on dev by git cat-file and by grep for the substantive symbols, not by merge state.

    Owner-validated on Windows 2026-10-23, read back from the live database independently of what the UI reported:

    before after
    file bytes 74,350,592 57,057,280 (-16.5 MiB)
    migration timestamps 0 47
    audit entries 0 1, naming all 40 cleared keys
    cleared keys still holding a blob 0
    unmigrated history blobs lost 0 of 98
    cleared keys left with zero rows 0

    He confirmed the channels read normally afterwards.

    Agent Mail: TealGlen

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions