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): ...@@ -33,6 +33,8 @@ class GamesThread(ThreadedComponent):
self.yesterday_fixture_id: Optional[str] = None # Track yesterday's fixture for completion 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._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._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: def _get_today_venue_date(self) -> datetime.date:
"""Get today's date in venue timezone (for day change detection)""" """Get today's date in venue timezone (for day change detection)"""
...@@ -648,8 +650,17 @@ class GamesThread(ThreadedComponent): ...@@ -648,8 +650,17 @@ class GamesThread(ThreadedComponent):
This method ensures that new matches are created in today's fixture, This method ensures that new matches are created in today's fixture,
not in yesterday's fixture. It uses multiple strategies to find existing not in yesterday's fixture. It uses multiple strategies to find existing
today fixtures to prevent creating duplicates. today fixtures to prevent creating duplicates.
A cache is used to prevent race conditions where multiple calls might
create duplicate fixtures.
""" """
try: 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() session = self.db_manager.get_session()
try: try:
# Get today's date in venue timezone # Get today's date in venue timezone
...@@ -671,8 +682,12 @@ class GamesThread(ThreadedComponent): ...@@ -671,8 +682,12 @@ class GamesThread(ThreadedComponent):
).order_by(MatchModel.created_at.desc()).first() ).order_by(MatchModel.created_at.desc()).first()
if today_match_with_start_time: if today_match_with_start_time:
logger.info(f"Found existing today fixture (by start_time): {today_match_with_start_time.fixture_id}") fixture_id = today_match_with_start_time.fixture_id
return 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) # 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 # This catches matches that were just created and don't have start_time yet
...@@ -683,8 +698,12 @@ class GamesThread(ThreadedComponent): ...@@ -683,8 +698,12 @@ class GamesThread(ThreadedComponent):
).order_by(MatchModel.created_at.asc()).first() ).order_by(MatchModel.created_at.asc()).first()
if today_match_by_created: if today_match_by_created:
logger.info(f"Found existing today fixture (by created_at): {today_match_by_created.fixture_id}") fixture_id = today_match_by_created.fixture_id
return 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 # No today fixture exists - create a new one
logger.info("No today fixture found - creating new fixture") logger.info("No today fixture found - creating new fixture")
...@@ -693,6 +712,9 @@ class GamesThread(ThreadedComponent): ...@@ -693,6 +712,9 @@ class GamesThread(ThreadedComponent):
new_fixture_id = self._initialize_new_fixture() new_fixture_id = self._initialize_new_fixture()
if new_fixture_id: if new_fixture_id:
logger.info(f"Created new today fixture: {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 return new_fixture_id
finally: 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