app_module_for_backend.py 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344
  1. """Shims the real reflex app module for running backend server (uvicorn or gunicorn).
  2. Only the app attribute is explicitly exposed.
  3. """
  4. from concurrent.futures import ThreadPoolExecutor
  5. from reflex import constants
  6. from reflex.utils.exec import is_prod_mode
  7. from reflex.utils.prerequisites import get_app, get_compiled_app
  8. if "app" != constants.CompileVars.APP:
  9. raise AssertionError("unexpected variable name for 'app'")
  10. app_module = get_app(reload=False)
  11. app = getattr(app_module, constants.CompileVars.APP)
  12. _executor = ThreadPoolExecutor(max_workers=1)
  13. def _done(executor: ThreadPoolExecutor):
  14. def _cb(f):
  15. # Do not leak file handles from the executor itself
  16. executor.shutdown(wait=False)
  17. # Force background compile errors to print eagerly
  18. print("compile done", f.result(), executor)
  19. return _cb
  20. compile_future = _executor.submit(app.compile_)
  21. compile_future.add_done_callback(_done(_executor))
  22. # Wait for the compile to finish in prod mode to ensure all optional endpoints are mounted.
  23. if is_prod_mode():
  24. compile_future.result()
  25. # ensure only "app" is exposed.
  26. del app_module
  27. del compile_future
  28. del _done
  29. del _executor
  30. del get_app
  31. del get_compiled_app
  32. del is_prod_mode
  33. del constants
  34. del ThreadPoolExecutor