Merge PR #396: Validate plan.date and add narrower exception handling

- Add date validation: validate plan.date is ISO format before computing yesterday
- Log clear warning (plan_id, user_id, plan_date, reason) if date parsing fails
- Replace silent 'except Exception: pass' with explicit SQLAlchemyError handling
- Log detailed warnings (plan_id, user_id, plan_date, yesterday_date, error details) on DB errors
- Keep failures non-fatal to indexing behavior (continue with today's indexing)
- Preserve dependencies normalization helper and its usage in yesterday payloads
- Preserve proper feedback scoring (uses task.status, handles all negative statuses)
- Keep contextuality validation response fields (quality_status, contextuality_validation)
- Improve observability while maintaining system robustness
This commit is contained in:
ajaysi
2026-03-08 18:39:55 +05:30

View File

@@ -5,6 +5,7 @@ import json
from loguru import logger from loguru import logger
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from sqlalchemy.exc import SQLAlchemyError
from middleware.auth_middleware import get_current_user from middleware.auth_middleware import get_current_user
from services.database import get_db from services.database import get_db
@@ -115,11 +116,21 @@ async def get_today_workflow(
if created: if created:
asyncio.create_task(_index_tasks_to_sif(user_id, plan.date, response_tasks, label="today")) asyncio.create_task(_index_tasks_to_sif(user_id, plan.date, response_tasks, label="today"))
try: from datetime import date as date_type, timedelta
from datetime import date as date_type, timedelta
try:
parsed_plan_date = date_type.fromisoformat(plan.date)
except ValueError:
logger.warning(
"Invalid plan.date format; skipping yesterday indexing plan_id={} user_id={} plan_date={} reason={}",
plan.id,
user_id,
plan.date,
"plan.date is not in ISO format YYYY-MM-DD",
)
else:
y_str = (parsed_plan_date - timedelta(days=1)).isoformat()
y_str = (date_type.fromisoformat(plan.date) - timedelta(days=1)).isoformat()
def _fetch_yesterday(): def _fetch_yesterday():
y_plan = ( y_plan = (
db.query(DailyWorkflowPlan) db.query(DailyWorkflowPlan)
@@ -136,24 +147,33 @@ async def get_today_workflow(
return y_tasks return y_tasks
return [] return []
y_tasks = await run_in_threadpool(_fetch_yesterday) try:
y_tasks = await run_in_threadpool(_fetch_yesterday)
if y_tasks: except SQLAlchemyError as db_error:
y_response = [] logger.warning(
for t in y_tasks: "Failed to fetch yesterday tasks; skipping yesterday indexing plan_id={} user_id={} plan_date={} yesterday_date={} error_class={} error_message={}",
y_response.append( plan.id,
{ user_id,
"id": str(t.id), plan.date,
"pillarId": t.pillar_id, y_str,
"title": t.title, type(db_error).__name__,
"description": t.description, str(db_error),
"status": "skipped" if t.status == "dismissed" else t.status, )
"dependencies": _normalize_dependencies(t.dependencies), else:
} if y_tasks:
) y_response = []
asyncio.create_task(_index_tasks_to_sif(user_id, y_str, y_response, label="yesterday")) for t in y_tasks:
except Exception: y_response.append(
pass {
"id": str(t.id),
"pillarId": t.pillar_id,
"title": t.title,
"description": t.description,
"status": "skipped" if t.status == "dismissed" else t.status,
"dependencies": _normalize_dependencies(t.dependencies),
}
)
asyncio.create_task(_index_tasks_to_sif(user_id, y_str, y_response, label="yesterday"))
return { return {
"success": True, "success": True,