Skip to content

Commit 2e4c2d5

Browse files
authored
Merge pull request #103 from Akin01/main
Refactor on startup configuration, sqlalchemy session maker, and email sender factory.
2 parents d9597d1 + f82aa55 commit 2e4c2d5

File tree

4 files changed

+39
-31
lines changed

4 files changed

+39
-31
lines changed

Diff for: .gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ venv.bak/
139139

140140
# Rope project settings
141141
.ropeproject
142+
.vscode
142143

143144
# mkdocs documentation
144145
/site

Diff for: src/labs/api.py

+17-19
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010
API endpoints are built and served using the FastAPI micro-framework.
1111
1212
"""
13+
from contextlib import asynccontextmanager
1314
from . import __title__, __version__
1415

1516
from fastapi import FastAPI, Request, status, WebSocket
16-
from fastapi.responses import JSONResponse
1717
from fastapi.routing import APIRoute
1818

1919
from .settings import settings
@@ -39,19 +39,33 @@ def generate_operation_id(route: APIRoute) -> str:
3939
return route.name
4040

4141

42+
@asynccontextmanager
43+
async def lifespan(_fastapi: FastAPI):
44+
if broker.is_worker_process:
45+
# TaskIQ configurartion so we can share FastAPI dependencies in tasks
46+
await broker.startup()
47+
48+
yield
49+
50+
if broker.is_worker_process:
51+
# On shutdown, we need to shutdown the broker
52+
await broker.shutdown()
53+
54+
4255
"""A FastAPI application that serves handlers
4356
"""
4457
app = FastAPI(
4558
title=__title__,
4659
version=__version__,
47-
description=settings.api_router.__doc__,
60+
description=str(settings.api_router.__doc__),
4861
docs_url=settings.api_router.path_docs,
4962
root_path=settings.api_router.path_root,
5063
terms_of_service=settings.api_router.terms_of_service,
5164
contact=settings.api_router.contact,
5265
license_info=settings.api_router.license_info,
5366
openapi_tags=settings.api_router.open_api_tags,
5467
generate_unique_id_function=generate_operation_id,
68+
lifespan=lifespan
5569
)
5670

5771

@@ -67,23 +81,7 @@ async def websocket_endpoint(websocket: WebSocket):
6781
app.include_router(router_root)
6882

6983

70-
# TaskIQ configurartion so we can share FastAPI dependencies in tasks
71-
@app.on_event("startup")
72-
async def app_startup():
73-
if not broker.is_worker_process:
74-
await broker.startup()
75-
76-
# On shutdown, we need to shutdown the broker
77-
78-
79-
@app.on_event("shutdown")
80-
async def app_shutdown():
81-
if not broker.is_worker_process:
82-
await broker.shutdown()
83-
8484
# Default handler
85-
86-
8785
@app.get(
8886
"/",
8987
status_code=status.HTTP_200_OK,
@@ -93,5 +91,5 @@ async def root(request: Request) -> RootResponse:
9391
"""
9492
return RootResponse(
9593
message="Welcome to the {} API".format(__name__),
96-
root_path=request.scope.get("root_path")
94+
root_path=str(request.scope.get("root_path"))
9795
)

Diff for: src/labs/db.py

+8-10
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@
66
77
"""
88

9+
from typing import AsyncGenerator
910
from sqlalchemy.ext.asyncio import create_async_engine,\
10-
AsyncSession
11+
AsyncSession, async_sessionmaker, AsyncAttrs
1112
from sqlalchemy.orm import DeclarativeBase,\
12-
configure_mappers, sessionmaker
13+
configure_mappers
1314

1415

1516
from .settings import settings
@@ -24,19 +25,16 @@
2425
configure_mappers()
2526

2627
# Get an async session from the engine
28+
AsyncSessionFactory = async_sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
2729

2830

29-
async def get_async_session() -> AsyncSession:
30-
async_session = sessionmaker(
31-
engine, class_=AsyncSession, expire_on_commit=False
32-
)
33-
async with async_session() as session:
31+
async def get_async_session() -> AsyncGenerator[AsyncSession, None]:
32+
async with AsyncSessionFactory() as session:
3433
yield session
3534

36-
# Used by the ORM layer to describe models
37-
3835

39-
class Base(DeclarativeBase):
36+
# Used by the ORM layer to describe models
37+
class Base(DeclarativeBase, AsyncAttrs):
4038
"""
4139
SQLAlchemy 2.0 style declarative base class
4240
https://bit.ly/3WE3Srg

Diff for: src/labs/email.py

+13-2
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,22 @@
1414
Redmail docs are located at https://red-mail.readthedocs.io/
1515
"""
1616
import os
17-
from redmail import EmailSender
17+
from redmail.email.sender import EmailSender
1818

1919
from .settings import settings
2020

21-
sender = EmailSender(
21+
# Custom factory to be able to set the sender globally
22+
class EmailSenderFactory(EmailSender):
23+
@property
24+
def sender(self):
25+
return self.sender
26+
27+
@sender.setter
28+
def sender(self, sender: str):
29+
self.sender = sender
30+
31+
32+
sender = EmailSenderFactory(
2233
host=settings.smtp.host,
2334
port=settings.smtp.port,
2435
username=settings.smtp.user.get_secret_value(),

0 commit comments

Comments
 (0)