mirror of
https://github.com/Horizontal42/Sort_YM.git
synced 2026-11-10 15:42:02 +03:00
Кэш ключевался по track.track_id, пересчитанному из albums[0] вернувшегося Track - а не по исходному id из списка лайков. Для трека, доступного на нескольких альбомах, "основной" альбом в ответе tracks() может отличаться от того, под которым трек лайкнут. Из-за этого 138 треков из ~1984 кэшировались под несовпадающим ключом и тут же вычищались как "больше не лайкнутые" - при том что реально лайкнуты. Теперь кэшируем по исходному id из likes.tracks_ids, сопоставляя по позиции в батче.
74 lines
2.8 KiB
Python
74 lines
2.8 KiB
Python
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}"
|