Jelajahi Sumber

Enable pc prod without redis (#85)

* Make app callable

* Enable pc prod without redis

* Add missing code
Nikhil Rao 2 tahun lalu
induk
melakukan
d39bcc7d38
4 mengubah file dengan 37 tambahan dan 12 penghapusan
  1. 8 0
      pynecone/app.py
  2. 1 3
      pynecone/constants.py
  3. 3 1
      pynecone/state.py
  4. 25 8
      pynecone/utils.py

+ 8 - 0
pynecone/app.py

@@ -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.

+ 1 - 3
pynecone/constants.py

@@ -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.

+ 3 - 1
pynecone/state.py

@@ -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.

+ 25 - 8
pynecone/utils.py

@@ -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)