diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-10-08 01:27:58 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-10-08 01:27:58 +0200 |
| commit | c27e04c88557716bbe8e42b9174ba9b07f90facf (patch) | |
| tree | a1a56edbede2bba9bb0cc99b81b98570b8313915 /packages/meshbay-node/tests | |
| parent | cdd5fd52e981c4c59643e7dee705b6c55acae68e (diff) | |
| download | meshbay-c27e04c88557716bbe8e42b9174ba9b07f90facf.tar.gz | |
perf(node): sample 9 MB with the size above 9 MB, keep known ids0.19
hash_version 3: size + first 4 MB + last 4 MB + 1 MB at the middle,
5.5x faster cold on a USB disk than the 45 MB sample. The cache now
serves a hit under whatever version it holds, so no existing id moves.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-node/tests')
| -rw-r--r-- | packages/meshbay-node/tests/test_index_cache.py | 39 | ||||
| -rw-r--r-- | packages/meshbay-node/tests/test_indexer.py | 51 |
2 files changed, 57 insertions, 33 deletions
diff --git a/packages/meshbay-node/tests/test_index_cache.py b/packages/meshbay-node/tests/test_index_cache.py index 8f0ff25..e4424d2 100644 --- a/packages/meshbay-node/tests/test_index_cache.py +++ b/packages/meshbay-node/tests/test_index_cache.py @@ -127,43 +127,33 @@ async def test_cache_survives_reopen(tmp_path): @pytest.mark.asyncio -async def test_put_v2_then_lookup_hits(cache): +@pytest.mark.parametrize("hv", [1, 2, 3]) +async def test_a_hit_keeps_the_version_it_was_hashed_under(cache, hv): + """An older scheme is served as is: the id is what TMDB matches, + thumbnails and playlists hang on.""" await cache.put("/lib/big.mkv", size=50_000_000, mtime=111.0, - hash="partial_abc", type="video", added_at=42, - hash_version=2) + hash="old_id", type="video", added_at=42, + hash_version=hv) - hit = await cache.lookup("/lib/big.mkv", size=50_000_000, mtime=111.0, - hash_version=2) + hit = await cache.lookup("/lib/big.mkv", size=50_000_000, mtime=111.0) assert hit is not None - assert hit.hash == "partial_abc" - assert hit.hash_version == 2 + assert hit.hash == "old_id" + assert hit.hash_version == hv @pytest.mark.asyncio -async def test_lookup_misses_on_wrong_hash_version(cache): - await cache.put("/lib/big.mkv", size=50_000_000, mtime=111.0, - hash="full_hash", type="video", added_at=42, - hash_version=1) - - assert await cache.lookup("/lib/big.mkv", size=50_000_000, mtime=111.0, - hash_version=2) is None - - -@pytest.mark.asyncio -async def test_put_v2_overwrites_v1_for_same_path(cache): +async def test_a_newer_hash_overwrites_the_older_for_same_path(cache): await cache.put("/lib/big.mkv", size=50_000_000, mtime=111.0, hash="full_hash", type="video", added_at=42, hash_version=1) await cache.put("/lib/big.mkv", size=50_000_000, mtime=111.0, hash="partial_hash", type="video", added_at=42, - hash_version=2) + hash_version=3) - assert await cache.lookup("/lib/big.mkv", size=50_000_000, mtime=111.0, - hash_version=1) is None - hit = await cache.lookup("/lib/big.mkv", size=50_000_000, mtime=111.0, - hash_version=2) + hit = await cache.lookup("/lib/big.mkv", size=50_000_000, mtime=111.0) assert hit is not None assert hit.hash == "partial_hash" + assert hit.hash_version == 3 @pytest.mark.asyncio @@ -191,8 +181,7 @@ async def test_v1_schema_auto_migrates(tmp_path): cache = IndexCache(db_path=db_path) await cache.open() - hit = await cache.lookup("/lib/old.mkv", size=1000, mtime=111.0, - hash_version=1) + hit = await cache.lookup("/lib/old.mkv", size=1000, mtime=111.0) await cache.close() assert hit is not None diff --git a/packages/meshbay-node/tests/test_indexer.py b/packages/meshbay-node/tests/test_indexer.py index c60600f..fda40c8 100644 --- a/packages/meshbay-node/tests/test_indexer.py +++ b/packages/meshbay-node/tests/test_indexer.py @@ -678,7 +678,7 @@ def test_small_file_gets_hash_version_1(tmp_path): assert entry.hash_version == 1 -def test_large_file_gets_hash_version_2(tmp_path): +def test_large_file_gets_hash_version_3(tmp_path): from meshbay_node.indexer.indexer import _PARTIAL_THRESHOLD, _scan_file d = tmp_path / "root" d.mkdir() @@ -688,7 +688,7 @@ def test_large_file_gets_hash_version_2(tmp_path): entry = _scan_file(one_root(d).roots[0], f) assert entry is not None - assert entry.hash_version == 2 + assert entry.hash_version == 3 assert entry.size == size @@ -719,7 +719,7 @@ def test_partial_hash_differs_from_full_hash(tmp_path): full_hash = b3.blake3(content).hexdigest() assert entry.id != full_hash - assert entry.hash_version == 2 + assert entry.hash_version == 3 def test_partial_hash_is_deterministic(tmp_path): @@ -771,16 +771,51 @@ async def test_cache_aware_scan_uses_hash_version(tmp_path, sk_node, gek): by_name = {e.name: e for e in indexer.index.entries} assert by_name["small.mp4"].hash_version == 1 - assert by_name["big.mkv"].hash_version == 2 + assert by_name["big.mkv"].hash_version == 3 hit_small = await cache.lookup( - str(small), small.stat().st_size, small.stat().st_mtime, - hash_version=1) + str(small), small.stat().st_size, small.stat().st_mtime) assert hit_small is not None hit_big = await cache.lookup( - str(big), big.stat().st_size, big.stat().st_mtime, - hash_version=2) + str(big), big.stat().st_size, big.stat().st_mtime) assert hit_big is not None await cache.close() + + +def test_the_size_is_part_of_a_sampled_hash(tmp_path): + """Two preallocated downloads, all zeros, sample the same bytes.""" + from meshbay_node.indexer.indexer import _PARTIAL_THRESHOLD, _scan_file + d = tmp_path / "root" + d.mkdir() + for name, extra in (("a.mkv", 1), ("b.mkv", 2)): + with open(d / name, "wb") as f: + f.truncate(_PARTIAL_THRESHOLD + extra) + + root = one_root(d).roots[0] + assert _scan_file(root, d / "a.mkv").id != _scan_file(root, d / "b.mkv").id + + +@pytest.mark.asyncio +async def test_a_file_hashed_under_an_older_scheme_keeps_its_id(tmp_path, sk_node, gek): + """The id is what TMDB matches, thumbnails and playlists are keyed by.""" + from meshbay_node.indexer.indexer import _PARTIAL_THRESHOLD + d = tmp_path / "root" + d.mkdir() + big = d / "big.mkv" + big.write_bytes(os.urandom(_PARTIAL_THRESHOLD + 1)) + st = big.stat() + + cache = IndexCache(db_path=tmp_path / "cache.db") + await cache.open() + await cache.put(str(big), st.st_size, st.st_mtime, "v2_id", "video", 0, + hash_version=2) + try: + indexer = DirectoryIndexer(roots=one_root(d), group_id="g", + sk_node=sk_node, gek=gek, cache=cache) + await indexer.initial_scan() + [entry] = indexer.index.entries + assert (entry.id, entry.hash_version) == ("v2_id", 2) + finally: + await cache.close() |