Enable pc prod without redis (#85)

* Make app callable

* Enable pc prod without redis

* Add missing code
This commit is contained in:
Nikhil Rao 2022-12-13 10:05:37 -08:00 committed by GitHub
parent 23fc3cadd9
commit d39bcc7d38
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 37 additions and 12 deletions

View File

@ -74,6 +74,14 @@ class App(Base):
"""
return f"<App state={self.state.__name__}>"
def __call__(self) -> fastapi.FastAPI:
"""Run the backend api instance.
Returns:
The backend api.
"""
return self.api
def add_default_endpoints(self):
"""Add the default endpoints."""
# To test the server.

View File

@ -56,12 +56,10 @@ BUN_PATH = "$HOME/.bun/bin/bun"
INSTALL_BUN = "curl https://bun.sh/install | bash"
# Command to run the backend in dev mode.
RUN_BACKEND = "uvicorn --log-level critical --reload --host 0.0.0.0".split()
# The number of workers to run in production mode by default.
NUM_WORKERS = (os.cpu_count() or 1) * 2 + 1
# The default timeout when launching the gunicorn server.
TIMEOUT = 120
# The command to run the backend in production mode.
RUN_BACKEND_PROD = f"gunicorn --worker-class uvicorn.workers.UvicornH11Worker --bind 0.0.0.0:8000 --workers {NUM_WORKERS} --threads {NUM_WORKERS} --preload --timeout {TIMEOUT} --log-level debug".split()
RUN_BACKEND_PROD = f"gunicorn --worker-class uvicorn.workers.UvicornH11Worker --bind 0.0.0.0:8000 --preload --timeout {TIMEOUT} --log-level debug".split()
# Compiler variables.
# The extension for compiled Javascript files.

View File

@ -8,6 +8,8 @@ import traceback
from abc import ABC
from typing import Any, Callable, ClassVar, Dict, List, Optional, Sequence, Set, Type
from redis import Redis
from pynecone import constants, utils
from pynecone.base import Base
from pynecone.event import Event, EventHandler, window_alert
@ -476,7 +478,7 @@ class StateManager(Base):
token_expiration: int = constants.TOKEN_EXPIRATION
# The redis client to use.
redis: Any = None
redis: Optional[Redis] = None
def setup(self, state: Type[State]):
"""Set up the state manager.

View File

@ -29,6 +29,7 @@ from typing import (
import plotly.graph_objects as go
from plotly.io import to_json
from redis import Redis
from rich.console import Console
from pynecone import constants
@ -385,6 +386,20 @@ def run_frontend_prod(app) -> subprocess.Popen:
return subprocess.Popen(command, cwd=constants.WEB_DIR)
def get_num_workers() -> int:
"""Get the number of backend worker processes.
Returns:
The number of backend worker processes.
"""
if get_redis() is None:
# If there is no redis, then just use 1 worker.
return 1
# Use the number of cores * 2 + 1.
return (os.cpu_count() or 1) * 2 + 1
def run_backend(app):
"""Run the backend.
@ -403,7 +418,14 @@ def run_backend_prod(app) -> None:
Args:
app: The app.
"""
command = constants.RUN_BACKEND_PROD + [f"{app.__name__}:{constants.API_VAR}"]
num_workers = get_num_workers()
command = constants.RUN_BACKEND_PROD + [
"--workers",
str(num_workers),
"--threads",
str(num_workers),
f"{app.__name__}:{constants.APP_VAR}()",
]
subprocess.call(command)
@ -918,20 +940,15 @@ def get_hydrate_event(state) -> str:
return get_event(state, constants.HYDRATE)
def get_redis():
def get_redis() -> Optional[Redis]:
"""Get the redis client.
Returns:
The redis client.
"""
try:
import redis # type: ignore
except:
return None
config = get_config()
if config.redis_url is None:
return None
redis_url, redis_port = config.redis_url.split(":")
print("Using redis at", config.redis_url)
return redis.Redis(host=redis_url, port=int(redis_port), db=0)
return Redis(host=redis_url, port=int(redis_port), db=0)