
- Implemented comprehensive multi-tenant data isolation using database-level security - Built JWT authentication system with role-based access control (Super Admin, Org Admin, User, Viewer) - Created RESTful API endpoints for user and organization operations - Added complete audit logging for all data modifications with IP tracking - Implemented API rate limiting and input validation with security middleware - Built webhook processing engine with async event handling and retry logic - Created external API call handlers with circuit breaker pattern and error handling - Implemented data synchronization between external services and internal data - Added integration health monitoring and status tracking - Created three mock external services (User Management, Payment, Communication) - Implemented idempotency for webhook processing to handle duplicates gracefully - Added comprehensive security headers and XSS/CSRF protection - Set up Alembic database migrations with proper SQLite configuration - Included extensive documentation and API examples Architecture features: - Multi-tenant isolation at database level - Circuit breaker pattern for external API resilience - Async background task processing - Complete audit trail with user context - Role-based permission system - Webhook signature verification - Request validation and sanitization - Health monitoring endpoints Co-Authored-By: Claude <noreply@anthropic.com>
94 lines
2.9 KiB
Python
94 lines
2.9 KiB
Python
import time
|
|
from enum import Enum
|
|
from typing import Callable, Any
|
|
from dataclasses import dataclass
|
|
import logging
|
|
from app.core.config import settings
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class CircuitState(Enum):
|
|
CLOSED = "closed"
|
|
OPEN = "open"
|
|
HALF_OPEN = "half_open"
|
|
|
|
|
|
@dataclass
|
|
class CircuitBreakerConfig:
|
|
failure_threshold: int = settings.CIRCUIT_BREAKER_FAILURE_THRESHOLD
|
|
timeout: int = settings.CIRCUIT_BREAKER_TIMEOUT
|
|
expected_exception: type = Exception
|
|
|
|
|
|
class CircuitBreaker:
|
|
def __init__(self, config: CircuitBreakerConfig):
|
|
self.failure_threshold = config.failure_threshold
|
|
self.timeout = config.timeout
|
|
self.expected_exception = config.expected_exception
|
|
|
|
self.failure_count = 0
|
|
self.last_failure_time = None
|
|
self.state = CircuitState.CLOSED
|
|
|
|
def call(self, func: Callable, *args, **kwargs) -> Any:
|
|
"""Execute function with circuit breaker protection"""
|
|
|
|
if self.state == CircuitState.OPEN:
|
|
if self._should_attempt_reset():
|
|
self.state = CircuitState.HALF_OPEN
|
|
logger.info("Circuit breaker state changed to HALF_OPEN")
|
|
else:
|
|
raise Exception("Circuit breaker is OPEN")
|
|
|
|
try:
|
|
result = func(*args, **kwargs)
|
|
self._on_success()
|
|
return result
|
|
|
|
except self.expected_exception as e:
|
|
self._on_failure()
|
|
raise e
|
|
|
|
def _should_attempt_reset(self) -> bool:
|
|
"""Check if enough time has passed to attempt reset"""
|
|
return (
|
|
self.last_failure_time is not None and
|
|
time.time() - self.last_failure_time >= self.timeout
|
|
)
|
|
|
|
def _on_success(self):
|
|
"""Handle successful call"""
|
|
if self.state == CircuitState.HALF_OPEN:
|
|
self.state = CircuitState.CLOSED
|
|
logger.info("Circuit breaker state changed to CLOSED")
|
|
|
|
self.failure_count = 0
|
|
|
|
def _on_failure(self):
|
|
"""Handle failed call"""
|
|
self.failure_count += 1
|
|
self.last_failure_time = time.time()
|
|
|
|
if self.failure_count >= self.failure_threshold:
|
|
self.state = CircuitState.OPEN
|
|
logger.warning(
|
|
f"Circuit breaker state changed to OPEN after {self.failure_count} failures"
|
|
)
|
|
|
|
def get_state(self) -> CircuitState:
|
|
"""Get current circuit breaker state"""
|
|
return self.state
|
|
|
|
def reset(self):
|
|
"""Manually reset circuit breaker"""
|
|
self.failure_count = 0
|
|
self.last_failure_time = None
|
|
self.state = CircuitState.CLOSED
|
|
logger.info("Circuit breaker manually reset to CLOSED")
|
|
|
|
|
|
# Global circuit breakers for each service
|
|
user_service_circuit_breaker = CircuitBreaker(CircuitBreakerConfig())
|
|
payment_service_circuit_breaker = CircuitBreaker(CircuitBreakerConfig())
|
|
communication_service_circuit_breaker = CircuitBreaker(CircuitBreakerConfig()) |