#!/usr/bin/env python3
"""三 case 串行驱动：每臂前 /free 清池（冒烟5连跑后池累积21.78GiB致OOM的教训）
OOM(error) 自动 /free + 重试一次。进度实时打点。
"""
import json, time, sys, urllib.request, urllib.error

BASE = 'http://127.0.0.1:8190'
CASES = ['case08', 'case07', 'case06']
JSONDIR = '/home/kai/shared/2026-10-17/h3lossless'

def http(path, payload=None, timeout=60):
    if payload is None:
        req = urllib.request.Request(BASE + path)
    else:
        req = urllib.request.Request(BASE + path, data=json.dumps(payload).encode(),
                                     headers={'Content-Type': 'application/json'})
    return json.loads(urllib.request.urlopen(req, timeout=timeout).read().decode())

def free_pool():
    try:
        http('/free', {'unload_models': True, 'free_memory': True})
        print(f'[{time.strftime("%H:%M:%S")}] /free OK', flush=True)
    except Exception as e:
        print(f'[{time.strftime("%H:%M:%S")}] /free err: {e}', flush=True)
    time.sleep(8)

def run_case(case, pid):
    api = json.load(open(f'{JSONDIR}/api_full_{case}_15s.json'))
    body = json.dumps({'prompt': api, 'client_id': 'h3lossless-serial'}).encode()
    req = urllib.request.Request(BASE + '/prompt', data=body,
                                 headers={'Content-Type': 'application/json'})
    resp = json.loads(urllib.request.urlopen(req, timeout=120).read().decode())
    new_pid = resp.get('prompt_id')
    print(f'[{time.strftime("%H:%M:%S")}] {case} submitted pid={new_pid}', flush=True)
    t0 = time.time()
    while time.time() - t0 < 90 * 60:
        time.sleep(30)
        try:
            h = http(f'/history/{new_pid}')
        except Exception:
            continue
        for k, v in h.items():
            st = v.get('status', {}).get('status_str', '')
            if st in ('success', 'error'):
                mins = (time.time() - t0) / 60
                print(f'[{time.strftime("%H:%M:%S")}] {case} FINISHED status={st} ({mins:.1f}min)', flush=True)
                return new_pid, st
    print(f'[{time.strftime("%H:%M:%S")}] {case} TIMEOUT 90min', flush=True)
    return new_pid, 'timeout'

results = {}
for case in CASES:
    free_pool()
    pid, st = run_case(case, None)
    if st == 'error':
        print(f'{case} OOM/错误 → /free 后重试一次', flush=True)
        free_pool()
        pid, st = run_case(case, None)
    results[case] = {'pid': pid, 'status': st}

print('=== SERIAL DRIVER DONE ===', flush=True)
for c, r in results.items():
    print(c, r['status'], r['pid'], flush=True)
