Skip to content

Commit b3c1f58

Browse files
committed
fix(tests): resolve flaky FailedJob_CanBeRetried test
Replace fixed Task.Delay(200) calls with proper synchronization using TaskCompletionSource signals. The test was failing on slow CI machines because 200ms wasn't enough time for job processing to complete before the retry was enqueued. The handler now exposes FirstInvocationCompleted and SecondInvocationCompleted tasks that the test awaits with a 5-second timeout, making the test deterministic regardless of machine speed.
1 parent ec457ca commit b3c1f58

File tree

1 file changed

+23
-2
lines changed

1 file changed

+23
-2
lines changed

tests/Octopus.Server.Processing.Tests/ProcessingWorkerServiceTests.cs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,10 @@ public async Task FailedJob_CanBeRetried()
270270
Version = 1
271271
};
272272
await queue.EnqueueAsync(envelope1);
273-
await Task.Delay(200);
273+
274+
// Wait for first invocation to complete (with timeout)
275+
var firstCompleted = await Task.WhenAny(handler.FirstInvocationCompleted, Task.Delay(5000));
276+
Assert.True(firstCompleted == handler.FirstInvocationCompleted, "First invocation did not complete within timeout");
274277

275278
// Retry the same job
276279
var envelope2 = new JobEnvelope
@@ -282,7 +285,10 @@ public async Task FailedJob_CanBeRetried()
282285
Version = 1
283286
};
284287
await queue.EnqueueAsync(envelope2);
285-
await Task.Delay(200);
288+
289+
// Wait for second invocation to complete (with timeout)
290+
var secondCompleted = await Task.WhenAny(handler.SecondInvocationCompleted, Task.Delay(5000));
291+
Assert.True(secondCompleted == handler.SecondInvocationCompleted, "Second invocation did not complete within timeout");
286292

287293
cts.Cancel();
288294
queue.Complete();
@@ -313,13 +319,28 @@ public class FailingThenSucceedingHandler : IJobHandler<TestJobPayload>
313319
public string JobType => "TestJob";
314320
public int InvocationCount { get; private set; }
315321

322+
private readonly TaskCompletionSource _firstInvocation = new(TaskCreationOptions.RunContinuationsAsynchronously);
323+
private readonly TaskCompletionSource _secondInvocation = new(TaskCreationOptions.RunContinuationsAsynchronously);
324+
325+
/// <summary>
326+
/// Completes when the first invocation has finished (after throwing).
327+
/// </summary>
328+
public Task FirstInvocationCompleted => _firstInvocation.Task;
329+
330+
/// <summary>
331+
/// Completes when the second invocation has finished (successfully).
332+
/// </summary>
333+
public Task SecondInvocationCompleted => _secondInvocation.Task;
334+
316335
public Task HandleAsync(string jobId, TestJobPayload payload, CancellationToken cancellationToken = default)
317336
{
318337
InvocationCount++;
319338
if (InvocationCount == 1)
320339
{
340+
_firstInvocation.TrySetResult();
321341
throw new InvalidOperationException("Simulated failure on first attempt");
322342
}
343+
_secondInvocation.TrySetResult();
323344
return Task.CompletedTask;
324345
}
325346
}

0 commit comments

Comments
 (0)