"""Background task que consulta recently_played cada 30s y persiste el historial.""" import asyncio import logging from datetime import datetime, timezone from app.database import SessionLocal from app.models import PlayHistory from app import spotify logger = logging.getLogger(__name__) POLL_INTERVAL = 30 # segundos async def start_poller(): while True: try: await asyncio.to_thread(_fetch_and_save) except Exception as exc: logger.warning("history_poller error: %s", exc) await asyncio.sleep(POLL_INTERVAL) def _fetch_and_save(): if not spotify.is_authenticated(): return sp = spotify.get_client() result = sp.current_user_recently_played(limit=50) items = result.get("items", []) if not items: return # Recolectar IDs de artistas Ășnicos para lookup de gĂ©neros en batch artist_ids: set[str] = set() for item in items: for artist in item["track"]["artists"]: artist_ids.add(artist["id"]) genre_map: dict[str, list[str]] = {} artist_id_list = list(artist_ids) for i in range(0, len(artist_id_list), 50): batch = artist_id_list[i : i + 50] try: data = sp.artists(batch) for a in data.get("artists") or []: if a: genre_map[a["id"]] = a.get("genres", []) except Exception: pass db = SessionLocal() try: saved = 0 for item in items: track = item["track"] played_at = datetime.fromisoformat( item["played_at"].replace("Z", "+00:00") ) exists = ( db.query(PlayHistory) .filter( PlayHistory.track_id == track["id"], PlayHistory.played_at == played_at, ) .first() ) if exists: continue track_artists = track.get("artists", []) artist_names = [a["name"] for a in track_artists] genres: set[str] = set() for a in track_artists: genres.update(genre_map.get(a["id"], [])) db.add( PlayHistory( track_id=track["id"], track_name=track["name"], artists=", ".join(artist_names), genres=", ".join(sorted(genres)), played_at=played_at, ) ) saved += 1 if saved: db.commit() logger.info("history_poller: guardadas %d reproducciones", saved) except Exception: db.rollback() raise finally: db.close()