Files
gitrusprusandCursor 1492576fd9 Add Telegram listener, scheduler, and extended parsers admin UI.
Introduce background scheduling and migrations for analytics ingest, expand parser management and map toolbar UX, and ignore local data/session files from version control.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-02 20:47:56 +03:00

59 lines
1.6 KiB
Python

import logging
import threading
import time
from datetime import datetime, timezone
from ..database import SessionLocal
from ..models import ParseJob
from .jobs import enqueue_job
logger = logging.getLogger(__name__)
TICK_SECONDS = 30
RECURRING_STATUSES = ("completed", "failed")
def run_scheduler_tick() -> None:
db = SessionLocal()
try:
now = datetime.now(timezone.utc)
jobs = (
db.query(ParseJob)
.filter(
ParseJob.is_active.is_(True),
ParseJob.interval_seconds > 0,
ParseJob.status.in_(RECURRING_STATUSES),
)
.all()
)
for job in jobs:
if job.last_run_at is None:
continue
elapsed = (now - job.last_run_at).total_seconds()
if elapsed < job.interval_seconds:
continue
job.status = "queued"
job.last_error = None
db.commit()
enqueue_job(job.id, job.source_type, job.source_config)
logger.info("Re-queued recurring job %s (interval %ss)", job.id, job.interval_seconds)
except Exception:
logger.exception("Scheduler tick failed")
db.rollback()
finally:
db.close()
def _scheduler_loop(stop_event: threading.Event) -> None:
while not stop_event.wait(TICK_SECONDS):
run_scheduler_tick()
def start_scheduler() -> threading.Event:
stop_event = threading.Event()
thread = threading.Thread(target=_scheduler_loop, args=(stop_event,), daemon=True)
thread.start()
logger.info("Parse job scheduler started (tick every %ss)", TICK_SECONDS)
return stop_event