using Health.Infrastructure.AI; using Health.Infrastructure.Data; using Health.Infrastructure.Data.Records; using Health.Infrastructure.Reports; using Microsoft.EntityFrameworkCore; namespace Health.Tests; public sealed class PersistencePipelineTests { [Fact] public async Task AiConfirmation_CanOnlyBeTakenOnceByOwner() { await using var db = CreateDbContext(); var store = new EfAiWriteConfirmationStore(db); var ownerId = Guid.NewGuid(); var command = await store.CreateAsync(ownerId, "record_health_data", "{}", TimeSpan.FromMinutes(10), CancellationToken.None); var wrongUser = await store.TakeAsync(command.Id, Guid.NewGuid(), CancellationToken.None); var firstTake = await store.TakeAsync(command.Id, ownerId, CancellationToken.None); var secondTake = await store.TakeAsync(command.Id, ownerId, CancellationToken.None); Assert.Null(wrongUser); Assert.NotNull(firstTake); Assert.Null(secondTake); } [Fact] public async Task ReportTask_RetryUsesBackoffBeforeMaxAttempts() { await using var db = CreateDbContext(); var task = NewReportTask(attempts: 1); db.ReportAnalysisTasks.Add(task); await db.SaveChangesAsync(); var queue = new EfReportAnalysisQueue(db); var before = DateTime.UtcNow; await queue.RetryAsync(task.Id, "temporary failure", CancellationToken.None); Assert.Equal("Pending", task.Status); Assert.True(task.AvailableAt > before); Assert.Equal("temporary failure", task.LastError); } [Fact] public async Task ReportTask_RetryMarksFailedAtMaxAttempts() { await using var db = CreateDbContext(); var task = NewReportTask(attempts: 3); db.ReportAnalysisTasks.Add(task); await db.SaveChangesAsync(); var queue = new EfReportAnalysisQueue(db); await queue.RetryAsync(task.Id, new string('x', 2500), CancellationToken.None); Assert.Equal("Failed", task.Status); Assert.Equal(2000, task.LastError!.Length); } private static ReportAnalysisTaskRecord NewReportTask(int attempts) => new() { Id = Guid.NewGuid(), ReportId = Guid.NewGuid(), FilePath = "report.jpg", Status = "Processing", Attempts = attempts, AvailableAt = DateTime.UtcNow, CreatedAt = DateTime.UtcNow, UpdatedAt = DateTime.UtcNow, }; private static AppDbContext CreateDbContext() => new( new DbContextOptionsBuilder() .UseInMemoryDatabase(Guid.NewGuid().ToString()) .Options); }