exec.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. """Everything regarding execution of the built app."""
  2. from __future__ import annotations
  3. import os
  4. import platform
  5. import sys
  6. from pathlib import Path
  7. from reflex import constants
  8. from reflex.config import get_config
  9. from reflex.utils import console, path_ops, prerequisites, processes
  10. from reflex.utils.watch import AssetFolderWatch
  11. def start_watching_assets_folder(root):
  12. """Start watching assets folder.
  13. Args:
  14. root: root path of the project.
  15. """
  16. asset_watch = AssetFolderWatch(root)
  17. asset_watch.start()
  18. def run_process_and_launch_url(
  19. run_command: list[str],
  20. ):
  21. """Run the process and launch the URL.
  22. Args:
  23. run_command: The command to run.
  24. """
  25. process = processes.new_process(
  26. run_command, cwd=constants.WEB_DIR, shell=constants.IS_WINDOWS
  27. )
  28. if process.stdout:
  29. for line in process.stdout:
  30. if "ready started server on" in line:
  31. url = line.split("url: ")[-1].strip()
  32. console.print(f"App running at: [bold green]{url}")
  33. else:
  34. console.debug(line)
  35. def run_frontend(
  36. root: Path,
  37. port: str,
  38. ):
  39. """Run the frontend.
  40. Args:
  41. root: The root path of the project.
  42. port: The port to run the frontend on.
  43. """
  44. # Start watching asset folder.
  45. start_watching_assets_folder(root)
  46. # Run the frontend in development mode.
  47. console.rule("[bold green]App Running")
  48. os.environ["PORT"] = str(get_config().frontend_port if port is None else port)
  49. run_process_and_launch_url([prerequisites.get_package_manager(), "run", "dev"])
  50. def run_frontend_prod(
  51. root: Path,
  52. port: str,
  53. ):
  54. """Run the frontend.
  55. Args:
  56. root: The root path of the project (to keep same API as run_frontend).
  57. port: The port to run the frontend on.
  58. """
  59. # Set the port.
  60. os.environ["PORT"] = str(get_config().frontend_port if port is None else port)
  61. # Run the frontend in production mode.
  62. console.rule("[bold green]App Running")
  63. run_process_and_launch_url([prerequisites.get_package_manager(), "run", "prod"])
  64. def run_backend(
  65. app_name: str,
  66. host: str,
  67. port: int,
  68. loglevel: constants.LogLevel = constants.LogLevel.ERROR,
  69. ):
  70. """Run the backend.
  71. Args:
  72. host: The app host
  73. app_name: The app name.
  74. port: The app port
  75. loglevel: The log level.
  76. """
  77. processes.new_process(
  78. [
  79. "uvicorn",
  80. f"{app_name}:{constants.APP_VAR}.{constants.API_VAR}",
  81. "--host",
  82. host,
  83. "--port",
  84. str(port),
  85. "--log-level",
  86. loglevel.value,
  87. "--reload",
  88. "--reload-dir",
  89. app_name.split(".")[0],
  90. ],
  91. run=True,
  92. show_logs=True,
  93. )
  94. def run_backend_prod(
  95. app_name: str,
  96. host: str,
  97. port: int,
  98. loglevel: constants.LogLevel = constants.LogLevel.ERROR,
  99. ):
  100. """Run the backend.
  101. Args:
  102. host: The app host
  103. app_name: The app name.
  104. port: The app port
  105. loglevel: The log level.
  106. """
  107. num_workers = processes.get_num_workers()
  108. config = get_config()
  109. RUN_BACKEND_PROD = f"gunicorn --worker-class uvicorn.workers.UvicornH11Worker --preload --timeout {config.timeout} --log-level critical".split()
  110. RUN_BACKEND_PROD_WINDOWS = f"uvicorn --timeout-keep-alive {config.timeout}".split()
  111. command = (
  112. [
  113. *RUN_BACKEND_PROD_WINDOWS,
  114. "--host",
  115. host,
  116. "--port",
  117. str(port),
  118. f"{app_name}:{constants.APP_VAR}",
  119. ]
  120. if constants.IS_WINDOWS
  121. else [
  122. *RUN_BACKEND_PROD,
  123. "--bind",
  124. f"{host}:{port}",
  125. "--threads",
  126. str(num_workers),
  127. f"{app_name}:{constants.APP_VAR}()",
  128. ]
  129. )
  130. command += [
  131. "--log-level",
  132. loglevel.value,
  133. "--workers",
  134. str(num_workers),
  135. ]
  136. processes.new_process(command, run=True, show_logs=True)
  137. def output_system_info():
  138. """Show system informations if the loglevel is in DEBUG."""
  139. if console.LOG_LEVEL > constants.LogLevel.DEBUG:
  140. return
  141. config = get_config()
  142. try:
  143. config_file = sys.modules[config.__module__].__file__
  144. except Exception:
  145. config_file = None
  146. console.rule(f"System Info")
  147. console.debug(f"Config file: {config_file!r}")
  148. console.debug(f"Config: {config}")
  149. dependencies = [
  150. f"[Reflex {constants.VERSION} with Python {platform.python_version()} (PATH: {sys.executable})]",
  151. f"[Node {prerequisites.get_node_version()} (Expected: {constants.NODE_VERSION}) (PATH:{constants.NODE_PATH})]",
  152. ]
  153. system = platform.system()
  154. if system != "Windows":
  155. dependencies.extend(
  156. [
  157. f"[NVM {constants.NVM_VERSION} (Expected: {constants.NVM_VERSION}) (PATH: {constants.NVM_PATH})]",
  158. f"[Bun {prerequisites.get_bun_version()} (Expected: {constants.BUN_VERSION}) (PATH: {config.bun_path})]",
  159. ],
  160. )
  161. else:
  162. dependencies.append(
  163. f"[FNM {constants.FNM_VERSION} (Expected: {constants.FNM_VERSION}) (PATH: {constants.FNM_EXE})]",
  164. )
  165. if system == "Linux":
  166. import distro # type: ignore
  167. os_version = distro.name(pretty=True)
  168. else:
  169. os_version = platform.version()
  170. dependencies.append(f"[OS {platform.system()} {os_version}]")
  171. for dep in dependencies:
  172. console.debug(f"{dep}")
  173. console.debug(
  174. f"Using package installer at: {prerequisites.get_install_package_manager()}"
  175. )
  176. console.debug(f"Using package executer at: {prerequisites.get_package_manager()}")
  177. if system != "Windows":
  178. console.debug(f"Unzip path: {path_ops.which('unzip')}")