Files
dj/integration-work/historical_cleanup_install_history_guard.py
T
2026-11-13 11:46:25 +08:00

53 lines
3.9 KiB
Python

"""Prevent verified deleted historical tasks from resurfacing via signed restore snapshots."""
import contextlib,hashlib,importlib.util,json,pathlib,shutil,sqlite3,subprocess,time
ROOT=pathlib.Path('/home/ps/huobao-video-cleanup');OUT=ROOT/'historical-20261112'
cfg=json.loads((ROOT/'config.json').read_text());approved=json.loads((ROOT/'historical-approved.json').read_text())
assert (OUT/'enqueue-done.json').exists()
candidate=ROOT/'comfy_video_cleanup.candidate.py';compile(candidate.read_text(),str(candidate),'exec')
assert 'def reconcile_cleaned_history(' in candidate.read_text()
bridges={b['name']:b for b in cfg['bridges']};byworker={}
for a in approved:byworker.setdefault(a['worker'],[]).append(a)
workers=json.loads(subprocess.check_output(['docker','inspect',*byworker],text=True))
added=[]
for b in bridges.values():
backup=OUT/(b['name']+'-before-history-guard.sqlite3')
if not backup.exists():
with contextlib.closing(sqlite3.connect('file:'+b['database']+'?mode=ro',uri=True)) as source,contextlib.closing(sqlite3.connect(backup)) as target:source.backup(target)
for i in workers:
env=dict(x.split('=',1) for x in i['Config'].get('Env',[]) if '=' in x);dest=env.get('H3_HISTORY_SNAPSHOT')
if not dest:continue
mount=next((m for m in i['Mounts'] if m['Destination']==dest),None)
if not mount:continue
snapshot=json.loads(pathlib.Path(mount['Source']).read_text())
for a in byworker[i['Name'].lstrip('/')]:
history=snapshot.get('history',{}).get(a['manifest']['prompt'])
if not history:continue
locations=[]
for node in (history.get('outputs') or {}).values():
for field in ('images','gifs','audio'):
for loc in node.get(field) or []:
if isinstance(loc,dict):locations.append({k:loc.get(k,'output' if k=='type' else '') for k in ('filename','subfolder','type')})
assert a['manifest']['locator'] in locations,'Snapshot video locator does not match verified deleted source'
h=hashlib.sha256(json.dumps(history,sort_keys=True,separators=(',',':'),ensure_ascii=False).encode()).hexdigest()
with contextlib.closing(sqlite3.connect(bridges[a['bridge']]['database'],timeout=15)) as db,db:
db.row_factory=sqlite3.Row;row=db.execute('select status,manifest from video_cleanup_acks where id=?',(a['id'],)).fetchone()
assert row and row['status']=='cleaned','Wait for exact video cleanup'
manifest=json.loads(row['manifest']);assert manifest['fileReceipt']==a['fileReceipt']
manifest['restoredHistoryHashes']=sorted(set(manifest.get('restoredHistoryHashes',[])+[h]))
db.execute('update video_cleanup_acks set manifest=? where id=?',(json.dumps(manifest),a['id']))
added.append(a['task'])
# All approved deletions must finish before restarting only the private cleanup helper.
for a in approved:
with contextlib.closing(sqlite3.connect('file:'+bridges[a['bridge']]['database']+'?mode=ro',uri=True)) as db:
assert db.execute('select status from video_cleanup_acks where id=?',(a['id'],)).fetchone()[0]=='cleaned'
old=OUT/'comfy_video_cleanup-before-history-guard.py'
if not old.exists():shutil.copy2(ROOT/'comfy_video_cleanup.py',old)
shutil.copy2(candidate,ROOT/'comfy_video_cleanup.py')
subprocess.run(['systemctl','--user','restart','huobao-video-cleanup.service'],check=True,capture_output=True)
assert subprocess.check_output(['systemctl','--user','is-active','huobao-video-cleanup.service'],text=True).strip()=='active'
before=json.loads((OUT/'services-before.json').read_text())
after={i['Name']:{'id':i['Id'],'started':i['State']['StartedAt']} for i in json.loads(subprocess.check_output(['docker','inspect',*[x.lstrip('/') for x in before]],text=True))}
assert before==after,'Model service identity changed'
report={'historyGuardInstalled':True,'snapshotTasksProtected':added,'pollSeconds':60,'modelServicesUnchanged':True,'snapshotFilesUnchanged':True,'codeSha256':hashlib.sha256((ROOT/'comfy_video_cleanup.py').read_bytes()).hexdigest()}
(OUT/'history-guard-report.json').write_text(json.dumps(report,indent=2));print(json.dumps(report))