From 3ec1da531af8a32e66b3f90c5e601c6fe71a6e9d Mon Sep 17 00:00:00 2001 From: cryptooda Date: Tue, 25 Nov 2025 00:12:23 +0700 Subject: [PATCH] Fix stuck the bundle backtests --- .../Workers/BacktestComputeWorker.cs | 53 ++++++++++++++++--- 1 file changed, 46 insertions(+), 7 deletions(-) diff --git a/src/Managing.Application/Workers/BacktestComputeWorker.cs b/src/Managing.Application/Workers/BacktestComputeWorker.cs index 37cd4af5..501930e2 100644 --- a/src/Managing.Application/Workers/BacktestComputeWorker.cs +++ b/src/Managing.Application/Workers/BacktestComputeWorker.cs @@ -340,7 +340,7 @@ public class BacktestComputeWorker : BackgroundService { try { - await UpdateBundleRequestProgress(job.BundleRequestId.Value, scope.ServiceProvider); + await UpdateBundleRequestProgress(job.BundleRequestId.Value, scope.ServiceProvider, job); } catch (Exception ex) { @@ -421,7 +421,7 @@ public class BacktestComputeWorker : BackgroundService } } - private async Task UpdateBundleRequestProgress(Guid bundleRequestId, IServiceProvider serviceProvider) + private async Task UpdateBundleRequestProgress(Guid bundleRequestId, IServiceProvider serviceProvider, Job? updatedJob = null) { try { @@ -432,10 +432,49 @@ public class BacktestComputeWorker : BackgroundService // Get all jobs for this bundle var jobs = await jobRepository.GetByBundleRequestIdAsync(bundleRequestId); + var totalJobs = jobs.Count(); + + // If we have an updated job, use its current status instead of querying again + // This avoids race conditions where the job was just updated but not yet reflected in the query var completedJobs = jobs.Count(j => j.Status == JobStatus.Completed); var failedJobs = jobs.Count(j => j.Status == JobStatus.Failed); var runningJobs = jobs.Count(j => j.Status == JobStatus.Running); - var totalJobs = jobs.Count(); + + // Adjust counts based on the updated job if provided + if (updatedJob != null) + { + var existingJob = jobs.FirstOrDefault(j => j.Id == updatedJob.Id); + if (existingJob != null) + { + // Remove the old status count + switch (existingJob.Status) + { + case JobStatus.Completed: + completedJobs--; + break; + case JobStatus.Failed: + failedJobs--; + break; + case JobStatus.Running: + runningJobs--; + break; + } + + // Add the new status count + switch (updatedJob.Status) + { + case JobStatus.Completed: + completedJobs++; + break; + case JobStatus.Failed: + failedJobs++; + break; + case JobStatus.Running: + runningJobs++; + break; + } + } + } if (totalJobs == 0) { @@ -467,7 +506,7 @@ public class BacktestComputeWorker : BackgroundService bundleRequest.UpdatedAt = DateTime.UtcNow; // CRITICAL: If bundle is already in a final state (Completed/Failed with CompletedAt set), - // don't overwrite it unless we're detecting a legitimate change + // don't overwrite it unless we're detecting a legitimate inconsistency that needs fixing if (bundleRequest.CompletedAt.HasValue && (bundleRequest.Status == BundleBacktestRequestStatus.Completed || bundleRequest.Status == BundleBacktestRequestStatus.Failed)) @@ -629,7 +668,7 @@ public class BacktestComputeWorker : BackgroundService { try { - await UpdateBundleRequestProgress(stuckJob.BundleRequestId.Value, scope.ServiceProvider); + await UpdateBundleRequestProgress(stuckJob.BundleRequestId.Value, scope.ServiceProvider, stuckJob); } catch (Exception ex) { @@ -706,7 +745,7 @@ public class BacktestComputeWorker : BackgroundService // Update bundle request if this is part of a bundle if (job.BundleRequestId.HasValue) { - await UpdateBundleRequestProgress(job.BundleRequestId.Value, scope.ServiceProvider); + await UpdateBundleRequestProgress(job.BundleRequestId.Value, scope.ServiceProvider, job); } } @@ -868,7 +907,7 @@ public class BacktestComputeWorker : BackgroundService // Update bundle request if this is part of a bundle if (job.BundleRequestId.HasValue) { - await UpdateBundleRequestProgress(job.BundleRequestId.Value, serviceProvider); + await UpdateBundleRequestProgress(job.BundleRequestId.Value, serviceProvider, job); } }