fix(cv): sync operation terminal state
CI and Deploy / test (pull_request) Successful in 5m12s
CI and Deploy / deploy (pull_request) Has been skipped

This commit is contained in:
cesnimda
2026-08-15 19:45:44 +02:00
parent 7185491a05
commit dbff0f8d49
6 changed files with 123 additions and 3 deletions
@@ -105,6 +105,71 @@ public sealed class CvProcessingOperationTests
Assert.Null(run.CompletedAtUtc);
}
[Fact]
public async Task Cancellation_before_claim_and_retry_keep_extraction_history_in_sync()
{
await using var fixture = await Fixture.CreateAsync();
await fixture.SeedUserAsync();
Guid operationId;
await using (var scope = fixture.Provider.CreateAsyncScope())
{
using var owner = scope.ServiceProvider.GetRequiredService<CurrentUserService>().UseBackgroundUser("user-1");
Assert.IsType<AcceptedResult>(await CreateController(scope.ServiceProvider).Upload(File()));
operationId = (await scope.ServiceProvider.GetRequiredService<JobTrackerContext>().UserOperations.SingleAsync()).Id;
}
await using (var scope = fixture.Provider.CreateAsyncScope())
{
using var owner = scope.ServiceProvider.GetRequiredService<CurrentUserService>().UseBackgroundUser("user-1");
var store = scope.ServiceProvider.GetRequiredService<UserOperationStore>();
Assert.True(await store.RequestCancellationAsync(operationId, default));
var cancelledRun = await scope.ServiceProvider.GetRequiredService<JobTrackerContext>().CvExtractionRuns.AsNoTracking().SingleAsync();
Assert.Equal("cancelled", cancelledRun.Status);
Assert.NotNull(cancelledRun.CompletedAtUtc);
}
await using (var scope = fixture.Provider.CreateAsyncScope())
{
using var owner = scope.ServiceProvider.GetRequiredService<CurrentUserService>().UseBackgroundUser("user-1");
Assert.True(await scope.ServiceProvider.GetRequiredService<UserOperationStore>().RetryAsync(operationId, default));
var queuedRun = await scope.ServiceProvider.GetRequiredService<JobTrackerContext>().CvExtractionRuns.AsNoTracking().SingleAsync();
Assert.Equal("queued", queuedRun.Status);
Assert.Null(queuedRun.ErrorMessage);
Assert.Null(queuedRun.CompletedAtUtc);
}
Assert.True(await fixture.Provider.GetRequiredService<AiOperationWorker>().RunOnceAsync(default));
await using var verification = fixture.Provider.CreateAsyncScope();
Assert.Equal("pending_review", (await verification.ServiceProvider.GetRequiredService<JobTrackerContext>()
.CvExtractionRuns.IgnoreQueryFilters().SingleAsync()).Status);
}
[Fact]
public async Task Deadline_before_claim_fails_the_dormant_extraction_run()
{
await using var fixture = await Fixture.CreateAsync();
await fixture.SeedUserAsync();
await using (var scope = fixture.Provider.CreateAsyncScope())
{
using var owner = scope.ServiceProvider.GetRequiredService<CurrentUserService>().UseBackgroundUser("user-1");
Assert.IsType<AcceptedResult>(await CreateController(scope.ServiceProvider).Upload(File()));
await scope.ServiceProvider.GetRequiredService<JobTrackerContext>().UserOperations
.ExecuteUpdateAsync(setters => setters.SetProperty(item => item.DeadlineAtUtc, DateTime.UtcNow.AddMinutes(-1)));
}
Assert.False(await fixture.Provider.GetRequiredService<AiOperationWorker>().RunOnceAsync(default));
await using var verification = fixture.Provider.CreateAsyncScope();
var db = verification.ServiceProvider.GetRequiredService<JobTrackerContext>();
Assert.Equal(OperationStatuses.Failed, (await db.UserOperations.IgnoreQueryFilters().SingleAsync()).Status);
var run = await db.CvExtractionRuns.IgnoreQueryFilters().SingleAsync();
Assert.Equal("failed", run.Status);
Assert.Contains("deadline", run.ErrorMessage, StringComparison.OrdinalIgnoreCase);
Assert.NotNull(run.CompletedAtUtc);
}
private static ProfileCvController CreateController(IServiceProvider services)
{
var controller = services.GetRequiredService<ProfileCvController>();