mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-02-02 10:55:14 -05:00
fix(backend): Clean up orphaned schedules without schedule_id
Old scheduled jobs created before schedule_id was added to GraphExecutionJobArgs have schedule_id=None. When these fail validation, _handle_graph_validation_error could not unschedule them, causing them to fire repeatedly and generate ~60K+ Sentry errors (AUTOGPT-SERVER-6W2 and AUTOGPT-SERVER-6W3). Fix: Add _cleanup_old_schedules_without_id() which finds schedules for the graph but only removes those with schedule_id=None (legacy jobs). This preserves any valid newer schedules the user may have created, unlike the broader _cleanup_orphaned_schedules_for_graph() which removes all schedules for a graph.
This commit is contained in:
@@ -193,9 +193,11 @@ async def _handle_graph_validation_error(args: "GraphExecutionJobArgs") -> None:
|
||||
user_id=args.user_id,
|
||||
)
|
||||
else:
|
||||
logger.error(
|
||||
f"Unable to unschedule graph: {args.graph_id} as this is an old job with no associated schedule_id please remove manually"
|
||||
logger.warning(
|
||||
f"Old scheduled job for graph {args.graph_id} (user {args.user_id}) "
|
||||
f"has no schedule_id, attempting targeted cleanup"
|
||||
)
|
||||
await _cleanup_old_schedules_without_id(args.graph_id, args.user_id)
|
||||
|
||||
|
||||
async def _handle_graph_not_available(
|
||||
@@ -238,6 +240,35 @@ async def _cleanup_orphaned_schedules_for_graph(graph_id: str, user_id: str) ->
|
||||
)
|
||||
|
||||
|
||||
async def _cleanup_old_schedules_without_id(graph_id: str, user_id: str) -> None:
|
||||
"""Remove only schedules that have no schedule_id in their job args.
|
||||
|
||||
Unlike _cleanup_orphaned_schedules_for_graph (which removes ALL schedules
|
||||
for a graph), this only targets legacy jobs created before schedule_id was
|
||||
added to GraphExecutionJobArgs, preserving any valid newer schedules.
|
||||
"""
|
||||
scheduler_client = get_scheduler_client()
|
||||
schedules = await scheduler_client.get_execution_schedules(
|
||||
graph_id=graph_id, user_id=user_id
|
||||
)
|
||||
|
||||
for schedule in schedules:
|
||||
if schedule.schedule_id is not None:
|
||||
continue
|
||||
try:
|
||||
await scheduler_client.delete_schedule(
|
||||
schedule_id=schedule.id, user_id=user_id
|
||||
)
|
||||
logger.info(
|
||||
f"Cleaned up old schedule {schedule.id} (no schedule_id) "
|
||||
f"for graph {graph_id}"
|
||||
)
|
||||
except Exception:
|
||||
logger.exception(
|
||||
f"Failed to delete old schedule {schedule.id} for graph {graph_id}"
|
||||
)
|
||||
|
||||
|
||||
def cleanup_expired_files():
|
||||
"""Clean up expired files from cloud storage."""
|
||||
# Wait for completion
|
||||
|
||||
Reference in New Issue
Block a user