From 77fe28567540636728574422eb51059b3b0e127d Mon Sep 17 00:00:00 2001 From: Masen Furer Date: Thu, 19 Dec 2024 03:16:41 -0800 Subject: [PATCH] Retry up to 100 times when proxying to frontend --- reflex/proxy.py | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/reflex/proxy.py b/reflex/proxy.py index 725d8a8be9..e0124a0fb3 100644 --- a/reflex/proxy.py +++ b/reflex/proxy.py @@ -2,12 +2,14 @@ from __future__ import annotations +import asyncio from contextlib import asynccontextmanager from typing import AsyncGenerator from urllib.parse import urlparse +import aiohttp from fastapi import FastAPI -from starlette.types import ASGIApp +from starlette.types import ASGIApp, Receive, Scope, Send from .config import get_config from .utils import console @@ -15,6 +17,7 @@ try: from asgiproxy.config import BaseURLProxyConfigMixin, ProxyConfig from asgiproxy.context import ProxyContext + from asgiproxy.proxies.http import proxy_http from asgiproxy.simple_proxy import make_simple_proxy_app except ImportError: @@ -32,6 +35,32 @@ async def proxy_middleware(*args, **kwargs) -> AsyncGenerator[None, None]: yield else: + async def proxy_http_with_retry( + *, + context: ProxyContext, + scope: Scope, + receive: Receive, + send: Send, + ) -> None: + """Proxy an HTTP request with retries. + + Args: + context: The proxy context. + scope: The ASGI scope. + receive: The receive channel. + send: The send channel. + """ + for _attempt in range(100): + try: + return await proxy_http( + context=context, scope=scope, receive=receive, send=send + ) + except aiohttp.client_exceptions.ClientError as err: # noqa: PERF203 + console.debug( + f"Retrying request {scope['path']} due to client error {err!r}." + ) + await asyncio.sleep(0.3) + def _get_proxy_app_with_context(frontend_host: str) -> tuple[ProxyContext, ASGIApp]: """Get the proxy app with the given frontend host. @@ -47,7 +76,9 @@ class LocalProxyConfig(BaseURLProxyConfigMixin, ProxyConfig): rewrite_host_header = urlparse(upstream_base_url).netloc proxy_context = ProxyContext(LocalProxyConfig()) - proxy_app = make_simple_proxy_app(proxy_context) + proxy_app = make_simple_proxy_app( + proxy_context, proxy_http_handler=proxy_http_with_retry + ) return proxy_context, proxy_app @asynccontextmanager