fix: invalidate cache after PlayerService write operations (#32)
All checks were successful
Build Docker Image / build (pull_request) Successful in 2m10s
All checks were successful
Build Docker Image / build (pull_request) Successful in 2m10s
Add finally blocks to update_player, patch_player, create_players, and delete_player in PlayerService to call invalidate_related_cache() using the existing cache_patterns. Matches the pattern already used in TeamService. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
ddf5f77da4
commit
ea7c62c93f
@ -39,7 +39,7 @@ class PlayerService(BaseService):
|
||||
cache_patterns = ["players*", "players-search*", "player*", "team-roster*"]
|
||||
|
||||
# Deprecated fields to exclude from player responses
|
||||
EXCLUDED_FIELDS = ['pitcher_injury']
|
||||
EXCLUDED_FIELDS = ["pitcher_injury"]
|
||||
|
||||
# Class-level repository for dependency injection
|
||||
_injected_repo: Optional[AbstractPlayerRepository] = None
|
||||
@ -154,7 +154,7 @@ class PlayerService(BaseService):
|
||||
return {
|
||||
"count": len(players_data),
|
||||
"total": total_count,
|
||||
"players": players_data
|
||||
"players": players_data,
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
@ -204,9 +204,9 @@ class PlayerService(BaseService):
|
||||
p_list = [x.upper() for x in pos]
|
||||
|
||||
# Expand generic "P" to match all pitcher positions
|
||||
pitcher_positions = ['SP', 'RP', 'CP']
|
||||
if 'P' in p_list:
|
||||
p_list.remove('P')
|
||||
pitcher_positions = ["SP", "RP", "CP"]
|
||||
if "P" in p_list:
|
||||
p_list.remove("P")
|
||||
p_list.extend(pitcher_positions)
|
||||
|
||||
pos_conditions = (
|
||||
@ -245,9 +245,9 @@ class PlayerService(BaseService):
|
||||
p_list = [p.upper() for p in pos]
|
||||
|
||||
# Expand generic "P" to match all pitcher positions
|
||||
pitcher_positions = ['SP', 'RP', 'CP']
|
||||
if 'P' in p_list:
|
||||
p_list.remove('P')
|
||||
pitcher_positions = ["SP", "RP", "CP"]
|
||||
if "P" in p_list:
|
||||
p_list.remove("P")
|
||||
p_list.extend(pitcher_positions)
|
||||
|
||||
player_pos = [
|
||||
@ -385,19 +385,23 @@ class PlayerService(BaseService):
|
||||
# This filters at the database level instead of loading all players
|
||||
if search_all_seasons:
|
||||
# Search all seasons, order by season DESC (newest first)
|
||||
query = (Player.select()
|
||||
.where(fn.Lower(Player.name).contains(query_lower))
|
||||
.order_by(Player.season.desc(), Player.name)
|
||||
.limit(limit * 2)) # Get extra for exact match sorting
|
||||
query = (
|
||||
Player.select()
|
||||
.where(fn.Lower(Player.name).contains(query_lower))
|
||||
.order_by(Player.season.desc(), Player.name)
|
||||
.limit(limit * 2)
|
||||
) # Get extra for exact match sorting
|
||||
else:
|
||||
# Search specific season
|
||||
query = (Player.select()
|
||||
.where(
|
||||
(Player.season == season) &
|
||||
(fn.Lower(Player.name).contains(query_lower))
|
||||
)
|
||||
.order_by(Player.name)
|
||||
.limit(limit * 2)) # Get extra for exact match sorting
|
||||
query = (
|
||||
Player.select()
|
||||
.where(
|
||||
(Player.season == season)
|
||||
& (fn.Lower(Player.name).contains(query_lower))
|
||||
)
|
||||
.order_by(Player.name)
|
||||
.limit(limit * 2)
|
||||
) # Get extra for exact match sorting
|
||||
|
||||
# Execute query and convert limited results to dicts
|
||||
players = list(query)
|
||||
@ -468,19 +472,29 @@ class PlayerService(BaseService):
|
||||
# Use backrefs=False to avoid circular reference issues
|
||||
player_dict = model_to_dict(player, recurse=recurse, backrefs=False)
|
||||
# Filter out excluded fields
|
||||
return {k: v for k, v in player_dict.items() if k not in cls.EXCLUDED_FIELDS}
|
||||
return {
|
||||
k: v for k, v in player_dict.items() if k not in cls.EXCLUDED_FIELDS
|
||||
}
|
||||
except (ImportError, AttributeError, TypeError) as e:
|
||||
# Log the error and fall back to non-recursive serialization
|
||||
logger.warning(f"Error in recursive player serialization: {e}, falling back to non-recursive")
|
||||
logger.warning(
|
||||
f"Error in recursive player serialization: {e}, falling back to non-recursive"
|
||||
)
|
||||
try:
|
||||
# Fallback to non-recursive serialization
|
||||
player_dict = model_to_dict(player, recurse=False)
|
||||
return {k: v for k, v in player_dict.items() if k not in cls.EXCLUDED_FIELDS}
|
||||
return {
|
||||
k: v for k, v in player_dict.items() if k not in cls.EXCLUDED_FIELDS
|
||||
}
|
||||
except Exception as fallback_error:
|
||||
# Final fallback to basic dict conversion
|
||||
logger.error(f"Error in non-recursive serialization: {fallback_error}, using basic dict")
|
||||
logger.error(
|
||||
f"Error in non-recursive serialization: {fallback_error}, using basic dict"
|
||||
)
|
||||
player_dict = dict(player)
|
||||
return {k: v for k, v in player_dict.items() if k not in cls.EXCLUDED_FIELDS}
|
||||
return {
|
||||
k: v for k, v in player_dict.items() if k not in cls.EXCLUDED_FIELDS
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def update_player(
|
||||
@ -508,6 +522,8 @@ class PlayerService(BaseService):
|
||||
raise HTTPException(
|
||||
status_code=500, detail=f"Error updating player {player_id}: {str(e)}"
|
||||
)
|
||||
finally:
|
||||
temp_service.invalidate_related_cache(cls.cache_patterns)
|
||||
|
||||
@classmethod
|
||||
def patch_player(
|
||||
@ -535,6 +551,8 @@ class PlayerService(BaseService):
|
||||
raise HTTPException(
|
||||
status_code=500, detail=f"Error patching player {player_id}: {str(e)}"
|
||||
)
|
||||
finally:
|
||||
temp_service.invalidate_related_cache(cls.cache_patterns)
|
||||
|
||||
@classmethod
|
||||
def create_players(
|
||||
@ -567,6 +585,8 @@ class PlayerService(BaseService):
|
||||
raise HTTPException(
|
||||
status_code=500, detail=f"Error creating players: {str(e)}"
|
||||
)
|
||||
finally:
|
||||
temp_service.invalidate_related_cache(cls.cache_patterns)
|
||||
|
||||
@classmethod
|
||||
def delete_player(cls, player_id: int, token: str) -> Dict[str, str]:
|
||||
@ -590,6 +610,8 @@ class PlayerService(BaseService):
|
||||
raise HTTPException(
|
||||
status_code=500, detail=f"Error deleting player {player_id}: {str(e)}"
|
||||
)
|
||||
finally:
|
||||
temp_service.invalidate_related_cache(cls.cache_patterns)
|
||||
|
||||
@classmethod
|
||||
def _format_player_csv(cls, players: List[Dict]) -> str:
|
||||
@ -603,12 +625,12 @@ class PlayerService(BaseService):
|
||||
flat_player = player.copy()
|
||||
|
||||
# Flatten team object to just abbreviation
|
||||
if isinstance(flat_player.get('team'), dict):
|
||||
flat_player['team'] = flat_player['team'].get('abbrev', '')
|
||||
if isinstance(flat_player.get("team"), dict):
|
||||
flat_player["team"] = flat_player["team"].get("abbrev", "")
|
||||
|
||||
# Flatten sbaplayer object to just ID
|
||||
if isinstance(flat_player.get('sbaplayer'), dict):
|
||||
flat_player['sbaplayer'] = flat_player['sbaplayer'].get('id', '')
|
||||
if isinstance(flat_player.get("sbaplayer"), dict):
|
||||
flat_player["sbaplayer"] = flat_player["sbaplayer"].get("id", "")
|
||||
|
||||
flattened_players.append(flat_player)
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user