This repository has been archived by the owner on Sep 12, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Logic for reloading is in `uvicorn.run()`, but to use it we need to let uvicorn manage the event loop for us. So this commit moves the database/cache readiness checks into a starlite, "before_startup" hook handler, so that they are conducted after uvicorn has setup the event loop.
- Loading branch information
1 parent
8f6c80b
commit 40e832b
Showing
8 changed files
with
93 additions
and
80 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
"""Application lifespan handlers.""" | ||
# pylint: disable=broad-except | ||
import asyncio | ||
import logging | ||
|
||
import starlite | ||
from sqlalchemy import text | ||
|
||
from starlite_saqlalchemy import redis | ||
from starlite_saqlalchemy.db import engine | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
async def _db_ready() -> None: | ||
"""Wait for database to become responsive.""" | ||
while True: | ||
try: | ||
async with engine.begin() as conn: | ||
await conn.execute(text("SELECT 1")) | ||
except Exception as exc: | ||
logger.info("Waiting for DB: %s", exc) | ||
await asyncio.sleep(5) | ||
else: | ||
logger.info("DB OK!") | ||
break | ||
|
||
|
||
async def _redis_ready() -> None: | ||
"""Wait for redis to become responsive.""" | ||
while True: | ||
try: | ||
await redis.client.ping() | ||
except Exception as exc: | ||
logger.info("Waiting for Redis: %s", exc) | ||
await asyncio.sleep(5) | ||
else: | ||
logger.info("Redis OK!") | ||
break | ||
|
||
|
||
async def before_startup_handler(_: starlite.Starlite) -> None: | ||
"""Do things before the app starts up.""" | ||
await _db_ready() | ||
await _redis_ready() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,84 +1,41 @@ | ||
"""Application startup script.""" | ||
# pragma: no cover | ||
# pylint: disable=broad-except | ||
import argparse | ||
import asyncio | ||
|
||
import uvicorn | ||
import uvloop | ||
from sqlalchemy import text | ||
|
||
from starlite_saqlalchemy import redis, settings | ||
from starlite_saqlalchemy.db import engine | ||
from starlite_saqlalchemy import settings | ||
|
||
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy()) | ||
|
||
def determine_should_reload() -> bool: | ||
"""Evaluate whether reloading should be enabled.""" | ||
return ( | ||
settings.server.RELOAD | ||
if settings.server.RELOAD is not None | ||
else settings.app.ENVIRONMENT == "local" | ||
) | ||
|
||
async def _db_ready() -> None: | ||
"""Wait for database to become responsive.""" | ||
while True: | ||
try: | ||
async with engine.begin() as conn: | ||
await conn.execute(text("SELECT 1")) | ||
except Exception as exc: | ||
print(f"Waiting for DB: {exc}") | ||
await asyncio.sleep(5) | ||
else: | ||
print("DB OK!") | ||
break | ||
|
||
def determine_reload_dirs(should_reload: bool) -> list[str] | None: | ||
""" | ||
async def _redis_ready() -> None: | ||
"""Wait for redis to become responsive.""" | ||
while True: | ||
try: | ||
await redis.client.ping() | ||
except Exception as exc: | ||
print(f"Waiting for Redis: {exc}") | ||
await asyncio.sleep(5) | ||
else: | ||
print("Redis OK!") | ||
break | ||
Args: | ||
should_reload: is reloading enabled? | ||
Returns: | ||
List of directories to watch, or `None` if reloading disabled. | ||
""" | ||
return settings.server.RELOAD_DIRS if should_reload else None | ||
|
||
def _get_uvicorn_config() -> uvicorn.Config: | ||
reload = ( | ||
settings.server.RELOAD | ||
if settings.server.RELOAD is not None | ||
else settings.app.ENVIRONMENT == "local" | ||
) | ||
reload_dirs = settings.server.RELOAD_DIRS if reload else None | ||
|
||
return uvicorn.Config( | ||
def run_app() -> None: | ||
"""Run the application with config via environment.""" | ||
should_reload = determine_should_reload() | ||
reload_dirs = determine_reload_dirs(should_reload) | ||
uvicorn.run( | ||
app=settings.server.APP_LOC, | ||
factory=settings.server.APP_LOC_IS_FACTORY, | ||
host=settings.server.HOST, | ||
loop="none", | ||
loop="auto", | ||
port=settings.server.PORT, | ||
reload=reload, | ||
reload=should_reload, | ||
reload_dirs=reload_dirs, | ||
timeout_keep_alive=settings.server.KEEPALIVE, | ||
) | ||
|
||
|
||
async def _run_server(config: uvicorn.Config) -> None: | ||
"""Run an uvicorn server with the given config.""" | ||
server = uvicorn.Server(config) | ||
await server.serve() | ||
|
||
|
||
def run_app() -> None: | ||
"""Run the application.""" | ||
parser = argparse.ArgumentParser(description="Run the application") | ||
parser.add_argument("--no-db", action="store_const", const=False, default=True, dest="check_db") | ||
parser.add_argument( | ||
"--no-cache", action="store_const", const=False, default=True, dest="check_cache" | ||
) | ||
args = parser.parse_args() | ||
|
||
with asyncio.Runner() as runner: | ||
if args.check_db: | ||
runner.run(_db_ready()) | ||
if args.check_cache: | ||
runner.run(_redis_ready()) | ||
runner.run(_run_server(_get_uvicorn_config())) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters