ERP_Sysyem / scripts /benchmark_queries.py
AI Assistant
feat: implement redis-based caching layer for party data and reporting endpoints
9eecb05
Raw History Blame Contribute Delete
3.71 kB
import time
import asyncio
import logging
from decimal import Decimal
from sqlalchemy import event
from sqlalchemy.engine import Engine
from app.core.database import SessionLocal
from app.services.reports import unified_dashboard_report
from app.services.invoice_service import create_purchase_invoice_svc
from app.repositories.base import InvoiceRepository, BatchRepository
from app.schemas.invoice import InvoiceCreatePurchase, InvoiceItemCreatePurchase
from app.models.domain import Tenant, Party, Product
from app.core.cache import get_cache, set_cache, delete_cache
logging.basicConfig(level=logging.INFO)
query_count = 0
@event.listens_for(Engine, "before_cursor_execute")
def before_cursor_execute(conn, cursor, statement, parameters, context, executemany):
global query_count
query_count += 1
async def run_benchmark_async():
global query_count
with SessionLocal() as db:
try:
tenant = db.query(Tenant).first()
if not tenant:
print("No tenant found for benchmark.")
return
print(f"--- BENCHMARK FOR TENANT ID {tenant.id} ---")
cache_key = "dashboard:2026-01-01:2026-12-31"
# Clear cache before test
await delete_cache(tenant.id, cache_key)
# 1. First Call: Cache Miss (Query DB & Populate Redis)
query_count = 0
t0 = time.perf_counter()
cached_data = await get_cache(tenant.id, cache_key)
if cached_data is None:
res = unified_dashboard_report(db, tenant.id, "2026-01-01", "2026-12-31")
res_dict = res.model_dump() if hasattr(res, "model_dump") else res
await set_cache(tenant.id, cache_key, res_dict, ttl=300)
t1 = time.perf_counter()
print(f"[1st Call - Cache MISS (DB Engine)] Queries: {query_count} | Latency: {(t1 - t0)*1000:.2f} ms")
db.commit()
# 2. Second Call: Cache HIT (Redis sub-millisecond response)
query_count = 0
t0 = time.perf_counter()
cached_data = await get_cache(tenant.id, cache_key)
t1 = time.perf_counter()
print(f"[2nd Call - Cache HIT (Redis Cache)] Queries: {query_count} | Latency: {(t1 - t0)*1000:.2f} ms")
# 3. Multi-item Purchase Invoice Benchmark
party = db.query(Party).filter_by(tenant_id=tenant.id).first()
products = db.query(Product).filter_by(tenant_id=tenant.id).limit(5).all()
if party and len(products) >= 2:
inv_repo = InvoiceRepository(db, tenant.id)
batch_repo = BatchRepository(db, tenant.id)
items = [
InvoiceItemCreatePurchase(
product_id=p.id,
quantity=Decimal("5"),
purchase_price=Decimal("10.00"),
sell_price=Decimal("15.00")
)
for p in products
]
purch_data = InvoiceCreatePurchase(party_id=party.id, items=items)
query_count = 0
t0 = time.perf_counter()
inv = create_purchase_invoice_svc(db, inv_repo, batch_repo, purch_data, tenant.id)
t1 = time.perf_counter()
print(f"[Purchase Invoice Create (5 items)] Queries: {query_count} | Latency: {(t1 - t0)*1000:.2f} ms")
db.rollback()
except Exception as e:
db.rollback()
raise e
def run_benchmark():
asyncio.run(run_benchmark_async())
if __name__ == "__main__":
run_benchmark()