cezar-hapiko commited on
Commit
3cbe3bf
·
1 Parent(s): 4dba567

Heartbeat progress during long subprocess runs (keeps SSE stream alive)

Browse files
Files changed (1) hide show
  1. app.py +34 -4
app.py CHANGED
@@ -18,6 +18,8 @@ import os
18
  import shutil
19
  import subprocess
20
  import sys
 
 
21
  import uuid
22
  from dataclasses import dataclass
23
  from pathlib import Path
@@ -108,6 +110,10 @@ def _write_input_image(run_dir: Path, image: Image.Image) -> Path:
108
 
109
  def _run_subprocess(cmd: list[str], *, cwd: Path, progress: gr.Progress,
110
  progress_fraction: float, phase_label: str) -> None:
 
 
 
 
111
  progress(progress_fraction, desc=phase_label)
112
  log.info("[%s] %s (cwd=%s)", phase_label, " ".join(cmd), cwd)
113
  env = os.environ.copy()
@@ -122,10 +128,34 @@ def _run_subprocess(cmd: list[str], *, cwd: Path, progress: gr.Progress,
122
  bufsize=1,
123
  )
124
  assert proc.stdout is not None
125
- for line in proc.stdout:
126
- sys.stdout.write(line)
127
- sys.stdout.flush()
128
- rc = proc.wait()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
129
  if rc != 0:
130
  raise gr.Error(f"{phase_label} failed with exit code {rc}. Check Space logs for details.")
131
 
 
18
  import shutil
19
  import subprocess
20
  import sys
21
+ import threading
22
+ import time
23
  import uuid
24
  from dataclasses import dataclass
25
  from pathlib import Path
 
110
 
111
  def _run_subprocess(cmd: list[str], *, cwd: Path, progress: gr.Progress,
112
  progress_fraction: float, phase_label: str) -> None:
113
+ """Invoke a long-running Lyra-2 subprocess while emitting periodic progress
114
+ updates. Heartbeats matter: HF's SSE proxy drops connections when no events
115
+ flow for ~60s, and Lyra-2's model-load phase can be silent for 2+ min.
116
+ """
117
  progress(progress_fraction, desc=phase_label)
118
  log.info("[%s] %s (cwd=%s)", phase_label, " ".join(cmd), cwd)
119
  env = os.environ.copy()
 
128
  bufsize=1,
129
  )
130
  assert proc.stdout is not None
131
+
132
+ # Background heartbeat to keep the Gradio SSE stream alive during long
133
+ # silent phases (model load + diffusion steps don't flush to our stdout).
134
+ stop_heartbeat = threading.Event()
135
+ t_start = time.monotonic()
136
+
137
+ def _heartbeat() -> None:
138
+ while not stop_heartbeat.wait(20.0):
139
+ elapsed = time.monotonic() - t_start
140
+ try:
141
+ progress(progress_fraction, desc=f"{phase_label} — {elapsed:.0f}s elapsed")
142
+ except Exception:
143
+ # Progress updates can raise if the client disconnects; don't
144
+ # kill the subprocess just because the browser went away.
145
+ pass
146
+
147
+ hb = threading.Thread(target=_heartbeat, daemon=True)
148
+ hb.start()
149
+
150
+ try:
151
+ for line in proc.stdout:
152
+ sys.stdout.write(line)
153
+ sys.stdout.flush()
154
+ rc = proc.wait()
155
+ finally:
156
+ stop_heartbeat.set()
157
+ hb.join(timeout=1.0)
158
+
159
  if rc != 0:
160
  raise gr.Error(f"{phase_label} failed with exit code {rc}. Check Space logs for details.")
161