diff --git a/src/Managing.Application/Backtests/BacktestExecutor.cs b/src/Managing.Application/Backtests/BacktestExecutor.cs
index b835c295..ee7bf5ba 100644
--- a/src/Managing.Application/Backtests/BacktestExecutor.cs
+++ b/src/Managing.Application/Backtests/BacktestExecutor.cs
@@ -410,12 +410,6 @@ public class BacktestExecutor
if (save && user != null)
{
await _backtestRepository.InsertBacktestForUserAsync(user, result);
-
- // Update bundle request if provided
- if (bundleRequestId.HasValue)
- {
- await UpdateBundleRequestWithBacktestResult(user, bundleRequestId.Value, result);
- }
}
// Send notification if backtest meets criteria
@@ -574,150 +568,6 @@ public class BacktestExecutor
return tradingBot;
}
- ///
- /// Optimized backtest step execution - delegate to standard Run but with backtest optimizations
- ///
- private async Task RunOptimizedBacktestStep(TradingBotBase tradingBot)
- {
- // Use the standard Run method but ensure it's optimized for backtests
- }
-
-
- ///
- /// Updates bundle request with the completed backtest result
- ///
- private async Task UpdateBundleRequestWithBacktestResult(User user, Guid bundleRequestId, Backtest backtest)
- {
- try
- {
- using var scope = _scopeFactory.CreateScope();
- var backtestRepository = scope.ServiceProvider.GetRequiredService();
- var jobRepository = scope.ServiceProvider.GetRequiredService();
- var webhookService = scope.ServiceProvider.GetRequiredService();
-
- // Get bundle request
- var bundleRequest = backtestRepository.GetBundleBacktestRequestByIdForUser(user, bundleRequestId);
- if (bundleRequest == null)
- {
- _logger.LogWarning("Bundle request {BundleRequestId} not found for user {UserId}", bundleRequestId,
- user.Id);
- return;
- }
-
- var previousStatus = bundleRequest.Status;
-
- // Get all jobs for this bundle to calculate progress
- var jobs = await jobRepository.GetByBundleRequestIdAsync(bundleRequestId);
- 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();
-
- // Update bundle request progress (always update counters regardless of status)
- bundleRequest.CompletedBacktests = completedJobs;
- bundleRequest.FailedBacktests = failedJobs;
- 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
- if (bundleRequest.CompletedAt.HasValue &&
- (bundleRequest.Status == BundleBacktestRequestStatus.Completed ||
- bundleRequest.Status == BundleBacktestRequestStatus.Failed))
- {
- // Bundle already finalized, only update if job counts indicate it should be re-opened
- // (This shouldn't happen in normal flow, but guards against race conditions)
- if (completedJobs + failedJobs == totalJobs)
- {
- _logger.LogDebug(
- "Bundle {BundleRequestId} already completed/failed. Skipping status update.",
- bundleRequestId);
- // Progress counters already updated above, just return
- return;
- }
- else
- {
- _logger.LogWarning(
- "Bundle {BundleRequestId} was marked as completed/failed but has incomplete jobs ({Completed}+{Failed}/{Total}). Reopening.",
- bundleRequestId, completedJobs, failedJobs, totalJobs);
- // Allow the update to proceed to fix inconsistent state
- }
- }
-
- // Update status based on job states
- if (completedJobs + failedJobs == totalJobs)
- {
- // All jobs completed or failed
- if (failedJobs == 0)
- {
- bundleRequest.Status = BundleBacktestRequestStatus.Completed;
- }
- else if (completedJobs == 0)
- {
- bundleRequest.Status = BundleBacktestRequestStatus.Failed;
- bundleRequest.ErrorMessage = "All backtests failed";
- }
- else
- {
- bundleRequest.Status = BundleBacktestRequestStatus.Completed;
- bundleRequest.ErrorMessage = $"{failedJobs} backtests failed";
- }
-
- bundleRequest.CompletedAt = DateTime.UtcNow;
- bundleRequest.CurrentBacktest = null;
- }
- else if (runningJobs > 0 || completedJobs > 0 || failedJobs > 0)
- {
- // Some jobs are running, or some have completed/failed (meaning work has started)
- // Once a bundle has started processing, it should stay "Running" until all jobs are done
- bundleRequest.Status = BundleBacktestRequestStatus.Running;
- }
- // If all jobs are still pending (completedJobs = 0, failedJobs = 0, runningJobs = 0),
- // keep the current status (likely Pending)
-
- // Update results list with the new backtest ID
- var resultsList = bundleRequest.Results?.ToList() ?? new List();
- if (!resultsList.Contains(backtest.Id))
- {
- resultsList.Add(backtest.Id);
- bundleRequest.Results = resultsList;
- }
-
- await backtestRepository.UpdateBundleBacktestRequestAsync(bundleRequest);
-
- // Send webhook notification if bundle request just completed
- if (previousStatus != BundleBacktestRequestStatus.Completed &&
- bundleRequest.Status == BundleBacktestRequestStatus.Completed &&
- !string.IsNullOrEmpty(user.TelegramChannel))
- {
- var message =
- $"✅ Bundle backtest '{bundleRequest.Name}' (ID: {bundleRequest.RequestId}) completed successfully. " +
- $"Completed: {completedJobs}/{totalJobs} backtests" +
- (failedJobs > 0 ? $", Failed: {failedJobs}" : "") +
- $". Results: {resultsList.Count} backtest(s) generated.";
-
- await webhookService.SendMessage(message, user.TelegramChannel);
- }
- else if (previousStatus != BundleBacktestRequestStatus.Failed &&
- bundleRequest.Status == BundleBacktestRequestStatus.Failed &&
- !string.IsNullOrEmpty(user.TelegramChannel))
- {
- var message = $"❌ Bundle backtest '{bundleRequest.Name}' (ID: {bundleRequest.RequestId}) failed. " +
- $"All {totalJobs} backtests failed. Error: {bundleRequest.ErrorMessage}";
-
- await webhookService.SendMessage(message, user.TelegramChannel);
- }
-
- _logger.LogInformation(
- "Updated bundle request {BundleRequestId} with backtest {BacktestId}: {Completed}/{Total} completed, {Failed} failed, {Running} running",
- bundleRequestId, backtest.Id, completedJobs, totalJobs, failedJobs, runningJobs);
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, "Failed to update bundle request {BundleRequestId} with backtest {BacktestId}",
- bundleRequestId, backtest.Id);
- }
- }
-
///
/// Sends notification if backtest meets criteria
///
diff --git a/src/Managing.Application/Workers/BacktestComputeWorker.cs b/src/Managing.Application/Workers/BacktestComputeWorker.cs
index c9f5d5a2..e3f899d0 100644
--- a/src/Managing.Application/Workers/BacktestComputeWorker.cs
+++ b/src/Managing.Application/Workers/BacktestComputeWorker.cs
@@ -343,7 +343,18 @@ public class BacktestComputeWorker : BackgroundService
"Completed backtest job {JobId}. Score: {Score}, PnL: {PnL}, Duration: {DurationMinutes:F1} minutes",
job.Id, result.Score, result.FinalPnl, elapsedTime.TotalMinutes);
- // Bundle request is now updated in the BacktestExecutor
+ // Update bundle request progress if this job is part of a bundle
+ if (job.BundleRequestId.HasValue)
+ {
+ try
+ {
+ await UpdateBundleRequestProgress(job.BundleRequestId.Value, scope.ServiceProvider);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error updating bundle request progress for job {JobId}", job.Id);
+ }
+ }
}
catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested)
{