Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 14 additions & 8 deletions backend/scripts/clear_thumbnail_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,20 +110,26 @@ async def clear_thumbnail_for_resource(resource_id: str) -> bool:
return deleted > 0


async def clear_thumbnails_for_resources(resource_ids: list[str]) -> int:
"""Clear thumbnail caches for all resources within one event loop."""
cleared = 0
for resource_id in resource_ids:
try:
if await clear_thumbnail_for_resource(resource_id):
cleared += 1
except Exception as exc:
logger.error(f"Failed for {resource_id}: {exc}")
raise
return cleared


def main():
if len(sys.argv) < 2:
print("Usage: python scripts/clear_thumbnail_cache.py RESOURCE_ID [RESOURCE_ID ...]")
sys.exit(1)

resource_ids = sys.argv[1:]
cleared = 0
for rid in resource_ids:
try:
if asyncio.run(clear_thumbnail_for_resource(rid)):
cleared += 1
except Exception as e:
logger.error(f"Failed for {rid}: {e}")
raise
cleared = asyncio.run(clear_thumbnails_for_resources(resource_ids))

print(f"Cleared cache for {cleared}/{len(resource_ids)} resource(s)")

Expand Down
49 changes: 49 additions & 0 deletions backend/tests/scripts/test_clear_thumbnail_cache.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import asyncio
from unittest.mock import patch

import pytest

import scripts.clear_thumbnail_cache as clear_thumbnail_cache


@pytest.mark.asyncio
async def test_clear_multiple_resources_uses_one_event_loop():
calls: list[tuple[str, asyncio.AbstractEventLoop]] = []

async def fake_clear(resource_id: str) -> bool:
calls.append((resource_id, asyncio.get_running_loop()))
return resource_id != "unr-missing"

with patch.object(
clear_thumbnail_cache,
"clear_thumbnail_for_resource",
side_effect=fake_clear,
):
cleared = await clear_thumbnail_cache.clear_thumbnails_for_resources(
["unr-one", "unr-missing", "unr-two"]
)

assert cleared == 2
assert [resource_id for resource_id, _loop in calls] == [
"unr-one",
"unr-missing",
"unr-two",
]
assert len({id(loop) for _resource_id, loop in calls}) == 1


def test_main_runs_one_batch_and_prints_summary(capsys):
with (
patch.object(
clear_thumbnail_cache.sys,
"argv",
["clear_thumbnail_cache.py", "unr-one", "unr-two"],
),
patch.object(clear_thumbnail_cache.asyncio, "run", return_value=1) as mock_run,
):
clear_thumbnail_cache.main()

batch_coroutine = mock_run.call_args.args[0]
batch_coroutine.close()
mock_run.assert_called_once()
assert "Cleared cache for 1/2 resource(s)" in capsys.readouterr().out
Loading