Skip to content

Commit da8ef4d

Browse files
authored
Refactor database handling and update configuration (#65)
- Updated README.md to reflect changes from SQL Database to generic Database terminology. - Refactored app code to replace SQL database references with a more generic database implementation. - Modified settings to remove SQL-specific configurations and streamline database settings. - Adjusted dependencies to align with the new database session management.
1 parent 600e174 commit da8ef4d

5 files changed

Lines changed: 50 additions & 55 deletions

File tree

README.md

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ GitHub Actions, S3 compatible storage, AI APIs and more.
77
## Features
88

99
- Virtual Environment support: `uv`
10-
- SQL Database support: `PostgreSQL`
10+
- Database support: `PostgreSQL`
1111
- Caching support: `Redis`
1212
- Task Queue support: `Celery`
1313
- Message Queue support: `RabbitMQ`
@@ -42,12 +42,11 @@ APP_ROOT_URL=/api
4242
APP_DESCRIPTION="FastAPI App description."
4343
DEBUG=true
4444

45-
# SQL Database (PostgreSQL)
46-
SQL_DB_ENABLED=true
47-
SQL_DB_URL=postgresql+psycopg://postgres:postgres@localhost:5432/postgres
48-
SQL_DB_CONNECT_TIMEOUT=5.0
49-
SQL_DB_POOL_SIZE=10
50-
SQL_DB_POOL_TIMEOUT=5.0
45+
# Database (PostgreSQL)
46+
DB_URL=postgresql+psycopg://postgres:postgres@localhost:5432/postgres
47+
DB_CONNECT_TIMEOUT=5.0
48+
DB_POOL_SIZE=10
49+
DB_POOL_TIMEOUT=5.0
5150

5251
# Cache (Redis)
5352
REDIS_URL=redis://:foobared@localhost:6379/0

app/app.py

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from sqlmodel.ext.asyncio.session import AsyncSession
1818

1919
from app.db_models import TemplateDemo
20-
from app.dependencies import get_redis_session, get_sql_db_session
20+
from app.dependencies import get_db_session, get_redis_session
2121
from app.settings import get_settings
2222
from app.utils import pid_str
2323
from app.webhook import api as webhook_api
@@ -34,7 +34,7 @@
3434

3535

3636
class State(TypedDict):
37-
sql_db_client: AsyncEngine | None
37+
db_client: AsyncEngine
3838
redis_connection_pool: RedisConnectionPool
3939

4040

@@ -48,20 +48,18 @@ async def lifespan(_app: FastAPI) -> AsyncGenerator[dict[str, Any]]:
4848
client_name_str = f'{_app.title} [{_pid_str}]'.replace(' ', '-')
4949
logger.info(f'Starting {client_name_str}...')
5050

51-
sql_db_client = None
52-
if settings.sql_db_enabled:
53-
sql_db_client = create_async_engine(
54-
settings.sql_db_url.encoded_string(),
55-
pool_size=settings.sql_db_pool_size,
56-
max_overflow=20,
57-
pool_timeout=settings.sql_db_pool_timeout,
58-
connect_args={
59-
'application_name': client_name,
60-
'connect_timeout': settings.sql_db_connect_timeout,
61-
},
62-
logging_name=_app.title,
63-
echo=False,
64-
)
51+
db_client = create_async_engine(
52+
settings.db_url.encoded_string(),
53+
pool_size=settings.db_pool_size,
54+
max_overflow=20,
55+
pool_timeout=settings.db_pool_timeout,
56+
connect_args={
57+
'application_name': client_name,
58+
'connect_timeout': settings.db_connect_timeout,
59+
},
60+
logging_name=_app.title,
61+
echo=False,
62+
)
6563

6664
redis_connection_pool: RedisConnectionPool = RedisConnectionPool.from_url(
6765
url=settings.redis_url.encoded_string(),
@@ -74,14 +72,13 @@ async def lifespan(_app: FastAPI) -> AsyncGenerator[dict[str, Any]]:
7472
)
7573

7674
yield {
77-
'sql_db_client': sql_db_client,
75+
'db_client': db_client,
7876
'redis_connection_pool': redis_connection_pool,
7977
}
8078

8179
# Shutdown
82-
if settings.sql_db_enabled and sql_db_client:
83-
await sql_db_client.dispose()
84-
logger.debug(f'SQL Database connection {client_name_str} disposing...')
80+
await db_client.dispose()
81+
logger.debug(f'Database connection {client_name_str} disposing...')
8582
await redis_connection_pool.disconnect()
8683
logger.debug(f'Redis connection pool {client_name_str} disconnected')
8784

@@ -111,14 +108,14 @@ async def lifespan(_app: FastAPI) -> AsyncGenerator[dict[str, Any]]:
111108
@app.get(f'{settings.app_root_url}')
112109
async def root(
113110
request: Request,
114-
sql_db_session: AsyncSession = Depends(get_sql_db_session),
111+
db_session: AsyncSession = Depends(get_db_session),
115112
redis_session: Redis = Depends(get_redis_session),
116113
) -> dict[str, str | bool | None]:
117114
logger.debug(f'Root endpoint [{await pid_str()}]...')
118115

119-
# SQL Database
120-
message = await sql_db_session.exec(select(func.count(col(TemplateDemo.id))))
121-
logger.debug(f'SQL Database message: {message.first()}')
116+
# Database
117+
message = await db_session.exec(select(func.count(col(TemplateDemo.id))))
118+
logger.debug(f'Database message: {message.first()}')
122119

123120
# Cache (Redis)
124121
cache_val = await redis_session.get(f'{settings.cache_prefix}')

app/dependencies.py

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,18 @@
33
from collections.abc import AsyncGenerator
44
from typing import Any
55

6-
from fastapi import HTTPException, Request
6+
from fastapi import Request
77
from redis.asyncio import ConnectionPool as RedisConnectionPool
88
from redis.asyncio import Redis
99
from sqlalchemy.ext.asyncio import AsyncEngine
1010
from sqlmodel.ext.asyncio.session import AsyncSession
1111

1212

13-
async def get_sql_db_session(request: Request) -> AsyncGenerator[AsyncSession, Any]:
14-
"""Get SQL Database session."""
15-
sql_db_client: AsyncEngine | None = request.state.sql_db_client
16-
if sql_db_client:
17-
async with AsyncSession(sql_db_client) as session:
18-
yield session
19-
else:
20-
raise HTTPException(status_code=500, detail='SQL Database connection not found')
13+
async def get_db_session(request: Request) -> AsyncGenerator[AsyncSession, Any]:
14+
"""Get Database session."""
15+
db_client: AsyncEngine = request.state.db_client
16+
async with AsyncSession(db_client) as session:
17+
yield session
2118

2219

2320
async def get_redis_session(request: Request) -> AsyncGenerator[Redis, Any]:

app/settings.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,12 @@ class Settings(BaseSettings):
1919
debug: bool = False
2020

2121
# Database (PostgreSQL)
22-
sql_db_enabled: bool = False
23-
sql_db_url: PostgresDsn = PostgresDsn(
22+
db_url: PostgresDsn = PostgresDsn(
2423
'postgresql+psycopg://postgres:postgres@localhost:5432/postgres'
2524
)
26-
sql_db_connect_timeout: float = 5.0
27-
sql_db_pool_size: int = 10
28-
sql_db_pool_timeout: float = 5.0
25+
db_connect_timeout: float = 5.0
26+
db_pool_size: int = 10
27+
db_pool_timeout: float = 5.0
2928

3029
# Cache (Redis)
3130
redis_url: RedisDsn = RedisDsn('redis://:foobared@localhost:6379/0')

task/celery_worker.py

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,22 @@
2828
resend.api_key = settings.resend_api_key.get_secret_value()
2929

3030
client_name = f'{settings.app_name}-celery-{os.getpid()}'.replace(' ', '-')
31-
sql_db_engine = create_engine(
32-
settings.sql_db_url.encoded_string(),
33-
pool_size=settings.sql_db_pool_size,
31+
32+
33+
db_engine = create_engine(
34+
settings.db_url.encoded_string(),
35+
pool_size=settings.db_pool_size,
3436
max_overflow=20,
35-
pool_timeout=settings.sql_db_pool_timeout,
37+
pool_timeout=settings.db_pool_timeout,
3638
connect_args={
3739
'application_name': client_name,
38-
'connect_timeout': settings.sql_db_connect_timeout,
40+
'connect_timeout': settings.db_connect_timeout,
3941
},
4042
logging_name=client_name,
4143
echo=False,
4244
)
4345

46+
4447
redis_client = Redis.from_url(
4548
settings.redis_url.encoded_string(),
4649
encoding='utf-8',
@@ -136,7 +139,7 @@ def handle_resend_email_attachments_to_s3(
136139
ck_file_digest = f'{settings.cache_prefix}:file_digest_sha256'
137140
with (
138141
httpx.Client(timeout=download_timeout_config) as http_client,
139-
SQLSession(sql_db_engine) as sql_session,
142+
SQLSession(db_engine) as db_session,
140143
):
141144
for attachment in attachment_list:
142145
attachment_id = attachment['id']
@@ -160,7 +163,7 @@ def handle_resend_email_attachments_to_s3(
160163
Config=S3TransferConfig(multipart_threshold=settings.s3_multipart_threshold),
161164
)
162165

163-
sql_session.add(
166+
db_session.add(
164167
EmailAttachment(
165168
webhook=EmailWebhookEnum.RESEND,
166169
webhook_event_type=EmailWebhookEventTypeEnum.EMAIL_RECEIVED,
@@ -182,7 +185,7 @@ def handle_resend_email_attachments_to_s3(
182185

183186
redis_client.hset(ck_file_digest, file_name, file_digest)
184187

185-
sql_session.commit()
188+
db_session.commit()
186189

187190
# Release the message lock
188191
redis_client.delete(ck_message_lock)
@@ -205,7 +208,7 @@ def handle_resend_email_received(
205208
ck_ai_files = f'{settings.cache_prefix}:ai:files'
206209
with (
207210
httpx.Client(timeout=download_timeout_config) as http_client,
208-
SQLSession(sql_db_engine) as sql_session,
211+
SQLSession(db_engine) as db_session,
209212
):
210213
for attachment in attachment_list:
211214
attachment_id = attachment['id']
@@ -254,7 +257,7 @@ def handle_resend_email_received(
254257

255258
ai_file_ids[file_name] = ai_file_id
256259

257-
sql_session.commit()
260+
db_session.commit()
258261

259262
# Release the message lock
260263
redis_client.delete(message_lock_ck)

0 commit comments

Comments
 (0)