annator-atom / backend /ai /intelligence_background_worker.py
techprotrade's picture
Full stack ATOM backend + AIMONEYFLOW clients (port 7860)
68b32d7 verified
Raw
History Blame Contribute Delete
3.34 kB
import asyncio
from datetime import datetime
import logging
from typing import Set
from ai.data_intelligence import DataIntelligenceEngine, PlatformType
from core.notification_manager import notification_manager
logger = logging.getLogger(__name__)
class IntelligenceBackgroundWorker:
"""
Background worker that periodically runs anomaly detection
and broadcasts critical insights via WebSockets.
"""
def __init__(self, interval_seconds: int = 300): # Default 5 mins
self.engine = DataIntelligenceEngine()
self.interval = interval_seconds
self.seen_anomalies: Set[str] = set()
self.is_running = False
self._task = None
async def start(self):
"""Start the background monitoring task"""
if self.is_running:
return
self.is_running = True
self._task = asyncio.create_task(self._run_loop())
logger.info(f"IntelligenceBackgroundWorker started with interval {self.interval}s")
async def stop(self):
"""Stop the background task"""
if not self.is_running:
return
self.is_running = False
if self._task:
self._task.cancel()
try:
await self._task
except asyncio.CancelledError:
pass
logger.info("IntelligenceBackgroundWorker stopped")
async def _run_loop(self):
"""Continuous loop for anomaly detection"""
while self.is_running:
try:
await self._perform_scan()
except Exception as e:
logger.error(f"Error during intelligence scan: {e}")
await asyncio.sleep(self.interval)
async def _perform_scan(self):
"""Single scan iteration"""
# 1. Optionally refresh data if registry is empty
if not self.engine.entity_registry:
logger.info("Initializing background engine registry with first-run data")
for platform in [PlatformType.SALESFORCE, PlatformType.JIRA, PlatformType.ASANA]:
data = await self.engine._get_platform_data(platform)
if data:
await self.engine.ingest_platform_data(platform, data)
# 2. Run detection
anomalies = await self.engine.detect_anomalies()
# 3. Process and broadcast NEW critical anomalies
for anomaly in anomalies:
if anomaly.severity == "critical" and anomaly.anomaly_id not in self.seen_anomalies:
logger.info(f"🚨 New Critical Anomaly Detected: {anomaly.title}")
# Broadcast to the default 'demo-workspace' (or handle per-workspace logic)
await notification_manager.send_urgent_notification(
message=f"CRITICAL RISK: {anomaly.description}",
workspace_id="demo-workspace", # Standard for the demo env
channel="ui"
)
self.seen_anomalies.add(anomaly.anomaly_id)
# Cleanup old seen anomalies periodically to allow re-alerting if needed (optional)
if len(self.seen_anomalies) > 1000:
self.seen_anomalies.clear()
# Global worker instance
intelligence_worker = IntelligenceBackgroundWorker()