soulsync/tests/test_youtube_sync_idempotent_endpoints.py
BoulderBadgeDad 87e5e1fa23 #702: make mirrored-playlist cancel/reset/delete idempotent (un-wedge LB weekly sync)
Root cause (from the reporter's app.log): a ListenBrainz weekly playlist syncs
through the in-memory youtube_playlist_states discovery machine. When that live
state is lost — a Docker restart, or the discovery process ending while the user
waits for the media-server scan — the DB discover-download snapshot survives but
the live state is gone. Every recovery action (Cancel/Reset/Delete) then hit
`key not in states` and returned 404 "YouTube playlist not found" (hence the
confusing "Youtube" on a ListenBrainz playlist), leaving the playlist permanently
wedged with no way to dismiss or re-sync. Works for the maintainer because a
single session with no restart keeps the live state alive.

Fix — these are cleanup ops, so "the thing is already gone" is SUCCESS, not 404:
- cancel_sync core (shared by YouTube + ListenBrainz + Tidal/Deezer/Qobuz/...) →
  missing key returns idempotent success.
- reset_youtube_playlist / delete_youtube_playlist → same.
The playlist becomes recoverable: Cancel/Reset clears the dead state and the user
re-syncs fresh.

Tests: cancel_sync core (missing key = idempotent 200 not 404; present key still
cancels + clears the worker + reverts phase); endpoint-level idempotency for
cancel/reset/delete; updated the old test that locked the 404 wedge. 834 sync/
discovery tests green.
2026-06-11 12:55:55 -07:00

39 lines
1.1 KiB
Python

"""#702: cancel/reset/delete of a mirrored-playlist sync whose in-memory state is
gone (restart/eviction) must return success, not 404 'YouTube playlist not found'
— otherwise the playlist is permanently wedged."""
from __future__ import annotations
import os
import tempfile
import pytest
_TMP = tempfile.mkdtemp(prefix='soulsync-testdb-ytsync-')
os.environ['DATABASE_PATH'] = os.path.join(_TMP, 'y.db')
os.environ['SOULSYNC_TEST_DB_READY'] = '1'
web_server = pytest.importorskip('web_server')
@pytest.fixture
def client():
return web_server.app.test_client()
_GONE = 'state_wiped_by_restart_hash'
def test_cancel_missing_state_is_success(client):
r = client.post(f'/api/youtube/sync/cancel/{_GONE}')
assert r.status_code == 200 and r.get_json().get('success') is True
def test_reset_missing_state_is_success(client):
r = client.post(f'/api/youtube/reset/{_GONE}')
assert r.status_code == 200 and r.get_json().get('success') is True
def test_delete_missing_state_is_success(client):
r = client.delete(f'/api/youtube/delete/{_GONE}')
assert r.status_code == 200 and r.get_json().get('success') is True