reflex/reflex/server/base.py
2024-11-08 16:29:16 +00:00

96 lines
2.9 KiB
Python

"""The base for CustomBackendServer."""
from __future__ import annotations
import os
from abc import abstractmethod
from pathlib import Path
from reflex import constants
from reflex.base import Base
from reflex.constants.base import Env, LogLevel
class CustomBackendServer(Base):
"""BackendServer base."""
@staticmethod
def get_app_module(for_granian_target: bool = False, add_extra_api: bool = False):
"""Get the app module for the backend.
Returns:
The app module for the backend.
"""
import reflex
if for_granian_target:
app_path = str(Path(reflex.__file__).parent / "app_module_for_backend.py")
else:
app_path = "reflex.app_module_for_backend"
return f"{app_path}:{constants.CompileVars.APP}{f'.{constants.CompileVars.API}' if add_extra_api else ''}"
def get_available_cpus(self) -> int:
"""Get available cpus."""
return os.cpu_count() or 1
def get_max_workers(self) -> int:
"""Get max workers."""
# https://docs.gunicorn.org/en/latest/settings.html#workers
return (os.cpu_count() or 1) * 4 + 1
def get_recommended_workers(self) -> int:
"""Get recommended workers."""
# https://docs.gunicorn.org/en/latest/settings.html#workers
return (os.cpu_count() or 1) * 2 + 1
def get_max_threads(self, wait_time_ms: int = 50, service_time_ms: int = 5) -> int:
"""Get max threads."""
# https://engineering.zalando.com/posts/2019/04/how-to-set-an-ideal-thread-pool-size.html
# Brian Goetz formula
return int(self.get_available_cpus() * (1 + wait_time_ms / service_time_ms))
def get_recommended_threads(
self,
target_reqs: int | None = None,
wait_time_ms: int = 50,
service_time_ms: int = 5,
) -> int:
"""Get recommended threads."""
# https://engineering.zalando.com/posts/2019/04/how-to-set-an-ideal-thread-pool-size.html
max_available_threads = self.get_max_threads()
if target_reqs:
# Little's law formula
need_threads = target_reqs * (
(wait_time_ms / 1000) + (service_time_ms / 1000)
)
else:
need_threads = self.get_max_threads(wait_time_ms, service_time_ms)
return int(
max_available_threads
if need_threads > max_available_threads
else need_threads
)
@abstractmethod
def check_import(self, extra: bool = False):
"""Check package importation."""
raise NotImplementedError()
@abstractmethod
def setup(self, host: str, port: int, loglevel: LogLevel, env: Env):
"""Setup."""
raise NotImplementedError()
@abstractmethod
def run_prod(self):
"""Run in production mode."""
raise NotImplementedError()
@abstractmethod
def run_dev(self):
"""Run in development mode."""
raise NotImplementedError()