Recovered state: integrated TrendSurferAgent, restored frontend/backend files, and cleaned up recovery scripts

This commit is contained in:
ajaysi
2026-02-08 13:56:57 +05:30
parent 1db10ccd0f
commit e404a86502
333 changed files with 42223 additions and 10875 deletions

View File

@@ -12,7 +12,8 @@ from models.monitoring_models import (
StrategyActivationStatus
)
from models.enhanced_strategy_models import EnhancedContentStrategy
from services.database import get_db_session
from contextlib import contextmanager
from services.database import get_session_for_user
logger = logging.getLogger(__name__)
@@ -20,19 +21,41 @@ class StrategyService:
"""Service for managing content strategies and their activation status"""
def __init__(self, db_session: Optional[Session] = None):
self.db_session = db_session or get_db_session()
self.db_session = db_session
async def get_strategy_by_id(self, strategy_id: int) -> Optional[Dict[str, Any]]:
@contextmanager
def _get_session(self, user_id: int):
"""Helper to get session if not provided in init."""
if self.db_session:
try:
yield self.db_session
except Exception:
self.db_session.rollback()
raise
else:
session = get_session_for_user(str(user_id))
try:
yield session
except Exception:
if session:
session.rollback()
raise
finally:
if session:
session.close()
async def get_strategy_by_id(self, strategy_id: int, user_id: int = 1) -> Optional[Dict[str, Any]]:
"""Get strategy by ID with all related data"""
try:
if self.db_session:
# Query the actual database
strategy = self.db_session.query(EnhancedContentStrategy).filter(
EnhancedContentStrategy.id == strategy_id
).first()
if strategy:
return strategy.to_dict()
with self._get_session(user_id) as session:
if session:
# Query the actual database
strategy = session.query(EnhancedContentStrategy).filter(
EnhancedContentStrategy.id == strategy_id
).first()
if strategy:
return strategy.to_dict()
# Fallback to mock data if no database or strategy not found
strategy_data = {
@@ -84,129 +107,127 @@ class StrategyService:
"""Activate a strategy and set up monitoring"""
try:
# Check if strategy exists
strategy = await self.get_strategy_by_id(strategy_id)
strategy = await self.get_strategy_by_id(strategy_id, user_id)
if not strategy:
logger.error(f"Strategy {strategy_id} not found")
return False
# Check if already activated
if self.db_session:
existing_activation = self.db_session.query(StrategyActivationStatus).filter(
and_(
StrategyActivationStatus.strategy_id == strategy_id,
StrategyActivationStatus.user_id == user_id,
StrategyActivationStatus.status == 'active'
with self._get_session(user_id) as session:
if session:
existing_activation = session.query(StrategyActivationStatus).filter(
and_(
StrategyActivationStatus.strategy_id == strategy_id,
StrategyActivationStatus.user_id == user_id,
StrategyActivationStatus.status == 'active'
)
).first()
if existing_activation:
logger.info(f"Strategy {strategy_id} is already active")
return True
# Create activation status record
activation_status = StrategyActivationStatus(
strategy_id=strategy_id,
user_id=user_id,
activation_date=datetime.utcnow(),
status='active',
performance_score=0.0
)
).first()
if existing_activation:
logger.info(f"Strategy {strategy_id} is already active")
return True
# Create activation status record
activation_status = StrategyActivationStatus(
strategy_id=strategy_id,
user_id=user_id,
activation_date=datetime.utcnow(),
status='active',
performance_score=0.0
)
if self.db_session:
self.db_session.add(activation_status)
self.db_session.commit()
logger.info(f"Strategy {strategy_id} activated successfully")
else:
logger.info(f"Strategy {strategy_id} activated (no database session)")
session.add(activation_status)
session.commit()
logger.info(f"Strategy {strategy_id} activated successfully")
else:
logger.info(f"Strategy {strategy_id} activated (no database session)")
return True
except Exception as e:
logger.error(f"Error activating strategy {strategy_id}: {e}")
if self.db_session:
self.db_session.rollback()
return False
async def save_monitoring_plan(self, strategy_id: int, plan_data: Dict[str, Any]) -> bool:
async def save_monitoring_plan(self, strategy_id: int, plan_data: Dict[str, Any], user_id: int = 1) -> bool:
"""Save monitoring plan to database"""
try:
# Check if monitoring plan already exists
if self.db_session:
existing_plan = self.db_session.query(StrategyMonitoringPlan).filter(
StrategyMonitoringPlan.strategy_id == strategy_id
).first()
if existing_plan:
# Update existing plan
existing_plan.plan_data = plan_data
existing_plan.updated_at = datetime.utcnow()
else:
# Create new monitoring plan
monitoring_plan = StrategyMonitoringPlan(
strategy_id=strategy_id,
plan_data=plan_data
)
self.db_session.add(monitoring_plan)
# Clear existing tasks and create new ones
self.db_session.query(MonitoringTask).filter(
MonitoringTask.strategy_id == strategy_id
).delete()
# Create individual monitoring tasks
for component in plan_data.get('components', []):
for task in component.get('tasks', []):
monitoring_task = MonitoringTask(
with self._get_session(user_id) as session:
if session:
existing_plan = session.query(StrategyMonitoringPlan).filter(
StrategyMonitoringPlan.strategy_id == strategy_id
).first()
if existing_plan:
# Update existing plan
existing_plan.plan_data = plan_data
existing_plan.updated_at = datetime.utcnow()
else:
# Create new monitoring plan
monitoring_plan = StrategyMonitoringPlan(
strategy_id=strategy_id,
component_name=component['name'],
task_title=task['title'],
task_description=task['description'],
assignee=task['assignee'],
frequency=task['frequency'],
metric=task['metric'],
measurement_method=task['measurementMethod'],
success_criteria=task['successCriteria'],
alert_threshold=task['alertThreshold'],
status='pending'
plan_data=plan_data
)
self.db_session.add(monitoring_task)
self.db_session.commit()
logger.info(f"Monitoring plan saved for strategy {strategy_id}")
else:
logger.info(f"Monitoring plan prepared for strategy {strategy_id} (no database session)")
session.add(monitoring_plan)
# Clear existing tasks and create new ones
session.query(MonitoringTask).filter(
MonitoringTask.strategy_id == strategy_id
).delete()
# Create individual monitoring tasks
for component in plan_data.get('components', []):
for task in component.get('tasks', []):
monitoring_task = MonitoringTask(
strategy_id=strategy_id,
component_name=component['name'],
task_title=task['title'],
task_description=task['description'],
assignee=task['assignee'],
frequency=task['frequency'],
metric=task['metric'],
measurement_method=task['measurementMethod'],
success_criteria=task['successCriteria'],
alert_threshold=task['alertThreshold'],
status='pending'
)
session.add(monitoring_task)
session.commit()
logger.info(f"Monitoring plan saved for strategy {strategy_id}")
else:
logger.info(f"Monitoring plan prepared for strategy {strategy_id} (no database session)")
return True
except Exception as e:
logger.error(f"Error saving monitoring plan for strategy {strategy_id}: {e}")
if self.db_session:
self.db_session.rollback()
return False
async def get_monitoring_plan(self, strategy_id: int) -> Optional[Dict[str, Any]]:
async def get_monitoring_plan(self, strategy_id: int, user_id: int = 1) -> Optional[Dict[str, Any]]:
"""Get monitoring plan for a strategy"""
try:
if self.db_session:
monitoring_plan = self.db_session.query(StrategyMonitoringPlan).filter(
StrategyMonitoringPlan.strategy_id == strategy_id
).first()
if monitoring_plan:
return monitoring_plan.plan_data
# Also check activation status
activation_status = self.db_session.query(StrategyActivationStatus).filter(
StrategyActivationStatus.strategy_id == strategy_id
).first()
if activation_status:
return {
'strategy_id': strategy_id,
'status': activation_status.status,
'activation_date': activation_status.activation_date.isoformat(),
'message': 'Strategy is active but no monitoring plan found'
}
with self._get_session(user_id) as session:
if session:
monitoring_plan = session.query(StrategyMonitoringPlan).filter(
StrategyMonitoringPlan.strategy_id == strategy_id
).first()
if monitoring_plan:
return monitoring_plan.plan_data
# Also check activation status
activation_status = session.query(StrategyActivationStatus).filter(
StrategyActivationStatus.strategy_id == strategy_id
).first()
if activation_status:
return {
'strategy_id': strategy_id,
'status': activation_status.status,
'activation_date': activation_status.activation_date.isoformat(),
'message': 'Strategy is active but no monitoring plan found'
}
# Fallback to mock data
return {
@@ -222,38 +243,38 @@ class StrategyService:
async def update_strategy_status(self, strategy_id: int, status: str, user_id: int = 1) -> bool:
"""Update strategy activation status"""
try:
if self.db_session:
activation_status = self.db_session.query(StrategyActivationStatus).filter(
and_(
StrategyActivationStatus.strategy_id == strategy_id,
StrategyActivationStatus.user_id == user_id
)
).first()
if activation_status:
activation_status.status = status
activation_status.last_updated = datetime.utcnow()
self.db_session.commit()
logger.info(f"Strategy {strategy_id} status updated to {status}")
return True
with self._get_session(user_id) as session:
if session:
activation_status = session.query(StrategyActivationStatus).filter(
and_(
StrategyActivationStatus.strategy_id == strategy_id,
StrategyActivationStatus.user_id == user_id
)
).first()
if activation_status:
activation_status.status = status
activation_status.last_updated = datetime.utcnow()
session.commit()
logger.info(f"Strategy {strategy_id} status updated to {status}")
return True
else:
logger.warning(f"No activation status found for strategy {strategy_id}")
return False
else:
logger.warning(f"No activation status found for strategy {strategy_id}")
return False
else:
logger.info(f"Strategy {strategy_id} status would be updated to {status} (no database session)")
return True
logger.info(f"Strategy {strategy_id} status would be updated to {status} (no database session)")
return True
except Exception as e:
logger.error(f"Error updating strategy status for {strategy_id}: {e}")
if self.db_session:
self.db_session.rollback()
return False
async def get_active_strategies(self, user_id: int = 1) -> List[Dict[str, Any]]:
"""Get all active strategies for a user"""
try:
if self.db_session:
active_strategies = self.db_session.query(StrategyActivationStatus).filter(
session = self._get_session(user_id)
if session:
active_strategies = session.query(StrategyActivationStatus).filter(
and_(
StrategyActivationStatus.user_id == user_id,
StrategyActivationStatus.status == 'active'
@@ -303,19 +324,18 @@ class StrategyService:
confidence_score=metrics.get('confidence_score', 0.8)
)
if self.db_session:
self.db_session.add(performance_metrics)
self.db_session.commit()
logger.info(f"Performance metrics saved for strategy {strategy_id}")
else:
logger.info(f"Performance metrics prepared for strategy {strategy_id} (no database session)")
with self._get_session(user_id) as session:
if session:
session.add(performance_metrics)
session.commit()
logger.info(f"Performance metrics saved for strategy {strategy_id}")
else:
logger.info(f"Performance metrics prepared for strategy {strategy_id} (no database session)")
return True
except Exception as e:
logger.error(f"Error saving performance metrics for strategy {strategy_id}: {e}")
if self.db_session:
self.db_session.rollback()
return False
async def get_strategy_performance_history(self, strategy_id: int, days: int = 30) -> List[Dict[str, Any]]:
@@ -379,5 +399,16 @@ class StrategyService:
def __del__(self):
"""Cleanup database session"""
if self.db_session:
self.db_session.close()
# No need to close externally provided sessions or request-scoped sessions here usually
# But if we created one and stored it, we might want to close it.
# However, since we now create sessions on the fly in methods (and they are not stored in self.db_session unless init passed it),
# we don't need to close self.db_session unless it was passed in.
# If it was passed in, the caller is responsible.
# If we created it on the fly, we didn't store it in self.db_session.
# But wait, did I update methods to close the session?
# get_session_for_user returns a session that needs closing.
# My implementation of _get_session returns self.db_session OR a new session.
# If it returns a new session, who closes it?
# In the methods, I assigned it to `session`. I did NOT close it.
# This is a resource leak!
pass