Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion demo/unload_event_test/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,4 @@ def unload_fn():
demo.load(lambda: log_file.write_text(""))

if __name__ == "__main__":
demo.launch()
demo.launch(heartbeat_interval=0.25)
6 changes: 6 additions & 0 deletions gradio/blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ def __init__(
self.is_rendered: bool = False
self._constructor_args: list[dict]
self.state_session_capacity = 10000
self.heartbeat_interval = 15.0
self.temp_files: set[str] = set()
self.GRADIO_CACHE = get_upload_folder()
self.key = key
Expand Down Expand Up @@ -2532,6 +2533,7 @@ def launch(
root_path: str | None = None,
app_kwargs: dict[str, Any] | None = None,
state_session_capacity: int = 10000,
heartbeat_interval: float = 15.0,
share_server_address: str | None = None,
share_server_protocol: Literal["http", "https"] | None = None,
share_server_tls_certificate: str | None = None,
Expand Down Expand Up @@ -2583,6 +2585,7 @@ def launch(
root_path: The root path (or "mount point") of the application, if it's not served from the root ("/") of the domain. Often used when the application is behind a reverse proxy that forwards requests to the application. For example, if the application is served at "https://example.com/myapp", the `root_path` should be set to "/myapp". A full URL beginning with http:// or https:// can be provided, which will be used as the root path in its entirety. Can be set by environment variable GRADIO_ROOT_PATH. Defaults to "".
app_kwargs: Additional keyword arguments to pass to the underlying FastAPI app as a dictionary of parameter keys and argument values. For example, `{"docs_url": "/docs"}`
state_session_capacity: The maximum number of sessions whose information to store in memory. If the number of sessions exceeds this number, the oldest sessions will be removed. Reduce capacity to reduce memory usage when using gradio.State or returning updated components from functions. Defaults to 10000.
heartbeat_interval: The number of seconds to wait between heartbeat messages on the session heartbeat stream. Lower values allow unload events to fire sooner after a client disconnects. Defaults to 15.
share_server_address: Use this to specify a custom FRP server and port for sharing Gradio apps (only applies if share=True). If not provided, will use the default FRP server at https://gradio.live. See https://github.com/huggingface/frp for more information.
share_server_protocol: Use this to specify the protocol to use for the share links. Defaults to "https", unless a custom share_server_address is provided, in which case it defaults to "http". If you are using a custom share_server_address and want to use https, you must set this to "https".
share_server_tls_certificate: The path to a TLS certificate file to use when connecting to a custom share server. This parameter is not used with the default FRP server at https://gradio.live. Otherwise, you must provide a valid TLS certificate file (e.g. a "cert.pem") relative to the current working directory, or the connection will not use TLS encryption, which is insecure.
Expand Down Expand Up @@ -2676,6 +2679,9 @@ def reverse(text):
self.favicon_path = favicon_path
self.ssl_verify = ssl_verify
self.state_session_capacity = state_session_capacity
if heartbeat_interval <= 0:
raise ValueError("`heartbeat_interval` must be greater than 0.")
self.heartbeat_interval = heartbeat_interval
if root_path is None:
self.root_path = os.environ.get("GRADIO_ROOT_PATH", "")
else:
Expand Down
7 changes: 6 additions & 1 deletion gradio/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -1375,7 +1375,7 @@ def heartbeat(
"""Clients make a persistent connection to this endpoint to keep the session alive.
When the client disconnects, the session state is deleted.
"""
heartbeat_rate = 0.25 if os.getenv("GRADIO_IS_E2E_TEST", None) else 15
heartbeat_rate = app.get_blocks().heartbeat_interval

async def iterator():
stop_stream_task = asyncio.create_task(app.stop_event.wait())
Expand Down Expand Up @@ -2682,6 +2682,7 @@ def mount_gradio_app(
root_path: str | None = None,
allowed_paths: list[str] | None = None,
blocked_paths: list[str] | None = None,
heartbeat_interval: float = 15.0,
favicon_path: str | None = None,
show_error: bool = True,
max_file_size: str | int | None = None,
Expand Down Expand Up @@ -2714,6 +2715,7 @@ def mount_gradio_app(
root_path: The subpath corresponding to the public deployment of this FastAPI application. For example, if the application is served at "https://example.com/myapp", the `root_path` should be set to "/myapp". A full URL beginning with http:// or https:// can be provided, which will be used in its entirety. Normally, this does not need to provided (even if you are using a custom `path`). However, if you are serving the FastAPI app behind a proxy, the proxy may not provide the full path to the Gradio app in the request headers. In which case, you can provide the root path here.
allowed_paths: List of complete filepaths or parent directories that this gradio app is allowed to serve. Must be absolute paths. Warning: if you provide directories, any files in these directories or their subdirectories are accessible to all users of your app.
blocked_paths: List of complete filepaths or parent directories that this gradio app is not allowed to serve (i.e. users of your app are not allowed to access). Must be absolute paths. Warning: takes precedence over `allowed_paths` and all other directories exposed by Gradio by default.
heartbeat_interval: The number of seconds to wait between heartbeat messages on the session heartbeat stream. Lower values allow unload events to fire sooner after a client disconnects. Defaults to 15.
favicon_path: If a path to a file (.png, .gif, or .ico) is provided, it will be used as the favicon for this gradio app's page.
show_error: If True, any errors in the gradio app will be displayed in an alert modal and printed in the browser console log. Otherwise, errors will only be visible in the terminal session running the Gradio app.
max_file_size: The maximum file size in bytes that can be uploaded. Can be a string of the form "<value><unit>", where value is any positive integer and unit is one of "b", "kb", "mb", "gb", "tb". If None, no limit is set.
Expand Down Expand Up @@ -2753,6 +2755,9 @@ def read_main():
blocks.max_file_size = utils._parse_file_size(max_file_size)
blocks.config = blocks.get_config_file()
blocks.validate_queue_settings()
if heartbeat_interval <= 0:
raise ValueError("`heartbeat_interval` must be greater than 0.")
blocks.heartbeat_interval = heartbeat_interval
blocks.custom_mount_path = path
blocks.server_port = server_port
blocks.server_name = server_name
Expand Down
2 changes: 2 additions & 0 deletions gradio/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ def launch(
root_path: str | None = None,
app_kwargs: dict[str, Any] | None = None,
state_session_capacity: int = 10000,
heartbeat_interval: float = 15.0,
share_server_address: str | None = None,
share_server_protocol: Literal["http", "https"] | None = None,
share_server_tls_certificate: str | None = None,
Expand Down Expand Up @@ -311,6 +312,7 @@ def launch(
root_path=root_path,
app_kwargs=app_kwargs,
state_session_capacity=state_session_capacity,
heartbeat_interval=heartbeat_interval,
share_server_address=share_server_address,
share_server_protocol=share_server_protocol,
share_server_tls_certificate=share_server_tls_certificate,
Expand Down
13 changes: 13 additions & 0 deletions test/test_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,19 @@ def test_mount_gradio_app_with_app_kwargs(self):
with TestClient(app) as client:
assert client.get("/echo/docs-custom").is_success

def test_mount_gradio_app_sets_heartbeat_interval(self):
app = FastAPI()
demo = gr.Interface(lambda s: s, "textbox", "textbox")

gr.mount_gradio_app(
app,
demo,
path="/gradio",
heartbeat_interval=0.5,
)

assert demo.heartbeat_interval == 0.5

def test_mount_gradio_app_with_auth_and_params(self):
app = FastAPI()
demo = gr.Interface(lambda s: f"You said {s}!", "textbox", "textbox").queue()
Expand Down
22 changes: 22 additions & 0 deletions test/test_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,28 @@ def named_echo(msg: str) -> str:
finally:
gr.close_all()

def test_server_launch_sets_heartbeat_interval(self, monkeypatch):
server = gr.Server()

@server.api(name="echo")
def echo(x: str) -> str:
return x

captured = {}

def fake_launch(self, **kwargs):
captured.update(kwargs)
return None, None, None

monkeypatch.setattr(gr.Blocks, "launch", fake_launch)

server.launch(
prevent_thread_lock=True,
_frontend=False,
heartbeat_interval=0.5,
)
assert captured["heartbeat_interval"] == 0.5


def test_server_launch_args_match_blocks_launch():
launch_params = inspect.signature(gr.Blocks.launch).parameters
Expand Down
Loading