fix port handling (#4773)
* handle port better * setting port via envvar is possible again * change default deploy_url and api_url * fix for review * update docstring * type new envvar as optional
This commit is contained in:
parent
977e1dcb67
commit
dd5b817f0f
@ -562,6 +562,12 @@ class EnvironmentVariables:
|
|||||||
# Whether to run the frontend only. Exclusive with REFLEX_BACKEND_ONLY.
|
# Whether to run the frontend only. Exclusive with REFLEX_BACKEND_ONLY.
|
||||||
REFLEX_FRONTEND_ONLY: EnvVar[bool] = env_var(False)
|
REFLEX_FRONTEND_ONLY: EnvVar[bool] = env_var(False)
|
||||||
|
|
||||||
|
# The port to run the frontend on.
|
||||||
|
REFLEX_FRONTEND_PORT: EnvVar[int | None] = env_var(None)
|
||||||
|
|
||||||
|
# The port to run the backend on.
|
||||||
|
REFLEX_BACKEND_PORT: EnvVar[int | None] = env_var(None)
|
||||||
|
|
||||||
# Reflex internal env to reload the config.
|
# Reflex internal env to reload the config.
|
||||||
RELOAD_CONFIG: EnvVar[bool] = env_var(False, internal=True)
|
RELOAD_CONFIG: EnvVar[bool] = env_var(False, internal=True)
|
||||||
|
|
||||||
@ -640,19 +646,21 @@ class Config(Base):
|
|||||||
loglevel: constants.LogLevel = constants.LogLevel.DEFAULT
|
loglevel: constants.LogLevel = constants.LogLevel.DEFAULT
|
||||||
|
|
||||||
# The port to run the frontend on. NOTE: When running in dev mode, the next available port will be used if this is taken.
|
# The port to run the frontend on. NOTE: When running in dev mode, the next available port will be used if this is taken.
|
||||||
frontend_port: int = constants.DefaultPorts.FRONTEND_PORT
|
frontend_port: int | None = None
|
||||||
|
|
||||||
# The path to run the frontend on. For example, "/app" will run the frontend on http://localhost:3000/app
|
# The path to run the frontend on. For example, "/app" will run the frontend on http://localhost:3000/app
|
||||||
frontend_path: str = ""
|
frontend_path: str = ""
|
||||||
|
|
||||||
# The port to run the backend on. NOTE: When running in dev mode, the next available port will be used if this is taken.
|
# The port to run the backend on. NOTE: When running in dev mode, the next available port will be used if this is taken.
|
||||||
backend_port: int = constants.DefaultPorts.BACKEND_PORT
|
backend_port: int | None = None
|
||||||
|
|
||||||
# The backend url the frontend will connect to. This must be updated if the backend is hosted elsewhere, or in production.
|
# The backend url the frontend will connect to. This must be updated if the backend is hosted elsewhere, or in production.
|
||||||
api_url: str = f"http://localhost:{backend_port}"
|
api_url: str = f"http://localhost:{constants.DefaultPorts.BACKEND_PORT}"
|
||||||
|
|
||||||
# The url the frontend will be hosted on.
|
# The url the frontend will be hosted on.
|
||||||
deploy_url: Optional[str] = f"http://localhost:{frontend_port}"
|
deploy_url: Optional[str] = (
|
||||||
|
f"http://localhost:{constants.DefaultPorts.FRONTEND_PORT}"
|
||||||
|
)
|
||||||
|
|
||||||
# The url the backend will be hosted on.
|
# The url the backend will be hosted on.
|
||||||
backend_host: str = "0.0.0.0"
|
backend_host: str = "0.0.0.0"
|
||||||
|
@ -127,8 +127,8 @@ def _run(
|
|||||||
env: constants.Env = constants.Env.DEV,
|
env: constants.Env = constants.Env.DEV,
|
||||||
frontend: bool = True,
|
frontend: bool = True,
|
||||||
backend: bool = True,
|
backend: bool = True,
|
||||||
frontend_port: int = config.frontend_port,
|
frontend_port: int | None = None,
|
||||||
backend_port: int = config.backend_port,
|
backend_port: int | None = None,
|
||||||
backend_host: str = config.backend_host,
|
backend_host: str = config.backend_host,
|
||||||
loglevel: constants.LogLevel = config.loglevel,
|
loglevel: constants.LogLevel = config.loglevel,
|
||||||
):
|
):
|
||||||
@ -158,17 +158,28 @@ def _run(
|
|||||||
|
|
||||||
# Find the next available open port if applicable.
|
# Find the next available open port if applicable.
|
||||||
if frontend:
|
if frontend:
|
||||||
|
auto_increment_frontend = not bool(frontend_port or config.frontend_port)
|
||||||
frontend_port = processes.handle_port(
|
frontend_port = processes.handle_port(
|
||||||
"frontend",
|
"frontend",
|
||||||
frontend_port,
|
(
|
||||||
constants.DefaultPorts.FRONTEND_PORT,
|
frontend_port
|
||||||
|
or config.frontend_port
|
||||||
|
or constants.DefaultPorts.FRONTEND_PORT
|
||||||
|
),
|
||||||
|
auto_increment=auto_increment_frontend,
|
||||||
)
|
)
|
||||||
|
|
||||||
if backend:
|
if backend:
|
||||||
|
auto_increment_backend = not bool(backend_port or config.backend_port)
|
||||||
|
|
||||||
backend_port = processes.handle_port(
|
backend_port = processes.handle_port(
|
||||||
"backend",
|
"backend",
|
||||||
backend_port,
|
(
|
||||||
constants.DefaultPorts.BACKEND_PORT,
|
backend_port
|
||||||
|
or config.backend_port
|
||||||
|
or constants.DefaultPorts.BACKEND_PORT
|
||||||
|
),
|
||||||
|
auto_increment=auto_increment_backend,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Apply the new ports to the config.
|
# Apply the new ports to the config.
|
||||||
@ -246,7 +257,7 @@ def _run(
|
|||||||
# Start the frontend and backend.
|
# Start the frontend and backend.
|
||||||
with processes.run_concurrently_context(*commands):
|
with processes.run_concurrently_context(*commands):
|
||||||
# In dev mode, run the backend on the main thread.
|
# In dev mode, run the backend on the main thread.
|
||||||
if backend and env == constants.Env.DEV:
|
if backend and backend_port and env == constants.Env.DEV:
|
||||||
backend_cmd(
|
backend_cmd(
|
||||||
backend_host, int(backend_port), loglevel.subprocess_level(), frontend
|
backend_host, int(backend_port), loglevel.subprocess_level(), frontend
|
||||||
)
|
)
|
||||||
@ -275,10 +286,14 @@ def run(
|
|||||||
envvar=environment.REFLEX_BACKEND_ONLY.name,
|
envvar=environment.REFLEX_BACKEND_ONLY.name,
|
||||||
),
|
),
|
||||||
frontend_port: int = typer.Option(
|
frontend_port: int = typer.Option(
|
||||||
config.frontend_port, help="Specify a different frontend port."
|
config.frontend_port,
|
||||||
|
help="Specify a different frontend port.",
|
||||||
|
envvar=environment.REFLEX_FRONTEND_PORT.name,
|
||||||
),
|
),
|
||||||
backend_port: int = typer.Option(
|
backend_port: int = typer.Option(
|
||||||
config.backend_port, help="Specify a different backend port."
|
config.backend_port,
|
||||||
|
help="Specify a different backend port.",
|
||||||
|
envvar=environment.REFLEX_BACKEND_PORT.name,
|
||||||
),
|
),
|
||||||
backend_host: str = typer.Option(
|
backend_host: str = typer.Option(
|
||||||
config.backend_host, help="Specify the backend host."
|
config.backend_host, help="Specify the backend host."
|
||||||
|
@ -116,17 +116,14 @@ def change_port(port: int, _type: str) -> int:
|
|||||||
return new_port
|
return new_port
|
||||||
|
|
||||||
|
|
||||||
def handle_port(service_name: str, port: int, default_port: int) -> int:
|
def handle_port(service_name: str, port: int, auto_increment: bool) -> int:
|
||||||
"""Change port if the specified port is in use and is not explicitly specified as a CLI arg or config arg.
|
"""Change port if the specified port is in use and is not explicitly specified as a CLI arg or config arg.
|
||||||
otherwise tell the user the port is in use and exit the app.
|
Otherwise tell the user the port is in use and exit the app.
|
||||||
|
|
||||||
We make an assumption that when port is the default port,then it hasn't been explicitly set since its not straightforward
|
|
||||||
to know whether a port was explicitly provided by the user unless its any other than the default.
|
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
service_name: The frontend or backend.
|
service_name: The frontend or backend.
|
||||||
port: The provided port.
|
port: The provided port.
|
||||||
default_port: The default port number associated with the specified service.
|
auto_increment: Whether to automatically increment the port.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The port to run the service on.
|
The port to run the service on.
|
||||||
@ -134,13 +131,15 @@ def handle_port(service_name: str, port: int, default_port: int) -> int:
|
|||||||
Raises:
|
Raises:
|
||||||
Exit:when the port is in use.
|
Exit:when the port is in use.
|
||||||
"""
|
"""
|
||||||
if is_process_on_port(port):
|
if (process := get_process_on_port(port)) is None:
|
||||||
if port == int(default_port):
|
return port
|
||||||
return change_port(port, service_name)
|
if auto_increment:
|
||||||
else:
|
return change_port(port, service_name)
|
||||||
console.error(f"{service_name.capitalize()} port: {port} is already in use")
|
else:
|
||||||
raise typer.Exit()
|
console.error(
|
||||||
return port
|
f"{service_name.capitalize()} port: {port} is already in use by PID: {process.pid}."
|
||||||
|
)
|
||||||
|
raise typer.Exit()
|
||||||
|
|
||||||
|
|
||||||
def new_process(
|
def new_process(
|
||||||
|
Loading…
Reference in New Issue
Block a user