"""Dedicated Docker worker: database-backed queue, serialized claim, retry + restart recovery.""" import json import os import signal import time from datetime import datetime, timedelta, timezone from . import db, enterprise, builder running=True def stop(*_): global running running=False def claim(): with db.connect() as c: c.execute('BEGIN IMMEDIATE') job=c.execute("""SELECT id FROM build_jobs WHERE state='queued' AND (retry_at IS NULL OR retry_at<=?) ORDER BY created_at,id LIMIT 1""",(db.now(),)).fetchone() if not job:return None c.execute("UPDATE build_jobs SET state='running',attempts=attempts+1,started_at=?,retry_at=NULL WHERE id=?",(db.now(),job['id'])) return dict(c.execute('SELECT * FROM build_jobs WHERE id=?',(job['id'],)).fetchone()) def run_once(): job=claim() if job is None:return None try: if job['kind']=='build': result=builder.build(job['site_id'],False) else:raise ValueError('Unsupported job') db.execute("UPDATE build_jobs SET state='done',result_json=?,finished_at=? WHERE id=?", (json.dumps(result,ensure_ascii=False),db.now(),job['id'])) except Exception as exc: maximum=max(1,int(os.getenv('SITEFORGE_JOB_MAX_ATTEMPTS','3'))) if job['attempts']