def apply_fix(transaction): Logger.info(f"Processing league {league.id}") rosters = self.league_roster_repo.get_all( league.id, transaction) schedule = self.league_config_repo.get_schedule_config( league.id, transaction) previews: Dict[str, UserLeaguePreview] = {} for roster in rosters: preview = self.user_league_repo.get( roster.id, league.id, transaction) previews[roster.id] = (preview) for roster in rosters: week: ScheduleWeek = next( week for week in schedule.weeks if week.week_number == current_week) matchup = next((m for m in week.matchups if (m.away and m.away.id == roster.id) or ( m.home and m.home.id == roster.id)), None) preview = previews[roster.id] if not preview: return False preview.matchup = MatchupPreview.from_matchup( matchup) if matchup else None self.user_league_repo.set(roster.id, preview, transaction) return True
def apply_fix(transaction): Logger.info(f"Processing league {league.id}") schedule = self.league_config_repo.get_schedule_config( league.id, transaction) save_required = False for week in schedule.weeks: for matchup in week.matchups: if matchup.away and matchup.away.waiver_bids: matchup.away.waiver_bids = [] save_required = True if matchup.away and matchup.away.processed_waiver_bids: matchup.away.processed_waiver_bids = [] save_required = True if matchup.home and matchup.home.waiver_bids: matchup.home.waiver_bids = [] save_required = True if matchup.home and matchup.home.processed_waiver_bids: matchup.home.processed_waiver_bids = [] save_required = True if save_required: self.league_config_repo.set_schedule_config( league.id, schedule, transaction) return save_required
def update_status_from_game_rosters(self, rostered_players: Dict[str, Player]): current_week = self.state_repo.get().current_week games = self.game_repo.for_week(self.season, current_week) teams_with_rosters: List[int] = [] player_ids_on_game_roster: List[str] = [] for game in games: if game.away_roster: teams_with_rosters.append(game.teams.away.id) ids = [p.id for p in game.away_roster.values()] player_ids_on_game_roster.extend(ids) if game.home_roster: teams_with_rosters.append(game.teams.home.id) ids = [p.id for p in game.home_roster.values()] player_ids_on_game_roster.extend(ids) for rostered_player in rostered_players.values(): scratched = rostered_player.team.id in teams_with_rosters and rostered_player.id not in player_ids_on_game_roster if rostered_player.status_current == STATUS_ACTIVE and scratched: rostered_player.status_current = STATUS_INACTIVE rostered_player.hash = hash_dict(rostered_player.dict()) Logger.info(f"Scratched {rostered_player.display_name}")
def run_check(name: str, target: Callable): try: Logger.info(f"Starting test '{name}'") target() Logger.info(f"Test '{name}' completed successfully") return True except BaseException as ex: Logger.error(f"Test '{name}' failed", exc_info=ex) return False
def apply_fix(transaction): Logger.info(f"Processing league {league.id}") config = self.league_config_repo.get_scoring_config(league.id, transaction) if config.field_goal_returns_yards != config.kick_returns_yards: config.field_goal_returns_yards = config.kick_returns_yards self.league_config_repo.set_scoring_config(league.id, config, transaction) return 1 else: return 0
def create_push_subscription(self, subscription_name: str, topic_name: str, endpoint: str, config: SubscriptionConfig = None): # return PubSubPublisher(self.project_id).create_push_subscription(subscription_name, topic_name, endpoint, config) Logger.info( f"Created virtual push subscription '{subscription_name}' on topic '{topic_name}' to {endpoint}" ) return Subscription(name=subscription_name)
def end_of_day(transaction: Transaction) -> EndOfDayResult: scoreboard = self.public_repo.get_scoreboard(transaction) state = self.state_repo.get(transaction) if not state.waivers_active: Logger.info("Waivers not active") week_complete = scoreboard.all_games_complete() if not week_complete: Logger.info("Week not yet complete") return EndOfDayResult(command=command) now = datetime.now(tz=pytz.UTC) hours_since_last_game = hours_since( scoreboard.last_game_start_time(), now) if hours_since_last_game < self.settings.min_stat_correction_hours: Logger.info( "Week complete but not enough time since last game", extra={ "hours_since": hours_since_last_game, "min_hours": self.settings.min_stat_correction_hours }) return EndOfDayResult(command=command) Logger.info( "Week is complete, enabling waivers and publishing end of week" ) state.waivers_active = True state.waivers_end = datetime.now().today() + timedelta(days=1) state.locks = Locks.reset() completed_week_number = scoreboard.week() state.current_week = completed_week_number + 1 self.state_repo.set(state, transaction) return EndOfDayResult( command=command, state=state, waivers_enabled=True, completed_week_number=completed_week_number) else: Logger.info( "Waivers are active, initializing waiver processing") state.waivers_active = False state.waivers_end = None self.state_repo.set(state, transaction) return EndOfDayResult(command=command, state=state, waivers_complete=True)
def apply_fix(transaction): Logger.info(f"Processing league {league.id}") rosters = self.league_roster_repo.get_all( league.id, transaction) for roster in rosters: roster.this_week_points_for = 0 roster.this_week_bench_points_for = 0 for position in roster.positions.values(): position.game_score = 0 self.league_roster_repo.set(league.id, roster, transaction)
def create_topic(self, topic_name: str): topic_path = self.get_topic_path(topic_name) try: try: self.publisher.get_topic(topic=topic_path) Logger.info("Topic exists", extra={"topic_name": topic_name}) except NotFound: self.publisher.create_topic(name=topic_path) Logger.info("Topic created", extra={"topic_name": topic_name}) except BaseException as ex: Logger.error("Failed to create topic", extra={"topic_name": topic_name}, exc_info=ex) raise ex
def execute(self, command: TCommand) -> TResult: name = type(self).__name__ extra = {"command": command.json()} Logger.info(f"{name} executing", extra=extra) try: result = self.on_execute(command) except Exception as ex: Logger.error(f"Error executing {name}", exc_info=ex, extra=extra) raise ex Logger.info(f"{name} completed") return result
def create_push_subscription( self, subscription_name: str, topic_name: str, endpoint: str, config: SubscriptionConfig = None) -> Subscription: subscriber: SubscriberWrapper = SubscriberClient() subcription_path = subscriber.subscription_path( self.project_id, subscription_name) topic_path = self.get_topic_path(topic_name) if not config: config = SubscriptionConfig() logging_extra = { "subscription_name": subscription_name, "topic_name": topic_name, "config": config.dict(), } with subscriber: try: try: subscription = subscriber.get_subscription( request={"subscription": subcription_path}) Logger.info("Push subscription exists", logging_extra) return subscription except NotFound: request = Subscription( name=subcription_path, topic=topic_path, push_config=PushConfig(push_endpoint=endpoint), ack_deadline_seconds=60, expiration_policy=ExpirationPolicy(ttl=Duration( seconds=config.expiration_days * 86400) if config.expiration_days else None), retry_policy=RetryPolicy(), message_retention_duration=Duration( seconds=config.retention_days * 86400)) subscription = subscriber.create_subscription( request=request) Logger.info("Push subscription created", logging_extra) return subscription except BaseException as ex: Logger.error("Failed to create push subscription", exc_info=ex, extra=logging_extra) raise ex
def get_roster(self, roster_id): Logger.info(f"[CFL API] Fetching roster id {roster_id}") url = f"{self.endpoint}{roster_id}" response = requests.get(url) data = response.json() try: if data["success"] == 1: return data["players"] else: raise ApiException(data["message"]) except Exception as ex: Logger.exception( f"[CFL API] Failed to fetch team rosters for {roster_id}", exc_info=ex) raise ApiException("Failed to retrieve rosters")
def on_execute( self, command: UpdatePlayerStatsForWeekCommand ) -> UpdatePlayerStatsForWeekResult: Logger.info(f"Updating player stats for week {command.week}") season = command.season if self.public_repo.get_switches().enable_score_testing: season = 2019 Logger.warn("SCORE TESTING SWITCH IS ENABLED") current_games = self.get_current_games(season, command.week) player_updates = get_players(current_games) transaction = self.game_repo.firestore.create_transaction() @firestore.transactional def update(transaction, players: List[GamePlayerStats]): pending_player_updates = [] for player_update in players: player = self.player_repo.get(season, player_update.player.id, transaction) game_id = player_update.game_id if not player: player = from_game_player(player_update.player, player_update.team) if not player.game_stats: player.game_stats = {} player.game_stats[game_id] = PlayerGameStats( team=player.team, **player_update.stats.dict()) pending_player_updates.append(player) for player in pending_player_updates: self.player_repo.set(season, player, transaction) return pending_player_updates update(transaction, player_updates) return UpdatePlayerStatsForWeekResult(command=command, )
def get_message_data(push: Dict) -> Dict: Logger.info(f"[PUB/SUB] {push}") if not push: raise InvalidPushException() message = push["message"] if not message: raise InvalidPushException() data = message["data"] if not data: raise InvalidPushException() try: payload = base64.b64decode(data) return json.loads(payload) except Exception: return data
def get(self, path: str) -> dict: url = f"{self.settings.cfl_api_endpoint}/{path}" url_no_key = url if "?" in url: url += f"&key={self.settings.cfl_api_key}" else: url += f"?key={self.settings.cfl_api_key}" Logger.info(f"[CFL API] Fetching {url_no_key}") response = requests.get(url) if response.ok: return response.json() else: Logger.error( f"[CFL API] Error fetching data from {url_no_key}: {response.text}" ) raise CflApiException(response.text)
def smoke_test(state_repo: StateRepository = Depends( create_state_repository)) -> Tuple[List[str], List[str]]: checks = { "firebase:state": state_repo.get, } Logger.info("Smoke test started") passes: List[str] = [] failures: List[str] = [] for name in checks: check = checks[name] passed = run_check(name, check) if passed: passes.append(name) else: failures.append(name) if failures: Logger.error("Smoke test completed with errors") else: Logger.info("Smoke test completed successfully") return passes, failures
def on_execute(self, command: UpdateGamesCommand) -> UpdateGamesResult: Logger.info(f"Updating games for week {command.week}") season = command.season if self.public_repo.get_switches().enable_score_testing: season = 2019 Logger.warn("SCORE TESTING SWITCH IS ENABLED") current_games = self.get_current_games(season, command.week) stored_games = self.get_stored_games(season, command.week) roster_added = False for game_id in current_games: current_game = current_games[game_id] stored_game = stored_games.get(game_id, None) if current_game.away_roster and (not stored_game or not stored_game.away_roster): roster_added = True if current_game.home_roster and (not stored_game or not stored_game.home_roster): roster_added = True game_updates = get_changed_games(current_games, stored_games) player_updates = get_changed_players(game_updates, stored_games) transaction = self.game_repo.firestore.create_transaction() locked_teams: List[str] = [] active_games_count = 0 opponents: Dict[str, str] = {} for game in current_games.values(): if game.event_status.event_status_id == EVENT_STATUS_POSTPONED: continue opponents[ game.teams.away.abbreviation] = game.teams.home.abbreviation opponents[ game.teams.home.abbreviation] = game.teams.away.abbreviation if game.event_status.has_started(): active_games_count += 1 locked_teams.append(game.teams.away.abbreviation) locked_teams.append(game.teams.home.abbreviation) all_games_active = active_games_count == len(current_games) new_locks_state = Locks.create(locked_teams, all_games_active) new_scoreboard = Scoreboard.create(current_games.values()) new_opponents = Opponents.create(opponents) @firestore.transactional def update_games(transaction, games: Dict[str, Game], players: List[GamePlayerStats]): state = self.state_repo.get() new_state = state.copy() new_state.locks = new_locks_state current_scoreboard = self.public_repo.get_scoreboard() current_opponents = self.public_repo.get_opponents() pending_player_updates = [] for player_update in players: player = self.player_repo.get(season, player_update.player.id, transaction) game_id = player_update.game_id if not player: player = from_game_player(player_update.player, player_update.team) if not player.game_stats: player.game_stats = {} player.game_stats[game_id] = PlayerGameStats( team=player.team, **player_update.stats.dict()) player.recalc_season_stats() # Should this be here? pending_player_updates.append(player) for game_id in games: game = game_updates[game_id] self.game_repo.set(season, game, transaction) for player in pending_player_updates: self.player_repo.set(season, player, transaction) if new_state.changed(state): self.state_repo.set(new_state, transaction) if new_scoreboard.changed(current_scoreboard): self.public_repo.set_scoreboard(new_scoreboard, transaction) if new_opponents.changed(current_opponents): self.public_repo.set_opponents(new_opponents, transaction) return pending_player_updates update_games(transaction, game_updates, player_updates) payloads = self.publish_changed_players(player_updates) if roster_added: self.publisher.publish(BaseModel(), UPDATE_PLAYERS_TOPIC) return UpdateGamesResult( command=command, changed_games=[game_updates[game_id] for game_id in game_updates], changed_players=payloads)
def create_topic(self, topic_name: str): # PubSubPublisher(self.project_id).create_topic(topic_name) Logger.info(f"Created virtual topic '{topic_name}'")
def publish(self, payload: BaseModel, topic_name: str): topic_path = self.get_topic_path(topic_name) data = payload.json() Logger.info(f"Published virtual pub/sub message to '{topic_path}") Logger.info(data)
async def info(): Logger.info("This is a test info log entry") Logger.info("This is a test info log entry with extra info", extra={"foo": "bar"}) return {"logger": Logger.logger_type()}