Sort_YM/tests/test_fetch.py
Andrew Pimenov b93ac0d04a fix fetch caching tracks under wrong key, causing false stale purge
Кэш ключевался по track.track_id, пересчитанному из albums[0] вернувшегося
Track - а не по исходному id из списка лайков. Для трека, доступного на
нескольких альбомах, "основной" альбом в ответе tracks() может отличаться
от того, под которым трек лайкнут. Из-за этого 138 треков из ~1984
кэшировались под несовпадающим ключом и тут же вычищались как "больше не
лайкнутые" - при том что реально лайкнуты. Теперь кэшируем по исходному
id из likes.tracks_ids, сопоставляя по позиции в батче.
2026-07-06 12:16:14 +03:00

74 lines
2.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from pathlib import Path
from sort_ym import fetch
class FakeArtist:
def __init__(self, name):
self.name = name
class FakeAlbum:
def __init__(self, id_, genre=None):
self.id = id_
self.genre = genre
class FakeTrack:
def __init__(self, id_, albums, title="Title", artists=None, lyrics_available=False):
self.id = id_
self.albums = albums
self.title = title
self.artists = artists or [FakeArtist("Artist")]
self.lyrics_available = lyrics_available
class FakeLikes:
def __init__(self, tracks_ids):
self.tracks_ids = tracks_ids
class FakeClient:
"""Симулирует трек, у которого "основной" альбом в ответе tracks()
отличается от альбома, под которым трек значится в списке лайков -
это реальное поведение API Яндекса для треков на нескольких альбомах."""
def __init__(self, likes_ids, tracks_by_batch):
self._likes_ids = likes_ids
self._tracks_by_batch = tracks_by_batch
def users_likes_tracks(self):
return FakeLikes(self._likes_ids)
def tracks(self, batch):
return self._tracks_by_batch[tuple(batch)]
def test_fetch_caches_under_original_liked_id_not_recomputed_track_id(tmp_path: Path):
# Трек лайкнут как "100:10", но Track.albums[0].id из ответа API - 999 (другой альбом).
track = FakeTrack(id_=100, albums=[FakeAlbum(999, genre="pop")])
client = FakeClient(
likes_ids=["100:10"],
tracks_by_batch={("100:10",): [track]},
)
cache = fetch.fetch_liked_tracks(client, tmp_path, batch_size=100, batch_delay=0)
assert "100:10" in cache, "трек должен кэшироваться под id из списка лайков"
assert "100:999" not in cache, "не должен пересчитывать ключ из albums[0] вернувшегося Track"
assert cache["100:10"]["id"] == 100
assert cache["100:10"]["genre_raw"] == "pop"
def test_fetch_does_not_purge_track_with_mismatched_album_as_stale(tmp_path: Path):
# Регрессия: раньше такой трек кэшировался под "неправильным" ключом track.track_id,
# который не совпадал с likes.tracks_ids, и тут же удалялся как "больше не лайкнутый".
track = FakeTrack(id_=100, albums=[FakeAlbum(999)])
client = FakeClient(
likes_ids=["100:10"],
tracks_by_batch={("100:10",): [track]},
)
cache = fetch.fetch_liked_tracks(client, tmp_path, batch_size=100, batch_delay=0)
assert len(cache) == 1, f"трек не должен быть вычищен как stale сразу после загрузки: {cache}"