Coverage for api/utils/tallies.py: 94%
28 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 06:14 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 06:14 +0000
1from collections import defaultdict
2from datetime import datetime, timedelta
4import django_redis
5import structlog
6from django_redis.client.default import Redis
7from redis.exceptions import ConnectionError
10logger = structlog.get_logger(__name__)
13def get_weekly_timestamp() -> str:
14 """Get a timestamp for the Monday of any given week."""
15 now = datetime.now()
16 monday = now - timedelta(days=now.weekday())
17 return monday.strftime("%Y-%m-%d")
20def get_monthly_timestamp() -> str:
21 """Get a timestamp for the month."""
22 now = datetime.now()
23 return now.strftime("%Y-%m")
26def count_provider_occurrences(results: list[dict], index: str) -> None:
27 # Use ``get_redis_connection`` rather than Django's caches
28 # so that we can open a pipeline rather than sending off ``n``
29 # writes and because the RedisPy client's ``incr`` method
30 # is safe by default rather than Django's handspun method which:
31 # 1. Takes two requests to execute; and
32 # 2. Raises a ``ValueError`` if the key doesn't exist rather than
33 # just initialising the key to the value like Redis's behaviour.
34 tallies: Redis = django_redis.get_redis_connection("tallies")
36 provider_occurrences = defaultdict(int)
37 for result in results:
38 provider_occurrences[result["provider"]] += 1
40 week = get_weekly_timestamp()
41 with tallies.pipeline() as pipe:
42 for provider, occurrences in provider_occurrences.items():
43 pipe.incr(f"provider_occurrences:{index}:{week}:{provider}", occurrences)
44 pipe.incr(f"provider_appeared_in_searches:{index}:{week}:{provider}", 1)
45 try:
46 pipe.execute()
47 except ConnectionError:
48 logger.warning("Redis connect failed, cannot increment provider tallies.")