Fix: Prevent creating multiple today fixtures by adding cache

- Added _cached_today_fixture_id and _today_fixture_cache_time to cache today's fixture
- Cache is valid for 60 seconds to prevent race conditions
- This prevents multiple fixtures being created when _get_or_create_today_fixture is called multiple times in quick succession
- Also provides MySQL queries for user to clean up duplicate fixtures
parent 537311c1
......@@ -33,6 +33,8 @@ class GamesThread(ThreadedComponent):
self.yesterday_fixture_id: Optional[str] = None # Track yesterday's fixture for completion
self._last_orphan_cleanup_time: float = 0.0 # Track last orphan cleanup time
self._orphan_cleanup_interval: int = 10 # Run orphan cleanup every 10 seconds
self._cached_today_fixture_id: Optional[str] = None # Cache for today's fixture to prevent duplicates
self._today_fixture_cache_time: float = 0.0 # Timestamp when cache was set
def _get_today_venue_date(self) -> datetime.date:
"""Get today's date in venue timezone (for day change detection)"""
......@@ -648,8 +650,17 @@ class GamesThread(ThreadedComponent):
This method ensures that new matches are created in today's fixture,
not in yesterday's fixture. It uses multiple strategies to find existing
today fixtures to prevent creating duplicates.
A cache is used to prevent race conditions where multiple calls might
create duplicate fixtures.
"""
try:
# Check cache first (valid for 60 seconds)
current_time = time.time()
if self._cached_today_fixture_id and (current_time - self._today_fixture_cache_time) < 60:
logger.info(f"Using cached today fixture: {self._cached_today_fixture_id}")
return self._cached_today_fixture_id
session = self.db_manager.get_session()
try:
# Get today's date in venue timezone
......@@ -671,8 +682,12 @@ class GamesThread(ThreadedComponent):
).order_by(MatchModel.created_at.desc()).first()
if today_match_with_start_time:
logger.info(f"Found existing today fixture (by start_time): {today_match_with_start_time.fixture_id}")
return today_match_with_start_time.fixture_id
fixture_id = today_match_with_start_time.fixture_id
logger.info(f"Found existing today fixture (by start_time): {fixture_id}")
# Cache the result
self._cached_today_fixture_id = fixture_id
self._today_fixture_cache_time = current_time
return fixture_id
# Strategy 2: Check for matches created today (using created_at as fallback)
# This catches matches that were just created and don't have start_time yet
......@@ -683,8 +698,12 @@ class GamesThread(ThreadedComponent):
).order_by(MatchModel.created_at.asc()).first()
if today_match_by_created:
logger.info(f"Found existing today fixture (by created_at): {today_match_by_created.fixture_id}")
return today_match_by_created.fixture_id
fixture_id = today_match_by_created.fixture_id
logger.info(f"Found existing today fixture (by created_at): {fixture_id}")
# Cache the result
self._cached_today_fixture_id = fixture_id
self._today_fixture_cache_time = current_time
return fixture_id
# No today fixture exists - create a new one
logger.info("No today fixture found - creating new fixture")
......@@ -693,6 +712,9 @@ class GamesThread(ThreadedComponent):
new_fixture_id = self._initialize_new_fixture()
if new_fixture_id:
logger.info(f"Created new today fixture: {new_fixture_id}")
# Cache the result
self._cached_today_fixture_id = new_fixture_id
self._today_fixture_cache_time = current_time
return new_fixture_id
finally:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment