fix: every first watch state survives a write beside it, and a folded Watch later keeps its pin

A season marked watched, a pull from Plex and a YouTube resume point made their first row by a read
then an add, and failed on the unique key when a first checkpoint or the watched mark made it in
between. They go through the same insert-then-read as the checkpoint (the resume point is one
upsert); a pull that meets a local change still waiting for its push leaves it.

Folding duplicate Watch later lists moved their videos but not a Home pin, which the cascade then
deleted; the first pin of a dropped copy moves onto the kept list.

Marking one notice read trimmed before its own flag was flushed, so the trim left one past the cap.
The route test now crosses the cap and reads the result from a session of its own.
This commit is contained in:
2026-10-20 01:56:30 +02:00
parent b04b2cbd62
commit c5f121139b
10 changed files with 199 additions and 68 deletions
@@ -7,7 +7,9 @@ Create Date: 2026-10-20
Watch later was made on a user's first save by a read then an insert, so two first saves at once
each made a list, and the reader then picked between them at random. A partial unique index holds
"one per user" now. An instance that already has a second list keeps the oldest: the others' videos
move into it (after its own, in their order; one it already holds is not added twice), then they go.
move into it (after its own, in their order; one it already holds is not added twice), a Home pin
of one of them moves to it (unless it is pinned itself; of several, the first on the shelf), then
they go — a pin left on them goes with them, as the kept list already holds one.
"""
import sqlalchemy as sa
@@ -41,6 +43,19 @@ def upgrade() -> None:
ON CONFLICT ON CONSTRAINT uq_playlist_video DO NOTHING
"""
)
op.execute(
f"""
UPDATE comfort_pins c SET playlist_id = m.keep_id
FROM (
SELECT DISTINCT ON (e.keep_id) p.id AS pin_id, e.keep_id
FROM comfort_pins p
JOIN ({_EXTRA}) e ON e.id = p.playlist_id
WHERE NOT EXISTS (SELECT 1 FROM comfort_pins k WHERE k.playlist_id = e.keep_id)
ORDER BY e.keep_id, p.position, p.id
) m
WHERE c.id = m.pin_id
"""
)
op.execute(f"DELETE FROM playlists WHERE id IN (SELECT id FROM ({_EXTRA}) e)")
op.create_index(
"uq_playlist_watch_later",