Add async lock protection to geo service cache and mark Task 16 done
This commit is contained in:
@@ -700,7 +700,7 @@ class TestOriginFilter:
|
||||
assert len(result.bans) == 205
|
||||
assert all(b.country_code == "DE" for b in result.bans)
|
||||
|
||||
geo_service.clear_cache()
|
||||
await geo_service.clear_cache()
|
||||
|
||||
async def test_bans_by_country_source_archive_reads_archive(
|
||||
self, app_db_with_archive: aiosqlite.Connection
|
||||
@@ -769,7 +769,7 @@ class TestBansbyCountryBackground:
|
||||
assert result.total == 3
|
||||
# Country counts should reflect the cached data.
|
||||
assert "DE" in result.countries or "US" in result.countries or "JP" in result.countries
|
||||
geo_service.clear_cache()
|
||||
await geo_service.clear_cache()
|
||||
|
||||
async def test_uncached_ips_trigger_background_task(
|
||||
self, mixed_origin_db_path: str
|
||||
@@ -778,7 +778,7 @@ class TestBansbyCountryBackground:
|
||||
resolution and the response returns without blocking."""
|
||||
from app.services import geo_service
|
||||
|
||||
geo_service.clear_cache() # ensure cache is empty
|
||||
await geo_service.clear_cache() # ensure cache is empty
|
||||
|
||||
with (
|
||||
patch(
|
||||
@@ -810,7 +810,7 @@ class TestBansbyCountryBackground:
|
||||
"""When http_session is None, no background task is created."""
|
||||
from app.services import geo_service
|
||||
|
||||
geo_service.clear_cache()
|
||||
await geo_service.clear_cache()
|
||||
|
||||
with (
|
||||
patch(
|
||||
|
||||
@@ -130,7 +130,7 @@ async def perf_db_path(tmp_path_factory: Any) -> str:
|
||||
ips = await _seed_f2b_db(path, _BAN_COUNT)
|
||||
|
||||
# Pre-populate the in-memory geo cache so no network calls are made.
|
||||
geo_service.clear_cache()
|
||||
await geo_service.clear_cache()
|
||||
country_cycle = _COUNTRIES * (_BAN_COUNT // len(_COUNTRIES) + 1)
|
||||
for i, ip in enumerate(ips):
|
||||
cc, cn = country_cycle[i]
|
||||
|
||||
@@ -45,9 +45,9 @@ def _make_session(response_json: dict[str, object], status: int = 200) -> MagicM
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def clear_geo_cache() -> None:
|
||||
async def clear_geo_cache() -> None:
|
||||
"""Flush the module-level geo cache before every test."""
|
||||
geo_service.clear_cache()
|
||||
await geo_service.clear_cache()
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -162,7 +162,7 @@ class TestLookupCaching:
|
||||
)
|
||||
|
||||
await geo_service.lookup("2.3.4.5", session)
|
||||
geo_service.clear_cache()
|
||||
await geo_service.clear_cache()
|
||||
await geo_service.lookup("2.3.4.5", session)
|
||||
|
||||
assert session.get.call_count == 2
|
||||
@@ -259,7 +259,7 @@ class TestNegativeCache:
|
||||
session = _make_session({"status": "fail", "message": "private range"})
|
||||
|
||||
await geo_service.lookup("192.0.2.3", session)
|
||||
geo_service.clear_neg_cache()
|
||||
await geo_service.clear_neg_cache()
|
||||
await geo_service.lookup("192.0.2.3", session)
|
||||
|
||||
assert session.get.call_count == 2
|
||||
@@ -474,27 +474,27 @@ class TestLookupBatchSingleCommit:
|
||||
class TestDirtySetTracking:
|
||||
"""_store() marks successfully resolved IPs as dirty."""
|
||||
|
||||
def test_successful_resolution_adds_to_dirty(self) -> None:
|
||||
async def test_successful_resolution_adds_to_dirty(self) -> None:
|
||||
"""Storing a GeoInfo with a country_code adds the IP to _dirty."""
|
||||
info = GeoInfo(country_code="DE", country_name="Germany", asn="AS1", org="ISP")
|
||||
geo_service._store("1.2.3.4", info)
|
||||
await geo_service._store("1.2.3.4", info)
|
||||
|
||||
assert "1.2.3.4" in geo_service._dirty
|
||||
|
||||
def test_null_country_does_not_add_to_dirty(self) -> None:
|
||||
async def test_null_country_does_not_add_to_dirty(self) -> None:
|
||||
"""Storing a GeoInfo with country_code=None must not pollute _dirty."""
|
||||
info = GeoInfo(country_code=None, country_name=None, asn=None, org=None)
|
||||
geo_service._store("10.0.0.1", info)
|
||||
await geo_service._store("10.0.0.1", info)
|
||||
|
||||
assert "10.0.0.1" not in geo_service._dirty
|
||||
|
||||
def test_clear_cache_also_clears_dirty(self) -> None:
|
||||
async def test_clear_cache_also_clears_dirty(self) -> None:
|
||||
"""clear_cache() must discard any pending dirty entries."""
|
||||
info = GeoInfo(country_code="US", country_name="United States", asn="AS1", org="ISP")
|
||||
geo_service._store("8.8.8.8", info)
|
||||
await geo_service._store("8.8.8.8", info)
|
||||
assert geo_service._dirty
|
||||
|
||||
geo_service.clear_cache()
|
||||
await geo_service.clear_cache()
|
||||
|
||||
assert not geo_service._dirty
|
||||
|
||||
@@ -519,7 +519,7 @@ class TestFlushDirty:
|
||||
async def test_flush_writes_and_clears_dirty(self) -> None:
|
||||
"""flush_dirty() inserts all dirty IPs and clears _dirty afterwards."""
|
||||
info = GeoInfo(country_code="GB", country_name="United Kingdom", asn="AS2856", org="BT")
|
||||
geo_service._store("100.0.0.1", info)
|
||||
await geo_service._store("100.0.0.1", info)
|
||||
assert "100.0.0.1" in geo_service._dirty
|
||||
|
||||
db = _make_async_db()
|
||||
@@ -542,7 +542,7 @@ class TestFlushDirty:
|
||||
async def test_flush_re_adds_to_dirty_on_db_error(self) -> None:
|
||||
"""When the DB write fails, entries are re-added to _dirty for retry."""
|
||||
info = GeoInfo(country_code="AU", country_name="Australia", asn="AS1", org="ISP")
|
||||
geo_service._store("200.0.0.1", info)
|
||||
await geo_service._store("200.0.0.1", info)
|
||||
|
||||
db = _make_async_db()
|
||||
db.executemany = AsyncMock(side_effect=OSError("disk full"))
|
||||
@@ -881,7 +881,7 @@ class TestReResolveAll:
|
||||
AsyncMock(return_value=geo_map),
|
||||
) as mock_lookup, patch(
|
||||
"app.services.geo_service.clear_neg_cache",
|
||||
MagicMock(),
|
||||
AsyncMock(),
|
||||
) as mock_clear:
|
||||
result = await geo_service.re_resolve_all(db, session)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user