feat: implement Redis caching for analytics endpoints with fallback to database
Test / test (push) Successful in 15s
Test / test (push) Successful in 15s
This commit is contained in:
@@ -5,6 +5,7 @@ from collections.abc import Iterable
|
||||
from dataclasses import dataclass
|
||||
from decimal import Decimal
|
||||
|
||||
from redis.asyncio.client import Redis
|
||||
from sqlalchemy import func, select
|
||||
|
||||
from app.models.activity import Activity, ActivityType
|
||||
@@ -12,6 +13,7 @@ from app.models.contact import Contact
|
||||
from app.models.deal import Deal, DealCreate, DealStage, DealStatus
|
||||
from app.models.organization_member import OrganizationRole
|
||||
from app.repositories.deal_repo import DealRepository
|
||||
from app.services.analytics_service import invalidate_analytics_cache
|
||||
from app.services.organization_service import OrganizationContext
|
||||
|
||||
|
||||
@@ -61,13 +63,23 @@ class DealUpdateData:
|
||||
class DealService:
|
||||
"""Encapsulates deal workflows and validations."""
|
||||
|
||||
def __init__(self, repository: DealRepository) -> None:
|
||||
def __init__(
|
||||
self,
|
||||
repository: DealRepository,
|
||||
cache: Redis | None = None,
|
||||
*,
|
||||
cache_backoff_ms: int = 0,
|
||||
) -> None:
|
||||
self._repository = repository
|
||||
self._cache = cache
|
||||
self._cache_backoff_ms = cache_backoff_ms
|
||||
|
||||
async def create_deal(self, data: DealCreate, *, context: OrganizationContext) -> Deal:
|
||||
self._ensure_same_organization(data.organization_id, context)
|
||||
await self._ensure_contact_in_organization(data.contact_id, context.organization_id)
|
||||
return await self._repository.create(data=data, role=context.role, user_id=context.user_id)
|
||||
deal = await self._repository.create(data=data, role=context.role, user_id=context.user_id)
|
||||
await invalidate_analytics_cache(self._cache, context.organization_id, self._cache_backoff_ms)
|
||||
return deal
|
||||
|
||||
async def update_deal(
|
||||
self,
|
||||
@@ -111,6 +123,7 @@ class DealService:
|
||||
author_id=context.user_id,
|
||||
activities=[activity for activity in [stage_activity, status_activity] if activity],
|
||||
)
|
||||
await invalidate_analytics_cache(self._cache, context.organization_id, self._cache_backoff_ms)
|
||||
return updated
|
||||
|
||||
async def ensure_contact_can_be_deleted(self, contact_id: int) -> None:
|
||||
|
||||
Reference in New Issue
Block a user