192 lines
6.2 KiB
Python
192 lines
6.2 KiB
Python
"""
|
||
Energy calculation worker module.
|
||
|
||
This module provides a worker that consumes energy calculation tasks
|
||
from RabbitMQ and executes energy calculation operations.
|
||
"""
|
||
|
||
import logging
|
||
from typing import Dict, List, Optional
|
||
from sqlalchemy.orm import Session
|
||
|
||
from app.services.energy_service import (
|
||
calculate_and_store_energy_score,
|
||
get_energy_score_by_match_and_team
|
||
)
|
||
from app.schemas.energy_score import EnergyScoreCalculationRequest
|
||
from app.ml.energy_calculator import (
|
||
calculate_energy_score,
|
||
get_source_weights
|
||
)
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
|
||
class EnergyWorker:
|
||
"""
|
||
Worker for processing energy calculation tasks.
|
||
|
||
Features:
|
||
- Consumes tasks from energy_calculation_tasks queue
|
||
- Executes energy score calculations
|
||
- Publishes results to results queue
|
||
- Handles errors with retries
|
||
- Structured logging
|
||
"""
|
||
|
||
def __init__(self):
|
||
"""Initialize energy calculation worker."""
|
||
# No initialization needed for energy worker
|
||
# Energy calculator is initialized in ml/energy_calculator
|
||
pass
|
||
|
||
def execute_energy_calculation_task(
|
||
self,
|
||
task: Dict,
|
||
db: Session
|
||
) -> Dict:
|
||
"""
|
||
Execute an energy calculation task.
|
||
|
||
Args:
|
||
task: Energy calculation task data
|
||
db: Database session
|
||
|
||
Returns:
|
||
Dictionary with energy calculation results
|
||
"""
|
||
match_id = task.get('match_id')
|
||
team_id = task.get('team_id')
|
||
twitter_sentiments = task.get('twitter_sentiments', [])
|
||
reddit_sentiments = task.get('reddit_sentiments', [])
|
||
rss_sentiments = task.get('rss_sentiments', [])
|
||
tweets_with_timestamps = task.get('tweets_with_timestamps', [])
|
||
|
||
logger.info(
|
||
f"🔧 Executing energy calculation task: "
|
||
f"match_id={match_id}, team_id={team_id}"
|
||
)
|
||
|
||
try:
|
||
# Check if energy score already exists
|
||
existing_score = get_energy_score_by_match_and_team(
|
||
db, match_id, team_id
|
||
)
|
||
|
||
if existing_score:
|
||
logger.info(
|
||
f"ℹ️ Energy score already exists for "
|
||
f"match {match_id}, team {team_id}"
|
||
)
|
||
return {
|
||
'energy_score': existing_score.score,
|
||
'confidence': existing_score.confidence,
|
||
'sources_used': existing_score.sources_used,
|
||
'status': 'success',
|
||
'metadata': {
|
||
'match_id': match_id,
|
||
'team_id': team_id,
|
||
'updated_existing': True
|
||
}
|
||
}
|
||
|
||
# Create calculation request
|
||
request = EnergyScoreCalculationRequest(
|
||
match_id=match_id,
|
||
team_id=team_id,
|
||
twitter_sentiments=twitter_sentiments,
|
||
reddit_sentiments=reddit_sentiments,
|
||
rss_sentiments=rss_sentiments,
|
||
tweets_with_timestamps=tweets_with_timestamps
|
||
)
|
||
|
||
# Calculate and store energy score
|
||
energy_score = calculate_and_store_energy_score(db, request)
|
||
|
||
logger.info(
|
||
f"✅ Energy calculation completed: "
|
||
f"score={energy_score.score:.2f}, "
|
||
f"confidence={energy_score.confidence:.2f}"
|
||
)
|
||
|
||
return {
|
||
'energy_score': energy_score.score,
|
||
'confidence': energy_score.confidence,
|
||
'sources_used': energy_score.sources_used,
|
||
'status': 'success',
|
||
'metadata': {
|
||
'match_id': match_id,
|
||
'team_id': team_id,
|
||
'twitter_score': energy_score.twitter_score,
|
||
'reddit_score': energy_score.reddit_score,
|
||
'rss_score': energy_score.rss_score,
|
||
'temporal_factor': energy_score.temporal_factor
|
||
}
|
||
}
|
||
|
||
except Exception as e:
|
||
logger.error(f"❌ Energy calculation task failed: {e}")
|
||
return {
|
||
'energy_score': 0.0,
|
||
'confidence': 0.0,
|
||
'sources_used': [],
|
||
'status': 'error',
|
||
'error': str(e)
|
||
}
|
||
|
||
def calculate_mock_energy(
|
||
self,
|
||
twitter_sentiments: List[Dict],
|
||
reddit_sentiments: List[Dict],
|
||
rss_sentiments: List[Dict] = None,
|
||
tweets_with_timestamps: List[Dict] = None
|
||
) -> Dict:
|
||
"""
|
||
Calculate energy score without storing to database (for testing).
|
||
|
||
Args:
|
||
twitter_sentiments: List of Twitter sentiment scores
|
||
reddit_sentiments: List of Reddit sentiment scores
|
||
rss_sentiments: Optional list of RSS sentiment scores
|
||
tweets_with_timestamps: Optional list of tweets with timestamps
|
||
|
||
Returns:
|
||
Dictionary with energy calculation results
|
||
"""
|
||
try:
|
||
result = calculate_energy_score(
|
||
match_id=0,
|
||
team_id=0,
|
||
twitter_sentiments=twitter_sentiments,
|
||
reddit_sentiments=reddit_sentiments,
|
||
rss_sentiments=rss_sentiments or [],
|
||
tweets_with_timestamps=tweets_with_timestamps or []
|
||
)
|
||
|
||
return {
|
||
'energy_score': result['score'],
|
||
'confidence': result['confidence'],
|
||
'sources_used': result['sources_used'],
|
||
'status': 'success'
|
||
}
|
||
|
||
except Exception as e:
|
||
logger.error(f"❌ Mock energy calculation failed: {e}")
|
||
return {
|
||
'energy_score': 0.0,
|
||
'confidence': 0.0,
|
||
'sources_used': [],
|
||
'status': 'error',
|
||
'error': str(e)
|
||
}
|
||
|
||
|
||
def create_energy_worker() -> EnergyWorker:
|
||
"""
|
||
Factory function to create an energy calculation worker.
|
||
|
||
Returns:
|
||
Configured EnergyWorker instance
|
||
"""
|
||
return EnergyWorker()
|