Fix critical week rollover bugs causing 60x freeze message spam
Three bugs identified and fixed: 1. Deduplication logic tracked wrong week (transaction_freeze.py:216-219) - Saved freeze_from_week BEFORE _begin_freeze() modifies current.week - Prevents re-execution when API returns stale data 2. _run_transactions() bypassed service layer (transaction_freeze.py:350-394) - Added get_regular_transactions_by_week() to transaction_service.py - Now properly filters frozen=false and cancelled=false - Uses Transaction model objects instead of raw dict access 3. CRITICAL: Hardcoded current_id=1 (league_service.py:88-106) - Current table has one row PER SEASON, not a single row - Was patching Season 3 (id=1) instead of Season 13 (id=11) - Now fetches actual current state ID before patching Root cause: The hardcoded ID caused every PATCH to update the wrong season's record, so freeze was never actually set to True on the current season. This caused the dedup check to pass 60 times (once per minute during hour 0). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
3ea743a489
commit
37bf797254
@ -85,17 +85,24 @@ class LeagueService(BaseService[Current]):
|
||||
logger.warning("update_current_state called with no updates")
|
||||
return await self.get_current_state()
|
||||
|
||||
# Current state always has ID of 1 (single record)
|
||||
current_id = 1
|
||||
# Get the current state to find its actual ID
|
||||
# (Current table has one row per season, NOT a single row with id=1)
|
||||
current = await self.get_current_state()
|
||||
if not current:
|
||||
logger.error("Cannot update current state - unable to fetch current state")
|
||||
return None
|
||||
|
||||
current_id = current.id
|
||||
logger.debug(f"Updating current state id={current_id} (season {current.season})")
|
||||
|
||||
# Use BaseService patch method
|
||||
updated_current = await self.patch(current_id, update_data)
|
||||
|
||||
if updated_current:
|
||||
logger.info(f"Updated current state: {update_data}")
|
||||
logger.info(f"Updated current state id={current_id}: {update_data}")
|
||||
return updated_current
|
||||
else:
|
||||
logger.error("Failed to update current state - patch returned None")
|
||||
logger.error(f"Failed to update current state id={current_id} - patch returned None")
|
||||
return None
|
||||
|
||||
except Exception as e:
|
||||
|
||||
@ -384,6 +384,43 @@ class TransactionService(BaseService[Transaction]):
|
||||
logger.error(f"Error getting frozen transactions for weeks {week_start}-{week_end}: {e}")
|
||||
return []
|
||||
|
||||
async def get_regular_transactions_by_week(
|
||||
self,
|
||||
season: int,
|
||||
week: int
|
||||
) -> List[Transaction]:
|
||||
"""
|
||||
Get non-frozen, non-cancelled transactions for a specific week.
|
||||
|
||||
This is used during freeze begin to process regular transactions
|
||||
that were submitted during the non-freeze period and should take
|
||||
effect immediately when the new week starts.
|
||||
|
||||
Args:
|
||||
season: Season number
|
||||
week: Week number to get transactions for
|
||||
|
||||
Returns:
|
||||
List of regular (non-frozen, non-cancelled) transactions for the week
|
||||
"""
|
||||
try:
|
||||
params = [
|
||||
('season', str(season)),
|
||||
('week_start', str(week)),
|
||||
('week_end', str(week)),
|
||||
('frozen', 'false'),
|
||||
('cancelled', 'false')
|
||||
]
|
||||
|
||||
transactions = await self.get_all_items(params=params)
|
||||
|
||||
logger.debug(f"Retrieved {len(transactions)} regular transactions for week {week}")
|
||||
return transactions
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting regular transactions for week {week}: {e}")
|
||||
return []
|
||||
|
||||
async def get_contested_transactions(self, season: int, week: int) -> List[Transaction]:
|
||||
"""
|
||||
Get transactions that may be contested (multiple teams want same player).
|
||||
|
||||
@ -213,9 +213,10 @@ class TransactionFreezeTask:
|
||||
# Only run if we haven't already frozen this week
|
||||
# Track the week we're freezing FROM (before increment)
|
||||
if self.last_freeze_week != current.week:
|
||||
freeze_from_week = current.week # Save BEFORE _begin_freeze modifies it
|
||||
self.logger.info("Triggering freeze begin", current_week=current.week)
|
||||
await self._begin_freeze(current)
|
||||
self.last_freeze_week = current.week # Track the week we froze (before increment)
|
||||
self.last_freeze_week = freeze_from_week # Track the week we froze FROM
|
||||
self.error_notification_sent = False # Reset error flag for new cycle
|
||||
else:
|
||||
self.logger.debug("Freeze already executed for week", week=current.week)
|
||||
@ -341,26 +342,22 @@ class TransactionFreezeTask:
|
||||
|
||||
async def _run_transactions(self, current: Current):
|
||||
"""
|
||||
Process regular (non-frozen) transactions for the current week.
|
||||
Process regular (non-frozen, non-cancelled) transactions for the current week.
|
||||
|
||||
These are transactions that take effect immediately.
|
||||
These are transactions that were submitted during the non-freeze period
|
||||
and should take effect immediately when the new week starts.
|
||||
"""
|
||||
try:
|
||||
# Get all non-frozen transactions for current week
|
||||
client = await transaction_service.get_client()
|
||||
params = [
|
||||
('season', str(current.season)),
|
||||
('week_start', str(current.week)),
|
||||
('week_end', str(current.week))
|
||||
]
|
||||
# Get non-frozen, non-cancelled transactions for current week via service
|
||||
transactions = await transaction_service.get_regular_transactions_by_week(
|
||||
season=current.season,
|
||||
week=current.week
|
||||
)
|
||||
|
||||
response = await client.get('transactions', params=params)
|
||||
|
||||
if not response or response.get('count', 0) == 0:
|
||||
if not transactions:
|
||||
self.logger.info(f"No regular transactions to process for week {current.week}")
|
||||
return
|
||||
|
||||
transactions = response.get('transactions', [])
|
||||
self.logger.info(f"Processing {len(transactions)} regular transactions for week {current.week}")
|
||||
|
||||
# Execute player roster updates for all transactions
|
||||
@ -371,9 +368,9 @@ class TransactionFreezeTask:
|
||||
try:
|
||||
# Update player's team via PATCH /players/{player_id}?team_id={new_team_id}
|
||||
await self._execute_player_update(
|
||||
player_id=transaction['player']['id'],
|
||||
new_team_id=transaction['newteam']['id'],
|
||||
player_name=transaction['player']['name']
|
||||
player_id=transaction.player.id,
|
||||
new_team_id=transaction.newteam.id,
|
||||
player_name=transaction.player.name
|
||||
)
|
||||
success_count += 1
|
||||
|
||||
@ -382,9 +379,9 @@ class TransactionFreezeTask:
|
||||
|
||||
except Exception as e:
|
||||
self.logger.error(
|
||||
f"Failed to execute transaction for {transaction['player']['name']}",
|
||||
player_id=transaction['player']['id'],
|
||||
new_team_id=transaction['newteam']['id'],
|
||||
f"Failed to execute transaction for {transaction.player.name}",
|
||||
player_id=transaction.player.id,
|
||||
new_team_id=transaction.newteam.id,
|
||||
error=str(e)
|
||||
)
|
||||
failure_count += 1
|
||||
|
||||
Loading…
Reference in New Issue
Block a user