- Add async Redis client singleton (redis_client.py) for caching and arq pool
- Add arq job functions (jobs.py) for background LLM processing
- Cache ask/explain LLM responses with TTL (1h ask, 24h explain)
- Add async mode to /api/ask: enqueue job, return job_id, poll /api/jobs/{id}
- Add GET /api/jobs/{job_id} endpoint for job status polling
- Add arq worker service to docker-compose (dev + prod)
- Switch from Redis to Valkey (BSD fork) in Docker Compose
- Add REDIS_URL config setting
- Add tests for cache hit, async mode, and job status
69 lines
2.9 KiB
Python
69 lines
2.9 KiB
Python
import mongomock
|
|
import pytest
|
|
from fastapi.testclient import TestClient
|
|
|
|
|
|
@pytest.fixture(scope="function")
|
|
def mock_events_collection():
|
|
client = mongomock.MongoClient()
|
|
db = client["micro_soc"]
|
|
coll = db["events"]
|
|
return coll
|
|
|
|
|
|
@pytest.fixture(scope="function")
|
|
def mock_watermarks_collection():
|
|
client = mongomock.MongoClient()
|
|
db = client["micro_soc"]
|
|
coll = db["watermarks"]
|
|
return coll
|
|
|
|
|
|
@pytest.fixture(scope="function")
|
|
def client(mock_events_collection, mock_watermarks_collection, monkeypatch):
|
|
monkeypatch.setattr("database.events_collection", mock_events_collection)
|
|
monkeypatch.setattr("database.saved_searches_collection", mock_events_collection)
|
|
monkeypatch.setattr("routes.fetch.events_collection", mock_events_collection)
|
|
monkeypatch.setattr("routes.events.events_collection", mock_events_collection)
|
|
monkeypatch.setattr("routes.ask.events_collection", mock_events_collection)
|
|
monkeypatch.setattr("routes.saved_searches.saved_searches_collection", mock_events_collection)
|
|
monkeypatch.setattr("watermark.watermarks_collection", mock_watermarks_collection)
|
|
monkeypatch.setattr("routes.health.watermarks_collection", mock_watermarks_collection)
|
|
monkeypatch.setattr("routes.fetch.get_watermark", lambda source: None)
|
|
monkeypatch.setattr("routes.fetch.set_watermark", lambda source, ts: None)
|
|
monkeypatch.setattr("auth.AUTH_ENABLED", False)
|
|
monkeypatch.setattr("routes.mcp.AUTH_ENABLED", False)
|
|
monkeypatch.setattr("config.PRIVACY_SERVICES", set())
|
|
monkeypatch.setattr("config.PRIVACY_SENSITIVE_OPERATIONS", set())
|
|
monkeypatch.setattr("routes.events.PRIVACY_SERVICES", set())
|
|
monkeypatch.setattr("routes.events.PRIVACY_SENSITIVE_OPERATIONS", set())
|
|
monkeypatch.setattr("routes.ask.PRIVACY_SERVICES", set())
|
|
monkeypatch.setattr("routes.ask.PRIVACY_SENSITIVE_OPERATIONS", set())
|
|
monkeypatch.setattr("database.db.command", lambda cmd: {"ok": 1} if cmd == "ping" else {})
|
|
|
|
# Mock audit trail and rules collections so tests don't wait on real MongoDB
|
|
audit_client = mongomock.MongoClient()
|
|
audit_db = audit_client["micro_soc"]
|
|
monkeypatch.setattr("audit_trail.audit_collection", audit_db["aoc_audit"])
|
|
monkeypatch.setattr("rules.alerts_collection", audit_db["alerts"])
|
|
monkeypatch.setattr("rules.rules_collection", audit_db["alert_rules"])
|
|
monkeypatch.setattr("routes.rules.rules_collection", audit_db["alert_rules"])
|
|
|
|
# Mock Redis so tests don't require a running Redis server
|
|
class FakeRedis:
|
|
async def get(self, key):
|
|
return None
|
|
async def setex(self, key, ttl, value):
|
|
pass
|
|
|
|
async def fake_get_arq_pool():
|
|
return FakeRedis()
|
|
|
|
monkeypatch.setattr("redis_client.get_arq_pool", fake_get_arq_pool)
|
|
monkeypatch.setattr("routes.ask.get_arq_pool", fake_get_arq_pool)
|
|
monkeypatch.setattr("routes.jobs.get_redis", fake_get_arq_pool)
|
|
|
|
from main import app
|
|
|
|
return TestClient(app)
|