68 lines
2.3 KiB
C#
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));
|
|
}
|
|
}
|