Spaces:
Sleeping
Sleeping
| """ | |
| WSGI entry point for Gunicorn production server. | |
| Usage: gunicorn -w 8 -b 0.0.0.0:5000 wsgi:app | |
| Only one worker starts the scheduler (file-lock based). | |
| """ | |
| import os | |
| import fcntl | |
| import time | |
| from app import app, init_db, crawl_update_all, is_match_day, db_health_check | |
| # Initialize database on first import | |
| init_db() | |
| # File-lock based singleton scheduler: only one gunicorn worker wins the race | |
| LOCK_FILE = "/tmp/short_track_scheduler.lock" | |
| scheduler_started = False | |
| try: | |
| lock_fd = os.open(LOCK_FILE, os.O_CREAT | os.O_WRONLY, 0o644) | |
| try: | |
| fcntl.flock(lock_fd, fcntl.LOCK_EX | fcntl.LOCK_NB) | |
| # We got the lock — start scheduler (only one worker will reach here) | |
| from apscheduler.schedulers.background import BackgroundScheduler | |
| _last_non_match_day_run = [0] | |
| def smart_crawl_update(): | |
| """智能爬取:比赛日5分钟一次,非比赛日7天一次""" | |
| try: | |
| match_day = is_match_day() | |
| except Exception: | |
| match_day = False | |
| if match_day: | |
| print("比赛日 - 执行数据更新") | |
| crawl_update_all() | |
| else: | |
| now = time.time() | |
| SEVEN_DAYS = 7 * 24 * 3600 | |
| if now - _last_non_match_day_run[0] >= SEVEN_DAYS: | |
| print("非比赛日 - 7天兜底更新") | |
| crawl_update_all() | |
| _last_non_match_day_run[0] = now | |
| scheduler = BackgroundScheduler() | |
| scheduler.add_job( | |
| func=smart_crawl_update, | |
| trigger="interval", | |
| minutes=5, | |
| id="auto_update", | |
| name="智能自动更新(比赛日5分钟,非比赛日7天)", | |
| replace_existing=True, | |
| max_instances=1, | |
| coalesce=True, | |
| misfire_grace_time=120, | |
| ) | |
| scheduler.add_job( | |
| func=db_health_check, | |
| trigger="interval", | |
| minutes=5, | |
| id="db_health_check", | |
| name="DB完整性检查+自动恢复", | |
| replace_existing=True, | |
| max_instances=1, | |
| coalesce=True, | |
| misfire_grace_time=120, | |
| ) | |
| scheduler.start() | |
| scheduler_started = True | |
| print("已启动智能定时更新:比赛日5分钟一次,非比赛日7天一次") | |
| print("已启动 DB 完整性检查:每5分钟一次") | |
| # 启动时立即执行一次健康检查 | |
| db_health_check() | |
| except BlockingIOError: | |
| # Another worker already holds the lock — skip | |
| print("调度器已在其他 worker 运行,跳过") | |
| finally: | |
| # Don't close lock_fd — we need to hold it for the process lifetime | |
| pass | |
| if __name__ == "__main__": | |
| app.run() | |