Files
Omika/tests/Omika.Diagnostics.Tests/DiagnosticImporterFailOpenTests.cs
T
2026-10-23 18:46:50 +02:00

68 lines
2.3 KiB
C#

using Microsoft.Extensions.Options;
using Omika.Diagnostics.Import;
using Omika.Diagnostics.Tests.Fakes;
namespace Omika.Diagnostics.Tests;
/// <summary>§52 — Fail-open PostgreSQL : l'importeur survit, backoff, JSONL intact, checkpoint non avancé.</summary>
public class DiagnosticImporterFailOpenTests
{
[Fact]
public async Task RepositoryDown_ReturnsRetryable_AndDoesNotAdvanceCheckpoint()
{
var source = new FakeDiagnosticJsonlSource(new[]
{
DiagnosticTestData.Record(Guid.NewGuid(), "A"),
DiagnosticTestData.Record(Guid.NewGuid(), "B")
});
var importer = new DiagnosticImporter(
source,
new ThrowingDiagnosticRepository(),
Options.Create(new DiagnosticImportOptions { BatchSize = 100 }));
DiagnosticImportResult result = await importer.ImportOnceAsync();
Assert.False(result.Succeeded);
Assert.True(result.Retryable);
Assert.Equal("InvalidOperationException", result.Error);
// Le checkpoint n'a PAS avancé : le JSONL reste intact et sera relu.
Assert.Equal(0, source.CommitCount);
Assert.Null(source.LoadCheckpoint());
}
[Fact]
public async Task RepositoryDown_NextPassReadsSameRecords()
{
var source = new FakeDiagnosticJsonlSource(new[]
{
DiagnosticTestData.Record(Guid.NewGuid(), "A")
});
var importer = new DiagnosticImporter(
source,
new ThrowingDiagnosticRepository(),
Options.Create(new DiagnosticImportOptions { BatchSize = 100 }));
await importer.ImportOnceAsync();
await importer.ImportOnceAsync();
// Toujours 0 commit : reprise idempotente, jamais de perte de données.
Assert.Equal(0, source.CommitCount);
}
[Fact]
public async Task Backoff_IsBoundedExponential_NoCpuSpin()
{
var options = new DiagnosticImportOptions { RetryDelaySeconds = 5, MaxRetryDelaySeconds = 300 };
TimeSpan first = DiagnosticBackoff.Compute(options, 1);
TimeSpan second = DiagnosticBackoff.Compute(options, 2);
TimeSpan capped = DiagnosticBackoff.Compute(options, 1000);
Assert.True(second > first);
Assert.True(capped <= TimeSpan.FromSeconds(options.MaxRetryDelaySeconds));
}
}