from flask import Blueprint, Response, current_app, request from sqlalchemy import select from l4d2web.auth import current_user, require_login from l4d2web.db import session_scope from l4d2web.models import Job, JobLog bp = Blueprint("job", __name__) @bp.get("/jobs//stream") @require_login def stream_job(job_id: int) -> Response: user = current_user() assert user is not None last_seq = int(request.args.get("last_seq", "0")) limit = int(current_app.config["JOB_LOG_REPLAY_LIMIT"]) with session_scope() as db: job = db.scalar(select(Job).where(Job.id == job_id, Job.user_id == user.id)) if job is None: return Response(status=404) def generate(): with session_scope() as db: rows = db.scalars( select(JobLog) .where(JobLog.job_id == job_id, JobLog.seq > last_seq) .order_by(JobLog.seq) .limit(limit) ).all() for row in rows: yield f"id: {row.seq}\n" yield f"event: {row.stream}\n" yield f"data: {row.line}\n\n" return Response(generate(), mimetype="text/event-stream")