diff --git a/app/services/player_service.py b/app/services/player_service.py index 23ab8d8..b3302b3 100644 --- a/app/services/player_service.py +++ b/app/services/player_service.py @@ -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)