Coverage for src / idx_api / utils / cache.py: 22%
32 statements
« prev ^ index » next coverage.py v7.13.1, created at 2025-12-28 11:09 -0700
« prev ^ index » next coverage.py v7.13.1, created at 2025-12-28 11:09 -0700
1"""Cache invalidation utilities for coordinating with Astro frontend.
3When brokerage settings change, the Astro SSR server needs to be notified
4to clear its in-memory config cache. This module provides async functions
5to call the Astro purge endpoint.
6"""
8import os
9import httpx
10from typing import Optional
12# Astro frontend URL for internal service-to-service communication
13ASTRO_INTERNAL_URL = os.getenv("ASTRO_INTERNAL_URL", "http://idx-web:4321")
14INTERNAL_API_KEY = os.getenv("INTERNAL_API_KEY", "idx-internal-key")
17async def invalidate_site_config(domain: Optional[str] = None) -> bool:
18 """
19 Notify Astro frontend to purge cached site config.
21 Args:
22 domain: Optional specific domain to purge. If None, purges all cached configs.
24 Returns:
25 True if purge was successful, False otherwise.
26 """
27 try:
28 async with httpx.AsyncClient(timeout=5.0) as client:
29 response = await client.post(
30 f"{ASTRO_INTERNAL_URL}/api/internal/purge-config",
31 headers={
32 "Authorization": f"Bearer {INTERNAL_API_KEY}",
33 "Content-Type": "application/json",
34 },
35 json={"domain": domain} if domain else {},
36 )
38 if response.status_code == 200:
39 result = response.json()
40 print(f"✅ Cache invalidated: {result}")
41 return True
42 else:
43 print(f"⚠️ Cache invalidation failed: {response.status_code} - {response.text}")
44 return False
46 except httpx.ConnectError:
47 # Astro server might not be running (dev mode) - not critical
48 print("⚠️ Could not connect to Astro server for cache invalidation (may be in dev mode)")
49 return False
50 except Exception as e:
51 print(f"⚠️ Cache invalidation error: {e}")
52 return False
55async def invalidate_brokerage_domains(brokerage_id: int, db) -> bool:
56 """
57 Invalidate cache for all domains associated with a brokerage.
59 Args:
60 brokerage_id: The brokerage ID whose domains should be purged.
61 db: Database session to query domains.
63 Returns:
64 True if all purges were successful.
65 """
66 from idx_api.models.brokerage_domain import BrokerageDomain
67 from sqlalchemy import select
69 # Get all domains for this brokerage
70 domains = db.scalars(
71 select(BrokerageDomain.domain)
72 .where(BrokerageDomain.brokerage_id == brokerage_id)
73 ).all()
75 if not domains:
76 # No domains configured - purge all just in case
77 return await invalidate_site_config()
79 # Purge each domain's cache
80 success = True
81 for domain in domains:
82 result = await invalidate_site_config(domain)
83 success = success and result
85 return success