поправил турнирку

This commit is contained in:
2025-10-27 20:48:31 +03:00
parent b301f1e918
commit 97045a0f72
2 changed files with 32 additions and 35 deletions

View File

@@ -688,15 +688,6 @@ def run_live_loop(
render_thread.start() render_thread.start()
logger.info("[LIVE_THREAD] render thread spawned") logger.info("[LIVE_THREAD] render thread spawned")
# поток standings
standings_thread = threading.Thread(
target=Standing_func,
args=(session, league, season, lang, stop_event),
daemon=False,
)
standings_thread.start()
logger.info("[LIVE_THREAD] standings thread spawned")
try: try:
poll_game_live( poll_game_live(
session=session, session=session,
@@ -714,7 +705,6 @@ def run_live_loop(
logger.info(f"[LIVE_THREAD] stopping worker threads for game_id={game_id}") logger.info(f"[LIVE_THREAD] stopping worker threads for game_id={game_id}")
render_thread.join() render_thread.join()
standings_thread.join()
logger.info(f"[LIVE_THREAD] stop live loop for game_id={game_id}") logger.info(f"[LIVE_THREAD] stop live loop for game_id={game_id}")
@@ -823,7 +813,6 @@ def render_once_after_game(
Referee(state) Referee(state)
# === 4. live_status и общий state === # === 4. live_status и общий state ===
atomic_write_json([state["result"]["live_status"]], "live_status")
atomic_write_json(state["result"], out_name) atomic_write_json(state["result"], out_name)
logger.info("[RENDER_ONCE] финальные json сохранены успешно") logger.info("[RENDER_ONCE] финальные json сохранены успешно")
@@ -1460,6 +1449,8 @@ def Standing_func(
# когда мы последний раз успешно обновили standings # когда мы последний раз успешно обновили standings
last_call_ts = 0 last_call_ts = 0
json_seasons = fetch_api_data(session, "seasons", host=HOST, league=league, lang=lang)
season = json_seasons[0]["season"]
# как часто вообще можно дёргать standings # как часто вообще можно дёргать standings
interval = get_interval_by_name("standings") interval = get_interval_by_name("standings")
@@ -1705,64 +1696,70 @@ def get_data_API(
logger.info("Для этой команды игр сегодня нет и нет завершённой последней игры.") logger.info("Для этой команды игр сегодня нет и нет завершённой последней игры.")
def main() -> None: def main():
"""
Главный цикл демона.
Работает бесконечно:
- собирает данные на сегодня (get_data_API)
- если нужно, следит за матчем в реальном времени до свистка
- после этого уходит спать до 00:05 следующего дня по APP_TZ
- повторяет
Ctrl+C:
- моментально поднимает stop_event и завершает работу.
"""
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument("--league", default="vtb") parser.add_argument("--league", default="vtb")
parser.add_argument("--team", required=True) parser.add_argument("--team", required=True)
parser.add_argument("--lang", default="en") parser.add_argument("--lang", default="en")
args = parser.parse_args() args = parser.parse_args()
while True: # Один общий stop_event на всё приложение.
# на каждый "прогон дня" — своя HTTP-сессия и свой stop_event
session = create_session()
stop_event = threading.Event() stop_event = threading.Event()
# Одна сессия для standings-потока.
# Её достаточно, потому что standings не требует суперчастого обновления.
standings_session = create_session()
# Запускаем standings-поток навсегда (пока процесс жив).
standings_thread = threading.Thread(
target=Standing_func,
args=(standings_session, args.league, None, args.lang, stop_event),
daemon=False,
)
standings_thread.start()
logger.info("[MAIN] standings thread started (global)")
# Основной дневной цикл.
while True:
session = create_session()
try: try:
get_data_API(session, args.league, args.team, args.lang, stop_event) get_data_API(session, args.league, args.team, args.lang, stop_event)
except KeyboardInterrupt: except KeyboardInterrupt:
logger.info("KeyboardInterrupt -> остановка по запросу оператора") logger.info("KeyboardInterrupt -> останавливаем всё")
stop_event.set() stop_event.set()
break break
except Exception as e: except Exception as e:
# мы не падаем навсегда, а логируем, чтобы демон продолжил жить
logger.exception(f"main loop crash: {e}") logger.exception(f"main loop crash: {e}")
# === сон до завтрашних 00:05 по APP_TZ === # спим до завтра 00:05
now = datetime.now(APP_TZ) now = datetime.now(APP_TZ)
tomorrow = (now + timedelta(days=1)).replace( tomorrow = (now + timedelta(days=1)).replace(
hour=0, minute=5, second=0, microsecond=0 hour=0, minute=5, second=0, microsecond=0
) )
sleep_seconds = (tomorrow - now).total_seconds() sleep_seconds = (tomorrow - now).total_seconds()
if sleep_seconds < 0: if sleep_seconds < 0:
# защита, если вдруг текущее время уже после 00:05 и replace() дал прошедшее
tomorrow = (now + timedelta(days=2)).replace( tomorrow = (now + timedelta(days=2)).replace(
hour=0, minute=5, second=0, microsecond=0 hour=0, minute=5, second=0, microsecond=0
) )
sleep_seconds = (tomorrow - now).total_seconds() sleep_seconds = (tomorrow - now).total_seconds()
logger.info( logger.info(
f"Работа завершена. Засыпаем до {tomorrow.strftime('%d.%m %H:%M')} " f"Работа за день завершена. Засыпаем до {tomorrow.strftime('%d.%m %H:%M')} "
f"(~{round(sleep_seconds/3600, 2)} ч)." f"(~{round(sleep_seconds/3600, 2)} ч)."
) )
try: try:
time.sleep(sleep_seconds) time.sleep(sleep_seconds)
except KeyboardInterrupt: except KeyboardInterrupt:
logger.info("KeyboardInterrupt во время сна -> выходим.") logger.info("KeyboardInterrupt во время сна -> выходим")
stop_event.set()
break break
# Выход из while True → стопаем standings-поток
stop_event.set()
standings_thread.join()
logger.info("[MAIN] standings thread stopped, shutdown complete")
# идём на новую итерацию while True # идём на новую итерацию while True
# (новая сессия / новый stop_event создаются в начале цикла) # (новая сессия / новый stop_event создаются в начале цикла)

View File

@@ -439,13 +439,13 @@ cached_referee = st.session_state.get("referee")
league_tag = None league_tag = None
if isinstance(cached_game_online, dict): if isinstance(cached_game_online, dict):
league_tag = (cached_game_online.get("league") or {}).get("tag") league_tag = (cached_game_online.get("league") or {}).get("tag")
print(cached_game_online.get("comp").get("name"))
comp_name = (cached_game_online.get("comp") or {}).get("name").replace(" ", "_") comp_name = (cached_game_online.get("comp") or {}).get("name").replace(" ", "_")
if league_tag: if league_tag:
load_data_from_json(f"standings_{league_tag}_{comp_name}") load_data_from_json(f"standings_{league_tag}_{comp_name}")
cached_standings = ( cached_standings = (
st.session_state.get(f"standings_{league_tag}_{comp_name}") if league_tag else None st.session_state.get(f"standings_{league_tag}_{comp_name}") if league_tag else None
) )
load_data_from_json("scores_quarter") load_data_from_json("scores_quarter")
cached_scores_quarter = st.session_state.get("scores_quarter") cached_scores_quarter = st.session_state.get("scores_quarter")