feat(ops): show step progress for reimport and sync jobs
A REIMPORT takes ~110 seconds and, until now, showed only a scrolling log — there was no way to tell "halfway" from "wedged", which mattered the day one actually did wedge. run_all.py emits "[paso i/N] name" before each step and the API derives progress from the job log. Emitting the marker from the Python rather than having the UI count STEPS itself means the step count is stated in exactly one place; adding a step cannot desync the display. Progress is derived, not stored, for the same reason: the log is already the record of what happened, and a separate counter could contradict it, which is precisely the confusion a progress display exists to remove. While RUNNING, step i is IN PROGRESS rather than finished, so only i-1 count as done. Counting i would show 100% while the final step was still working — and the final step (blob_extract) is the slowest, so the bar would sit at "100%" for the longest stretch of the job. BACKUP and RESTORE are a single mysqldump with no steps and deliberately render no bar; a fabricated percentage would be worse than none. The safety backup that precedes a REIMPORT is likewise named explicitly instead of showing 0%, which reads as stuck. Pinned by job-progress.spec.ts, including the literal line run_all.py emits, so a change to the Python format fails a test rather than silently blanking the panel. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+10
-3
@@ -78,7 +78,13 @@ SYNC_STEPS = [
|
||||
]
|
||||
|
||||
|
||||
def run(cmd: list[str]) -> None:
|
||||
def run(cmd: list[str], step: int | None = None, total: int | None = None) -> None:
|
||||
# The "[paso i/N] name" marker is a contract with the Operaciones screen,
|
||||
# which parses the last one to show progress. Emitting it here rather than
|
||||
# letting the UI count STEPS itself keeps the two from drifting when a step
|
||||
# is added — the number of steps is only ever stated in this file.
|
||||
if step is not None and total is not None:
|
||||
print(f"[paso {step}/{total}] {Path(cmd[1]).name}", flush=True)
|
||||
print("+ " + " ".join(cmd), flush=True)
|
||||
r = subprocess.run(cmd)
|
||||
if r.returncode:
|
||||
@@ -97,11 +103,12 @@ def main() -> None:
|
||||
if args.stage:
|
||||
run([PY, str(HERE / "load_staging.py"), "--output-dir", str(HERE / "output")])
|
||||
|
||||
for step in SYNC_STEPS if args.sync else STEPS:
|
||||
steps = SYNC_STEPS if args.sync else STEPS
|
||||
for i, step in enumerate(steps, start=1):
|
||||
cmd = [PY, str(HERE / step), "--env", args.env]
|
||||
if args.sync:
|
||||
cmd.append("--sync")
|
||||
run(cmd)
|
||||
run(cmd, step=i, total=len(steps))
|
||||
|
||||
print(f"\n✓ migration complete for env={args.env}")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user