# Async & Concurrency Performance Rules
# =====================================

async_rules:
  - id: "PERF-036"
    name: "Async for I/O operations"
    severity: info
    description: |
      Use async for I/O-bound operations:
      - Database queries (with async driver)
      - External API calls
      - File operations
      - Network requests
    file_pattern: "**/api/**/*.py|**/service*.py"
    suggested_patterns:
      - "async def|await|asyncio"

  - id: "PERF-037"
    name: "Parallel independent operations"
    severity: warning
    description: |
      Multiple independent async operations should run in parallel.
      Use asyncio.gather() instead of sequential awaits.
    file_pattern: "**/*.py"
    anti_patterns:
      - 'await\\s+\\w+\\([^)]*\\)\\s*\\n\\s*await\\s+\\w+\\([^)]*\\)\\s*\\n\\s*await\\s+\\w+\\('
    suggested_patterns:
      - "asyncio\\.gather|asyncio\\.create_task"
    example_bad: |
      user = await get_user(user_id)
      orders = await get_orders(user_id)
      preferences = await get_preferences(user_id)
    example_good: |
      user, orders, preferences = await asyncio.gather(
          get_user(user_id),
          get_orders(user_id),
          get_preferences(user_id)
      )

  - id: "PERF-038"
    name: "Background tasks for slow operations"
    severity: warning
    description: |
      Operations taking > 500ms should run in background:
      - Email sending
      - Report generation
      - External API syncs
      - File processing
    file_pattern: "**/api/**/*.py"
    suggested_patterns:
      - "BackgroundTasks|background_task|celery|rq|dramatiq"

  - id: "PERF-039"
    name: "Connection pooling for HTTP clients"
    severity: warning
    description: |
      HTTP clients should reuse connections.
      Create client once, not per request.
    file_pattern: "**/*client*.py|**/service*.py"
    anti_patterns:
      - 'def\\s+\\w+\\([^)]*\\):\\s*\\n[^}]*requests\\.get\\('
      - 'httpx\\.get\\('
      - 'aiohttp\\.request\\('
    suggested_patterns:
      - "httpx\\.AsyncClient|aiohttp\\.ClientSession|requests\\.Session"
    example_bad: |
      def fetch_data(url):
          response = requests.get(url)  # New connection each time
    example_good: |
      # Use a session (connection pool)
      async with httpx.AsyncClient() as client:
          response = await client.get(url)

  - id: "PERF-040"
    name: "Timeout configuration"
    severity: error
    description: |
      All external calls must have timeouts.
      Without timeouts, requests can hang indefinitely.
    file_pattern: "**/*client*.py|**/service*.py"
    context_patterns:
      - "requests|httpx|aiohttp|urllib"
    required_patterns:
      - "timeout"
    example_bad: |
      response = requests.get(url)
    example_good: |
      response = requests.get(url, timeout=30)

  - id: "PERF-041"
    name: "Connection pool limits"
    severity: info
    description: |
      Configure appropriate connection pool limits:
      - max_connections: Total connections
      - max_keepalive_connections: Idle connections
      - keepalive_expiry: Time before closing idle
    file_pattern: "**/*client*.py"
    suggested_patterns:
      - "max_connections|pool_connections|pool_maxsize"

  - id: "PERF-042"
    name: "Retry with backoff"
    severity: info
    description: |
      External calls should retry with exponential backoff.
      Prevents cascade failures and respects rate limits.
    file_pattern: "**/*client*.py|**/service*.py"
    suggested_patterns:
      - "retry|backoff|tenacity|Retry"

  - id: "PERF-043"
    name: "Circuit breaker pattern"
    severity: info
    description: |
      Use circuit breaker for unreliable external services.
      Prevents repeated failures from slowing down the system.
    file_pattern: "**/*client*.py"
    suggested_patterns:
      - "circuit_breaker|CircuitBreaker|pybreaker"

  - id: "PERF-044"
    name: "Task queues for heavy processing"
    severity: info
    description: |
      Heavy processing should use task queues:
      - Celery
      - RQ (Redis Queue)
      - Dramatiq
      - Huey
    file_pattern: "**/tasks/**/*.py"
    suggested_patterns:
      - "celery|rq|dramatiq|huey|@task"

  - id: "PERF-045"
    name: "Worker pool sizing"
    severity: info
    description: |
      Size worker pools appropriately:
      - CPU-bound: Number of cores
      - I/O-bound: Higher multiplier (2-4x cores)
      - Memory-constrained: Based on available RAM
