-
Notifications
You must be signed in to change notification settings - Fork 0
Test/unittest #58
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Test/unittest #58
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,16 +1,34 @@ | ||
| """Database session and engine configuration.""" | ||
| from __future__ import annotations | ||
|
|
||
| from functools import lru_cache | ||
|
|
||
| from sqlalchemy.ext.asyncio import AsyncEngine, AsyncSession, async_sessionmaker, create_async_engine | ||
|
|
||
| from app.core.config import get_settings | ||
|
|
||
| settings = get_settings() | ||
|
|
||
| engine: AsyncEngine = create_async_engine(settings.async_database_uri, echo=False) | ||
| SessionLocal = async_sessionmaker(bind=engine, expire_on_commit=False, class_=AsyncSession) | ||
|
|
||
| @lru_cache | ||
| def get_engine() -> AsyncEngine: | ||
| """Create (and memoize) the async engine. | ||
|
|
||
| Lazily initializing the engine keeps import-time side effects minimal and | ||
| allows test suites to override DB dependencies without requiring every | ||
| production DB driver to be installed. | ||
| """ | ||
|
|
||
| return create_async_engine(settings.async_database_uri, echo=False) | ||
|
|
||
|
|
||
| @lru_cache | ||
| def get_sessionmaker() -> async_sessionmaker[AsyncSession]: | ||
| return async_sessionmaker(bind=get_engine(), expire_on_commit=False, class_=AsyncSession) | ||
|
|
||
|
|
||
| async def get_db() -> AsyncSession: | ||
| """Yield an async database session for request lifecycle management.""" | ||
|
|
||
| async with SessionLocal() as session: | ||
| async with get_sessionmaker()() as session: | ||
| yield session | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| [pytest] | ||
| markers = | ||
| asyncio: async test executed via event loop |
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,259 @@ | ||||||||||
| """Simple backend stress/load test runner. | ||||||||||
|
|
||||||||||
| Default mode uses ASGITransport so you don't need to start uvicorn. | ||||||||||
| It is intentionally lightweight (no extra dependencies). | ||||||||||
| """ | ||||||||||
|
|
||||||||||
| from __future__ import annotations | ||||||||||
|
|
||||||||||
| import argparse | ||||||||||
| import asyncio | ||||||||||
| import contextlib | ||||||||||
| import json | ||||||||||
| import math | ||||||||||
| import os | ||||||||||
| import random | ||||||||||
| import shutil | ||||||||||
| import statistics | ||||||||||
| import tempfile | ||||||||||
| import time | ||||||||||
| from dataclasses import dataclass | ||||||||||
| from pathlib import Path | ||||||||||
| from typing import Any, AsyncIterator | ||||||||||
|
||||||||||
| from typing import Any, AsyncIterator | |
| from typing import AsyncIterator |
Copilot
AI
Dec 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing type annotation for the 'make_request' parameter. Consider adding a type hint such as 'Callable[[AsyncClient], Awaitable[int]]' to improve code clarity and enable better type checking.
Copilot
AI
Dec 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The 'lock' is only used to protect 'status_counts' and the 'ok'/'errors' counters, but 'latencies_ms[i]' is written without lock protection on line 134. While this is actually safe because each task writes to a unique index 'i', the inconsistent locking pattern could be confusing. Consider adding a comment explaining why 'latencies_ms[i]' doesn't need lock protection (unique index per task).
| elapsed_ms = (time.perf_counter() - start) * 1000 | |
| elapsed_ms = (time.perf_counter() - start) * 1000 | |
| # This write is safe without the lock: each task gets a unique index i, | |
| # so no two tasks ever write to the same latencies_ms element. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using '@lru_cache' on 'get_engine' and 'get_sessionmaker' may cause issues in multi-threaded or multi-process environments. The SQLAlchemy async engine is not inherently thread-safe across process boundaries (e.g., when using multiprocessing or after fork). Consider using '@lru_cache(maxsize=1)' for clarity, or document that this service should not be used with multiprocessing/forking servers without proper engine disposal between forks.