56 lines
1.9 KiB
Python
56 lines
1.9 KiB
Python
"""repair thread counters left stale by server-side flag changes and expunges
|
|||
|
|
|
||
|
|
`threads.unread_count`, `pinned` and `message_count` are denormalized from the
|
||
|
|
thread's messages. Two sync paths updated messages without recomputing them: a
|
||
|
|
flag change reported by the server (mail read on a phone, or filed by a
|
||
|
|
server-side rule) and a QRESYNC expunge. The row then disagreed with its own
|
||
|
|
messages — the message list showing a message as unread that the reading pane
|
||
|
|
showed as read, and only a manual "mark as read" reconciling it.
|
||
|
|
|
||
|
|
The code paths are fixed; this repairs rows that already drifted. Recomputes from
|
||
|
|
the messages themselves, so it is safe to run on a healthy database: threads that
|
||
|
|
already agree are left untouched.
|
||
|
|
|
||
|
|
Revision ID: 0018
|
||
|
|
Revises: 0017
|
||
|
|
Create Date: 2026-09-18
|
||
|
|
"""
|
||
|
|
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
from collections.abc import Sequence
|
||
|
|
|
||
|
|
from alembic import op
|
||
|
|
|
||
|
|
revision: str = "0018"
|
||
|
|
down_revision: str | None = "0017"
|
||
|
|
branch_labels: str | Sequence[str] | None = None
|
||
|
|
depends_on: str | Sequence[str] | None = None
|
||
|
|
|
||
|
|
|
||
|
|
def upgrade() -> None:
|
||
|
|
op.execute(
|
||
|
|
r"""
|
||
|
|
UPDATE threads t
|
||
|
|
SET unread_count = s.unread,
|
||
|
|
pinned = s.pinned,
|
||
|
|
message_count = s.total
|
||
|
|
FROM (
|
||
|
|
SELECT thread_id,
|
||
|
|
count(*) AS total,
|
||
|
|
count(*) FILTER (WHERE NOT ('\Seen' = ANY(flags))) AS unread,
|
||
|
|
bool_or('\Flagged' = ANY(flags)) AS pinned
|
||
|
|
FROM messages
|
||
|
|
WHERE thread_id IS NOT NULL
|
||
|
|
GROUP BY thread_id
|
||
|
|
) AS s
|
||
|
|
WHERE t.id = s.thread_id
|
||
|
|
AND (t.unread_count, t.pinned, t.message_count) IS DISTINCT FROM
|
||
|
|
(s.unread, s.pinned, s.total)
|
||
|
|
"""
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
def downgrade() -> None:
|
||
|
|
"""Nothing to undo: this only makes rows agree with the messages they describe."""
|