summaryrefslogtreecommitdiffstats
path: root/packages/meshbay-node/tests/test_poster_cache.py
blob: 908fb6974540bc4f5b9e675cc2427758d54dc07e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
"""
Bug found live, 2026-08-24: `_fetch_and_cache_poster` downloaded a TMDB
poster/backdrop from `image.tmdb.org` on *every* `media_meta_req`, even for
a file whose TMDB match was already cached — the content-addressed
`thumb_hash` isn't known until the bytes are downloaded, so nothing had
ever checked "have I already fetched this poster_path" first. On a group
with a show split across release folders (§V6), one Videos-tab visit
triggered four to six redundant image downloads; compounded with TMDB
latency (or a stall), this is what an operator saw as posters that "never
finish loading" on a second visit.

Fixed by keying the `thumbs` cache by a synthetic `tmdb:{poster_path}` id
*before* the network call, mirroring the `file_id` convention `_do_file_request`
already uses to resolve a thumbnail by id.
"""

import pytest
from meshbay_node.media_cache import MediaCache
from meshbay_node.transport.webrtc_server import WebRTCPeerSession

pytestmark = pytest.mark.asyncio


@pytest.fixture
async def media_cache(tmp_path):
    c = MediaCache(db_path=tmp_path / "media_cache.db")
    await c.open()
    yield c
    await c.close()


class FakeTmdbClient:
    def __init__(self):
        self.fetch_calls = 0

    @staticmethod
    def poster_url(path):
        return f"https://image.tmdb.org/t/p/w500{path}"

    async def fetch_image(self, url):
        self.fetch_calls += 1
        return b"jpeg-bytes-for-" + url.encode()


async def test_second_fetch_for_the_same_poster_path_skips_the_network(media_cache):
    client = FakeTmdbClient()

    first = await WebRTCPeerSession._fetch_and_cache_poster(
        media_cache, client, "/poster.jpg")
    second = await WebRTCPeerSession._fetch_and_cache_poster(
        media_cache, client, "/poster.jpg")

    assert first == second, "the same poster_path must yield the same thumb_hash"
    assert client.fetch_calls == 1, (
        "a poster already cached must never be re-downloaded from TMDB")


async def test_different_poster_paths_are_each_fetched_once(media_cache):
    client = FakeTmdbClient()

    poster_hash = await WebRTCPeerSession._fetch_and_cache_poster(
        media_cache, client, "/poster.jpg")
    backdrop_hash = await WebRTCPeerSession._fetch_and_cache_poster(
        media_cache, client, "/backdrop.jpg")
    poster_hash_again = await WebRTCPeerSession._fetch_and_cache_poster(
        media_cache, client, "/poster.jpg")

    assert poster_hash != backdrop_hash
    assert poster_hash == poster_hash_again
    assert client.fetch_calls == 2, "one network fetch per distinct poster_path"


async def test_none_path_is_a_no_op(media_cache):
    client = FakeTmdbClient()
    result = await WebRTCPeerSession._fetch_and_cache_poster(media_cache, client, None)
    assert result is None
    assert client.fetch_calls == 0


async def test_cached_hash_actually_serves_the_downloaded_bytes(media_cache):
    client = FakeTmdbClient()
    thumb_hash = await WebRTCPeerSession._fetch_and_cache_poster(
        media_cache, client, "/poster.jpg")
    await WebRTCPeerSession._fetch_and_cache_poster(media_cache, client, "/poster.jpg")

    stored = await media_cache.get_thumb(thumb_hash)
    assert stored == b"jpeg-bytes-for-https://image.tmdb.org/t/p/w500/poster.jpg"