"""Logic for new_music_friday.""" from datetime import date from datetime import datetime from datetime import time from datetime import timedelta from pydantic import BaseModel from pydantic import TypeAdapter from pydantic import ValidationError from pydantic import field_serializer from charts.api import app from charts.constants.dates import DAYS_IN_WEEK from charts.constants.dates import ISO_WEEKDAY_FRIDAY from charts.constants.new_music_friday import NEW_MUSIC_FRIDAY_FIRST_TIMEZONE from charts.constants.new_music_friday import NEW_MUSIC_FRIDAY_DATES_REDIS_KEY from charts.connectors import redis from charts.connectors import snowflake from charts.logic import sql_loader newMusicFridayDateListSnowflakeResponseTA = TypeAdapter(list[tuple[date]]) class NewMusicFridayDatesResponse(BaseModel): dates: list[date] @field_serializer('dates') def serialize_dates(self, value: list[date]) -> list[str]: return [date.strftime('%Y-%m-%d') for date in value] def new_music_friday_dates() -> NewMusicFridayDatesResponse: sql = sql_loader.load_query('new_music_friday/dates') redis_result_raw: str | None = None try: # Redis sync types are incorrect. See https://github.com/redis/redis-py/issues/2897 redis_result_raw = redis.client.get(NEW_MUSIC_FRIDAY_DATES_REDIS_KEY) # type: ignore[assignment] except redis.exceptions.ConnectionError: app.logger.warning("Redis connection error", exc_info=True) pass if redis_result_raw: try: return NewMusicFridayDatesResponse.model_validate_json(redis_result_raw) except ValidationError: app.logger.warning('NMF Redis validation error', exc_info=True) pass raw_db_result = snowflake.fetchall_nocache(sql, {}) parsed_db_result = newMusicFridayDateListSnowflakeResponseTA.validate_python(raw_db_result) result = NewMusicFridayDatesResponse( dates=[row[0] for row in parsed_db_result] ) expiry = datetime.combine(result.dates[0], time(), NEW_MUSIC_FRIDAY_FIRST_TIMEZONE) + timedelta(days=7) try: redis.client.set( NEW_MUSIC_FRIDAY_DATES_REDIS_KEY, result.model_dump_json(), exat=int(expiry.timestamp()), ) except redis.exceptions.ConnectionError: app.logger.warning("Redis connection error", exc_info=True) pass return result