From bddb2ab4d4eee4aaa17d1f6dddb9b1a1cc954582 Mon Sep 17 00:00:00 2001 From: Fred Boniface Date: Mon, 2 Nov 2026 11:07:42 +0000 Subject: [PATCH] Ensure all print statements are flushed immediately --- main.py | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/main.py b/main.py index 7b517e2..b910590 100644 --- a/main.py +++ b/main.py @@ -1,4 +1,6 @@ import os +import sys +import random import time import json import sqlite3 @@ -57,6 +59,10 @@ AI_PLAYLIST_DEFINITIONS = [ } ] +jitter = random.randint(0, 300) +print(f"Jitter active: sleeping for {jitter} seconds...", flush=True) +time.sleep(jitter) + # Initialize Gemini Client gemini_client = genai.Client(api_key=GEMINI_API_KEY) @@ -94,7 +100,7 @@ def init_db(): conn.close() def sync_library_to_sqlite(): - print("Fetching full track catalog from Gonic API...") + print("Fetching full track catalog from Gonic API...", flush=True) auth = get_auth_params() res = requests.get(f"{GONIC_URL}/getArtists.view", params=auth).json() @@ -128,7 +134,7 @@ def sync_library_to_sqlite(): cursor.executemany("INSERT OR REPLACE INTO tracks VALUES (?, ?, ?, ?, ?, ?)", all_tracks) conn.commit() conn.close() - print(f"Synced {len(all_tracks)} tracks to local SQLite index.") + print(f"Synced {len(all_tracks)} tracks to local SQLite index.", flush=True) def check_library_changed(): auth = get_auth_params() @@ -215,7 +221,7 @@ def ask_gemini_for_tracks(prompt, candidates): except Exception as e: if "503" in str(e) or "UNAVAILABLE" in str(e): if attempt < max_retries - 1: - print(f"Gemini capacity spike (503). Retrying in {delay}s (Attempt {attempt + 1}/{max_retries})...") + print(f"Gemini capacity spike (503). Retrying in {delay}s (Attempt {attempt + 1}/{max_retries})...", flush=True) time.sleep(delay) delay *= 2 continue @@ -227,7 +233,7 @@ def ask_gemini_for_tracks(prompt, candidates): try: return json.loads(response.text) except Exception as e: - print(f"Error parsing Gemini response: {e}\nRaw output: {response.text}") + print(f"Error parsing Gemini response: {e}\nRaw output: {response.text}", flush=True) return [] def ensure_and_process_ai_playlists(library_has_changed): @@ -251,7 +257,7 @@ def ensure_and_process_ai_playlists(library_has_changed): # 1. Create playlist automatically if it doesn't exist for this user account if not playlist_id: - print(f"Playlist '{name}' not found for user. Creating it...") + print(f"Playlist '{name}' not found for user. Creating it...", flush=True) requests.get(f"{GONIC_URL}/createPlaylist.view", params={ **auth, "name": name, @@ -266,7 +272,7 @@ def ensure_and_process_ai_playlists(library_has_changed): break if not playlist_id: - print(f"Failed to create or locate playlist '{name}'. Skipping.") + print(f"Failed to create or locate playlist '{name}'. Skipping.", flush=True) continue # 2. Fetch current playlist contents from Gonic @@ -287,19 +293,19 @@ def ensure_and_process_ai_playlists(library_has_changed): library_refresh_due = library_has_changed and (now - last_curated) > 86400 if not (is_empty or cooldown_expired or library_refresh_due): - print(f"Playlist '{name}' is up to date (Last curated {(now - last_curated) // 3600}h ago). Skipping Gemini.") + print(f"Playlist '{name}' is up to date (Last curated {(now - last_curated) // 3600}h ago). Skipping Gemini.", flush=True) continue reason = "Empty/New" if is_empty else ("Periodic refresh" if cooldown_expired else "Library update") - print(f"Processing AI Playlist ({reason}): '{name}' with prompt: '{prompt}'") + print(f"Processing AI Playlist ({reason}): '{name}' with prompt: '{prompt}'", flush=True) candidates = query_candidate_tracks(prompt) if not candidates: - print("No matching candidate tracks found in local index.") + print("No matching candidate tracks found in local index.", flush=True) continue selected_ids = ask_gemini_for_tracks(prompt, candidates) - print(f"Gemini selected {len(selected_ids)} tracks.") + print(f"Gemini selected {len(selected_ids)} tracks.", flush=True) if selected_ids: existing_song_ids = {str(song.get("id")) for song in existing_entries} @@ -318,11 +324,11 @@ def ensure_and_process_ai_playlists(library_has_changed): update_res = requests.get(f"{GONIC_URL}/updatePlaylist.view", params=query_list).json() if update_res.get("subsonic-response", {}).get("status") == "ok": - print(f"Successfully added {len(tracks_to_add)} new tracks to '{name}'!") + print(f"Successfully added {len(tracks_to_add)} new tracks to '{name}'!", flush=True) else: print(f"Failed to update playlist: {update_res}") else: - print(f"Playlist '{name}' has no new unique tracks to add from this selection.") + print(f"Playlist '{name}' has no new unique tracks to add from this selection.", flush=True) # Update last curated timestamp in SQLite state table cursor.execute("INSERT OR REPLACE INTO playlist_state (name, last_curated) VALUES (?, ?)", (name, now)) @@ -332,23 +338,23 @@ def ensure_and_process_ai_playlists(library_has_changed): def main(): init_db() - print("AI Playlist Sync one-shot execution started.") + print("AI Playlist Sync one-shot execution started.", flush=True) try: # 1. Sync library catalog only if changes are detected or local DB is missing lib_changed = check_library_changed() if lib_changed or not os.path.exists(DB_PATH): - print("Library changes detected (or missing local index). Updating local SQLite index...") + print("Library changes detected (or missing local index). Updating local SQLite index...", flush=True) sync_library_to_sqlite() else: - print("Library catalog unchanged. Using existing local SQLite index.") + print("Library catalog unchanged. Using existing local SQLite index.", flush=True) # 2. Check and process playlists using the time-based curation cooldown matrix ensure_and_process_ai_playlists(lib_changed) - print("AI Playlist Sync execution completed successfully.") + print("AI Playlist Sync execution completed successfully.", flush=True) except Exception as e: - print(f"Error during execution: {e}") + print(f"Error during execution: {e}", flush=True) raise e if __name__ == "__main__":