exec.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. """Everything regarding execution of the built app."""
  2. from __future__ import annotations
  3. import os
  4. import platform
  5. import subprocess
  6. from pathlib import Path
  7. from rich import print
  8. from reflex import constants
  9. from reflex.config import get_config
  10. from reflex.utils import console, prerequisites, processes
  11. from reflex.utils.processes import new_process
  12. from reflex.utils.watch import AssetFolderWatch
  13. def start_watching_assets_folder(root):
  14. """Start watching assets folder.
  15. Args:
  16. root: root path of the project.
  17. """
  18. asset_watch = AssetFolderWatch(root)
  19. asset_watch.start()
  20. def run_process_and_launch_url(
  21. run_command: list[str],
  22. loglevel: constants.LogLevel = constants.LogLevel.ERROR,
  23. ):
  24. """Run the process and launch the URL.
  25. Args:
  26. run_command: The command to run.
  27. loglevel: The log level to use.
  28. """
  29. process = new_process(
  30. run_command,
  31. cwd=constants.WEB_DIR,
  32. )
  33. if process.stdout:
  34. for line in process.stdout:
  35. if "ready started server on" in line:
  36. url = line.split("url: ")[-1].strip()
  37. print(f"App running at: [bold green]{url}")
  38. if loglevel == constants.LogLevel.DEBUG:
  39. print(line, end="")
  40. def run_frontend(
  41. root: Path,
  42. port: str,
  43. loglevel: constants.LogLevel = constants.LogLevel.ERROR,
  44. ):
  45. """Run the frontend.
  46. Args:
  47. root: The root path of the project.
  48. port: The port to run the frontend on.
  49. loglevel: The log level to use.
  50. """
  51. # Start watching asset folder.
  52. start_watching_assets_folder(root)
  53. # Run the frontend in development mode.
  54. console.rule("[bold green]App Running")
  55. os.environ["PORT"] = get_config().frontend_port if port is None else port
  56. run_process_and_launch_url(
  57. [prerequisites.get_package_manager(), "run", "dev"], loglevel
  58. )
  59. def run_frontend_prod(
  60. root: Path,
  61. port: str,
  62. loglevel: constants.LogLevel = constants.LogLevel.ERROR,
  63. ):
  64. """Run the frontend.
  65. Args:
  66. root: The root path of the project (to keep same API as run_frontend).
  67. port: The port to run the frontend on.
  68. loglevel: The log level to use.
  69. """
  70. # Set the port.
  71. os.environ["PORT"] = get_config().frontend_port if port is None else port
  72. # Run the frontend in production mode.
  73. console.rule("[bold green]App Running")
  74. run_process_and_launch_url(
  75. [prerequisites.get_package_manager(), "run", "prod"], loglevel
  76. )
  77. def run_backend(
  78. app_name: str,
  79. host: str,
  80. port: int,
  81. loglevel: constants.LogLevel = constants.LogLevel.ERROR,
  82. ):
  83. """Run the backend.
  84. Args:
  85. host: The app host
  86. app_name: The app name.
  87. port: The app port
  88. loglevel: The log level.
  89. """
  90. cmd = [
  91. "uvicorn",
  92. f"{app_name}:{constants.APP_VAR}.{constants.API_VAR}",
  93. "--host",
  94. host,
  95. "--port",
  96. str(port),
  97. "--log-level",
  98. loglevel,
  99. "--reload",
  100. "--reload-dir",
  101. app_name.split(".")[0],
  102. ]
  103. process = subprocess.Popen(cmd)
  104. try:
  105. process.wait()
  106. except KeyboardInterrupt:
  107. process.terminate()
  108. def run_backend_prod(
  109. app_name: str,
  110. host: str,
  111. port: int,
  112. loglevel: constants.LogLevel = constants.LogLevel.ERROR,
  113. ):
  114. """Run the backend.
  115. Args:
  116. host: The app host
  117. app_name: The app name.
  118. port: The app port
  119. loglevel: The log level.
  120. """
  121. num_workers = processes.get_num_workers()
  122. command = (
  123. [
  124. *constants.RUN_BACKEND_PROD_WINDOWS,
  125. "--host",
  126. host,
  127. "--port",
  128. str(port),
  129. f"{app_name}:{constants.APP_VAR}",
  130. ]
  131. if platform.system() == "Windows"
  132. else [
  133. *constants.RUN_BACKEND_PROD,
  134. "--bind",
  135. f"{host}:{port}",
  136. "--threads",
  137. str(num_workers),
  138. f"{app_name}:{constants.APP_VAR}()",
  139. ]
  140. )
  141. command += [
  142. "--log-level",
  143. loglevel.value,
  144. "--workers",
  145. str(num_workers),
  146. ]
  147. subprocess.run(command)