swayfx-mosaic/tooling/probes/step20c-optimized-blur-edge/budget.py

69 lines
2.8 KiB
Python

"""Durable fail-closed reservations, bound to one LAB for this ticket.
WHY: a failed graphical attempt must never create capacity for a rerun.
CONTRACT: exclusive flock; fsync file then atomic replace and directory fsync.
INVARIANT: exact schema, bounded counters, no reset/refund or alternate LAB.
"""
import fcntl
import json
import os
import tempfile
from pathlib import Path
MODES = ('R0', 'R1', 'R2', 'R3')
KEYS = ('run', 'mutation', 'capture', 'cycle', 'calibration')
CAMPAIGN = 'SWAYFX_MOSAIC_STEP20C_OPTIMIZED_CACHE_FREEZE_AND_EDGE_CAUSALITY_GATE_V1'
DEFAULT = Path.home() / 'swayfx-mosaic-optimized-edge-v1-budget.json'
def limits(mode):
return dict(run=1, mutation=3, capture=12, cycle=1,
calibration=1 if mode in ('R2', 'R3') else 0)
def validate(state, lab):
if set(state) != {'campaign', 'lab', 'modes'} or state['campaign'] != CAMPAIGN or state['lab'] != lab:
raise RuntimeError('wrong campaign/LAB or corrupt schema')
if set(state['modes']) != set(MODES):
raise RuntimeError('corrupt modes')
for mode, counts in state['modes'].items():
if set(counts) != set(KEYS):
raise RuntimeError('corrupt resource schema')
for key, value in counts.items():
if type(value) is not int or not 0 <= value <= limits(mode)[key]:
raise RuntimeError('corrupt/out-of-bounds counter')
if any(counts[k] for k in KEYS if k != 'run') and counts['run'] != 1:
raise RuntimeError('action before run')
def reserve(lab, mode, resource, path=DEFAULT):
if mode not in MODES or resource not in KEYS:
raise ValueError('unknown reservation')
lab = str(Path(lab).resolve())
path = Path(path)
with path.with_suffix('.lock').open('a+') as lock:
fcntl.flock(lock, fcntl.LOCK_EX)
state = json.loads(path.read_text()) if path.exists() else {
'campaign': CAMPAIGN, 'lab': lab,
'modes': {m: {k: 0 for k in KEYS} for m in MODES}}
validate(state, lab)
counts = state['modes'][mode]
if resource != 'run' and counts['run'] != 1:
raise RuntimeError('reserve run first')
if counts[resource] >= limits(mode)[resource]:
raise RuntimeError('budget exhausted: ' + resource)
counts[resource] += 1
fd, tmp = tempfile.mkstemp(prefix=path.name + '.', dir=path.parent)
try:
with os.fdopen(fd, 'w') as out:
json.dump(state, out, sort_keys=True)
out.write('\n')
out.flush()
os.fsync(out.fileno())
os.replace(tmp, path)
directory = os.open(path.parent, os.O_DIRECTORY)
try:
os.fsync(directory)
finally:
os.close(directory)
finally:
if os.path.exists(tmp):
os.unlink(tmp)
return state