Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pass Error status in /dev/reload stream #8106

Merged
merged 11 commits into from
May 1, 2024
5 changes: 5 additions & 0 deletions .changeset/slow-bats-sniff.md
@@ -0,0 +1,5 @@
---
"gradio": patch
---

feat:Pass Error status in /dev/reload stream
3 changes: 0 additions & 3 deletions gradio/http_server.py
Expand Up @@ -137,15 +137,12 @@ def start_server(
)
reloader = None
if GRADIO_WATCH_DIRS:
change_event = threading.Event()
app.change_event = change_event
reloader = SourceFileReloader(
app=app,
watch_dirs=GRADIO_WATCH_DIRS,
watch_module_name=GRADIO_WATCH_MODULE_NAME,
demo_name=GRADIO_WATCH_DEMO_NAME,
stop_event=threading.Event(),
change_event=change_event,
demo_file=GRADIO_WATCH_DEMO_PATH,
)
server = Server(config=config, reloader=reloader)
Expand Down
14 changes: 8 additions & 6 deletions gradio/routes.py
Expand Up @@ -19,7 +19,6 @@
import os
import posixpath
import secrets
import threading
import time
import traceback
from pathlib import Path
Expand All @@ -31,6 +30,7 @@
Callable,
Dict,
List,
Literal,
Optional,
Type,
Union,
Expand Down Expand Up @@ -173,7 +173,8 @@ def __init__(
self.queue_token = secrets.token_urlsafe(32)
self.startup_events_triggered = False
self.uploaded_file_dir = get_upload_folder()
self.change_event: None | threading.Event = None
self.change_count: int = 0
self.change_type: Literal["reload", "error"] | None = None
self._asyncio_tasks: list[asyncio.Task] = []
self.auth_dependency = auth_dependency
self.api_info = None
Expand Down Expand Up @@ -284,18 +285,19 @@ async def reload_checker(request: fastapi.Request):
heartbeat_rate = 15
check_rate = 0.05
last_heartbeat = time.perf_counter()
current_count = app.change_count

while True:
if await request.is_disconnected():
return

if app.change_event and app.change_event.is_set():
app.change_event.clear()
yield """event: reload\ndata: {}\n\n"""
if app.change_count != current_count:
current_count = app.change_count
yield f"""event: {app.change_type}\ndata: {{}}\n\n"""

await asyncio.sleep(check_rate)
if time.perf_counter() - last_heartbeat > heartbeat_rate:
yield """event: heartbeat\ndata: {}\n\n"""
yield """event: heartbeat\ndata: {}\n\n\n\n"""
last_heartbeat = time.time()

return StreamingResponse(
Expand Down
11 changes: 6 additions & 5 deletions gradio/utils.py
Expand Up @@ -38,6 +38,7 @@
Generic,
Iterable,
Iterator,
Literal,
Optional,
TypeVar,
)
Expand Down Expand Up @@ -123,15 +124,13 @@ def __init__(
watch_module_name: str,
demo_file: str,
stop_event: threading.Event,
change_event: threading.Event,
demo_name: str = "demo",
) -> None:
super().__init__()
self.app = app
self.watch_dirs = watch_dirs
self.watch_module_name = watch_module_name
self.stop_event = stop_event
self.change_event = change_event
self.demo_name = demo_name
self.demo_file = Path(demo_file)

Expand All @@ -145,16 +144,17 @@ def should_watch(self) -> bool:
def stop(self) -> None:
self.stop_event.set()

def alert_change(self):
self.change_event.set()
def alert_change(self, change_type: Literal["reload", "error"] = "reload"):
self.app.change_type = change_type
self.app.change_count += 1

def swap_blocks(self, demo: Blocks):
old_blocks = self.running_app.blocks
super().swap_blocks(demo)
if old_blocks:
reassign_keys(old_blocks, demo)
demo.config = demo.get_config_file()
self.alert_change()
self.alert_change("reload")


NO_RELOAD = True
Expand Down Expand Up @@ -281,6 +281,7 @@ def iter_py_files() -> Iterator[Path]:
)
traceback.print_exc()
mtimes = {}
reloader.alert_change("error")
continue
demo = getattr(module, reloader.demo_name)
reloader.swap_blocks(demo)
Expand Down