131 lines
5.0 KiB
C#
131 lines
5.0 KiB
C#
using Microsoft.Extensions.Options;
|
|
using Omika.Core.Observability.Identity;
|
|
using Omika.Core.Observability.Outbox;
|
|
using Omika.Diagnostics.Data;
|
|
using Omika.Diagnostics.Import;
|
|
using Omika.Diagnostics.Models;
|
|
using Omika.Diagnostics.Tests.Fakes;
|
|
|
|
namespace Omika.Diagnostics.Tests;
|
|
|
|
/// <summary>
|
|
/// Tâche 13-E — E12 + §38 : compatibilité d'un JSONL produit par Omika.Worker avec le
|
|
/// pipeline d'import (JsonlDiagnosticSource → DiagnosticImporter → DiagnosticEventRecord)
|
|
/// et NON-ÉCRASEMENT du contexte du producteur par Omika.Diagnostics.Worker.
|
|
///
|
|
/// Un événement Worker portant <c>ServerInstance = WKR-SRV-01</c> doit arriver dans
|
|
/// <c>DiagnosticEventRecord</c> avec EXACTEMENT <c>WKR-SRV-01</c>, jamais remplacé par
|
|
/// le nom de machine de l'importeur. Le contexte (ClientCode/ServerInstance/Environment)
|
|
/// représente le composant qui a PRODUIT l'événement, pas celui qui l'importe.
|
|
/// Aucun PostgreSQL réel : FakeDiagnosticEventRepository (§51).
|
|
/// </summary>
|
|
public class WorkerSyncImportContextTests : IDisposable
|
|
{
|
|
private readonly string _dir = CreateTempDirectory();
|
|
|
|
public void Dispose() => DeleteDirectory(_dir);
|
|
|
|
// --------------------------- E12 + §38 : import complet ---------------------
|
|
[Fact]
|
|
public async Task WorkerJsonl_ImportsToRecord_PreservingProducerContext()
|
|
{
|
|
// 1. Production d'un événement Worker (format RemoteDiagnosticIngestionStore,
|
|
// fichier omika-mobile-diagnostic-*.jsonl) avec contexte du producteur.
|
|
Guid operationId = Guid.NewGuid();
|
|
Guid eventId = Guid.NewGuid();
|
|
var context = new DiagnosticDeploymentContext
|
|
{
|
|
ClientCode = "CLIENT-A",
|
|
ServerInstance = "WKR-SRV-01",
|
|
Environment = "Production"
|
|
};
|
|
|
|
await WriteWorkerEventAsync(eventId, operationId, context);
|
|
|
|
// 2. Import par Omika.Diagnostics.Worker (JsonlDiagnosticSource + importer).
|
|
var repository = new FakeDiagnosticEventRepository();
|
|
var importer = new DiagnosticImporter(
|
|
new JsonlDiagnosticSource(_dir, "import-checkpoint.json"),
|
|
repository,
|
|
Options.Create(new DiagnosticImportOptions { BatchSize = 100, Source = "worker" }));
|
|
|
|
DiagnosticImportResult result = await importer.ImportOnceAsync();
|
|
|
|
// 3. L'événement est lisible et importé (aucun format incompatible).
|
|
Assert.True(result.Succeeded);
|
|
Assert.Equal(1, result.ImportedCount);
|
|
Assert.Equal(0, result.DroppedCount);
|
|
|
|
// 4. Le contexte du PRODUCTEUR est conservé, jamais remplacé par l'importeur.
|
|
IReadOnlyList<DiagnosticEventRecord> records = await repository.GetByOperationIdAsync(operationId);
|
|
DiagnosticEventRecord record = Assert.Single(records);
|
|
|
|
Assert.Equal("CLIENT-A", record.ClientCode);
|
|
Assert.Equal("WKR-SRV-01", record.ServerInstance);
|
|
Assert.NotEqual(Environment.MachineName, record.ServerInstance);
|
|
Assert.Equal("Production", record.Environment);
|
|
Assert.Equal("Omika.Worker", record.Component);
|
|
Assert.Equal("OMK-WKR-SYNC-001", record.EventCode);
|
|
Assert.Equal("worker", record.Source);
|
|
Assert.Equal(operationId, record.OperationId);
|
|
}
|
|
|
|
// --------------------------- Helpers -----------------------------------------
|
|
private async Task WriteWorkerEventAsync(
|
|
Guid eventId,
|
|
Guid operationId,
|
|
DiagnosticDeploymentContext context)
|
|
{
|
|
var store = new RemoteDiagnosticIngestionStore(new RemoteDiagnosticOptions { Directory = _dir });
|
|
|
|
var evt = new DiagnosticEventDto
|
|
{
|
|
EventId = eventId,
|
|
EventCode = "OMK-WKR-SYNC-001",
|
|
TimestampUtc = DateTimeOffset.UtcNow,
|
|
Level = "Info",
|
|
Priority = "P3",
|
|
Component = "Omika.Worker",
|
|
OperationId = operationId,
|
|
AppVersion = "1.0.0.0",
|
|
Platform = "worker",
|
|
Source = "worker",
|
|
EntityType = "Client",
|
|
EntityId = Guid.NewGuid().ToString("D"),
|
|
Success = true,
|
|
DurationMs = 12,
|
|
Metadata = new Dictionary<string, object?>
|
|
{
|
|
["operationType"] = "Create",
|
|
["retryCount"] = 0,
|
|
["result"] = "Success"
|
|
}
|
|
};
|
|
|
|
var batch = new DiagnosticBatchDto { Events = [evt] };
|
|
await store.StoreAsync(batch, DiagnosticActorKey.Empty, Guid.NewGuid().ToString("D"), DateTimeOffset.UtcNow, CancellationToken.None, context);
|
|
}
|
|
|
|
private static string CreateTempDirectory()
|
|
{
|
|
string dir = Path.Combine(Path.GetTempPath(), "omika-worker-sync-import-tests", Guid.NewGuid().ToString("N"));
|
|
Directory.CreateDirectory(dir);
|
|
return dir;
|
|
}
|
|
|
|
private static void DeleteDirectory(string dir)
|
|
{
|
|
try
|
|
{
|
|
if (Directory.Exists(dir))
|
|
{
|
|
Directory.Delete(dir, recursive: true);
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
// Best-effort.
|
|
}
|
|
}
|
|
}
|