From 172fae7f401948797611d9535d8fedfd85e5f0a7 Mon Sep 17 00:00:00 2001 From: vithobaa Date: Tue, 30 Jun 2026 11:56:25 +0530 Subject: [PATCH] fix: instantly create execution from scheduler instead of waiting for agent poll --- .../localagent_cloud/service/AgentService.java | 8 +++++--- .../service/CronExecutionEngine.java | 14 +++++++++++--- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/master/src/main/java/com/autopilot/localagent_cloud/service/AgentService.java b/master/src/main/java/com/autopilot/localagent_cloud/service/AgentService.java index 179f99f..2ad4c55 100644 --- a/master/src/main/java/com/autopilot/localagent_cloud/service/AgentService.java +++ b/master/src/main/java/com/autopilot/localagent_cloud/service/AgentService.java @@ -211,11 +211,12 @@ public class AgentService { .filter(s -> agentOrgId == null || agentOrgId.equals(s.getOrgId())) .toList(); - if (activeJobs.isEmpty()) { - return ResponseEntity.noContent().build(); + if (!activeJobs.isEmpty()) { + unwrapSchedulerToJobs(activeJobs.get(0), agentOrgId); } - Scheduler job = activeJobs.get(0); + @Transactional + public void unwrapSchedulerToJobs(Scheduler job, Long agentOrgId) { job.setStatus("processing"); schedulerRepository.save(job); @@ -297,6 +298,7 @@ public class AgentService { } } } + } // Bug fix: replaced unbounded recursion with a simple retry — pick up one of the jobs just created. // The recursive approach had no depth limit and could cause a StackOverflowError diff --git a/master/src/main/java/com/autopilot/localagent_cloud/service/CronExecutionEngine.java b/master/src/main/java/com/autopilot/localagent_cloud/service/CronExecutionEngine.java index a4a55b1..467a80e 100644 --- a/master/src/main/java/com/autopilot/localagent_cloud/service/CronExecutionEngine.java +++ b/master/src/main/java/com/autopilot/localagent_cloud/service/CronExecutionEngine.java @@ -19,9 +19,11 @@ public class CronExecutionEngine { private static final Logger logger = LoggerFactory.getLogger(CronExecutionEngine.class); private final SchedulerRepository schedulerRepository; + private final AgentService agentService; - public CronExecutionEngine(SchedulerRepository schedulerRepository) { + public CronExecutionEngine(SchedulerRepository schedulerRepository, AgentService agentService) { this.schedulerRepository = schedulerRepository; + this.agentService = agentService; } // Runs at the 0th second of every minute @@ -80,6 +82,7 @@ public class CronExecutionEngine { // Check time match (truncated to minutes) LocalTime nowTime = now.toLocalTime().truncatedTo(ChronoUnit.MINUTES); LocalTime targetTime = scheduledTime.truncatedTo(ChronoUnit.MINUTES); + logger.info("Evaluating schedule ID {} | Timezone: {} | nowTime: {} | targetTime: {}", s.getId(), s.getTimezone(), nowTime, targetTime); if (!nowTime.equals(targetTime)) { return false; } @@ -199,7 +202,12 @@ public class CronExecutionEngine { job.setStatus("active"); job.setOrgId(original.getOrgId()); job.setEnvironmentId(original.getEnvironmentId()); - schedulerRepository.save(job); - logger.info("Queued test suite '{}' for execution via local agent polling", job.getTestSuiteName()); + job = schedulerRepository.save(job); + logger.info("Queued test suite '{}' for execution. Instantly unwrapping to executions.", job.getTestSuiteName()); + try { + agentService.unwrapSchedulerToJobs(job, original.getOrgId()); + } catch(Exception e) { + logger.error("Failed to unwrap scheduler into execution: " + e.getMessage(), e); + } } }