#!/usr/bin/env python3
"""W2 定妆批 · 租约接力守望器 (Pattern 12 relay).

轮询 KAP gpu-queue：当 GPU1 或 GPU2 的 kgr_veda_v35 租约释放（holders 值变 null 且
显存实测 < 20G）→ 立即发车 run_w2_lockup.py。发车前再验一次 8188 ready。
"""
import json, subprocess, time, os, sys

LOG = "/home/kai/shared/virtual-idol/week1/W2_lockup/relay.log"
def log(m):
    line = f"[{time.strftime('%H:%M:%S')}] {m}"
    print(line, flush=True)
    with open(LOG, "a") as f:
        f.write(line + "\n")

def queue_state():
    try:
        out = subprocess.run(["curl","-s","-m","8","http://127.0.0.1:10588/api/production/gpu-queue"],
                             capture_output=True, text=True, timeout=15).stdout
        return json.loads(out).get("data", {})
    except Exception as e:
        log(f"queue poll err: {e}")
        return {}

def vram_free(gpu):
    try:
        out = subprocess.run(["nvidia-smi","--query-gpu=memory.used","--format=csv,noheader,nounits","-i",str(gpu)],
                             capture_output=True, text=True, timeout=10).stdout.strip()
        return 24576 - int(out)
    except Exception:
        return 0

log("relay 启动：等待 kgr_veda_v35 退卡（lease TTL ~01:43 或提前 release）")
deadline = time.time() + 4*3600  # 4h 硬上限
while time.time() < deadline:
    q = queue_state()
    holders = q.get("holders", {})
    # 两卡 holders 都为 null（无租约）才可发车；再验显存
    g1_free_lease = holders.get("1") in (None, "null")
    g2_free_lease = holders.get("2") in (None, "null")
    f1, f2 = vram_free(1), vram_free(2)
    log(f"holders={holders} GPU1空闲={f1}MiB GPU2空闲={f2}MiB")
    if (g1_free_lease and f1 > 12000) or (g2_free_lease and f2 > 12000):
        log(f"✅ 窗口开（GPU1 free={f1}, GPU2 free={f2}）→ 发车 run_w2_lockup.py")
        r = subprocess.run(["/data/workspace/hermes-agent/.venv/bin/python",
                            "/home/kai/shared/virtual-idol/week1/W2_lockup/run_w2_lockup.py"],
                           capture_output=True, text=True, timeout=5400)
        tail = (r.stdout or "")[-800:]
        log(f"批次结束 exit={r.returncode}\n{tail}")
        sys.exit(0 if "W2_LOCKUP_DONE" in (r.stdout or "") else 2)
    time.sleep(300)
log("⏰ 4h 等窗超时，relay 退出")
sys.exit(3)
