release orchestration strengthening
This commit is contained in:
@@ -40,3 +40,8 @@ app.MapExportEndpoints();
|
||||
app.MapHealthEndpoints();
|
||||
|
||||
app.Run();
|
||||
|
||||
namespace StellaOps.Timeline.WebService
|
||||
{
|
||||
public partial class Program { }
|
||||
}
|
||||
|
||||
@@ -154,6 +154,11 @@ public sealed class TimelineReplayOrchestrator : ITimelineReplayOrchestrator
|
||||
|
||||
try
|
||||
{
|
||||
if (_operations.TryGetValue(replayId, out var existing) && existing.Status == ReplayStatus.Cancelled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Update status to in-progress
|
||||
UpdateOperation(replayId, op => op with { Status = ReplayStatus.InProgress });
|
||||
|
||||
|
||||
@@ -6,8 +6,11 @@ using FluentAssertions;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Mvc.Testing;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using StellaOps.Eventing.Models;
|
||||
using StellaOps.Eventing.Storage;
|
||||
using StellaOps.Eventing;
|
||||
using StellaOps.HybridLogicalClock;
|
||||
using StellaOps.Timeline.WebService.Endpoints;
|
||||
using Xunit;
|
||||
@@ -193,7 +196,7 @@ public sealed class TimelineApiIntegrationTests : IClassFixture<TimelineWebAppli
|
||||
/// <summary>
|
||||
/// Custom WebApplicationFactory for Timeline integration tests.
|
||||
/// </summary>
|
||||
public sealed class TimelineWebApplicationFactory : WebApplicationFactory<Program>
|
||||
public sealed class TimelineWebApplicationFactory : WebApplicationFactory<StellaOps.Timeline.WebService.Program>
|
||||
{
|
||||
protected override void ConfigureWebHost(IWebHostBuilder builder)
|
||||
{
|
||||
@@ -202,13 +205,67 @@ public sealed class TimelineWebApplicationFactory : WebApplicationFactory<Progra
|
||||
builder.ConfigureServices(services =>
|
||||
{
|
||||
// Replace with in-memory store for tests
|
||||
services.RemoveAll<ITimelineEventStore>();
|
||||
services.RemoveAll<ITimelineEventEmitter>();
|
||||
services.RemoveAll<IHybridLogicalClock>();
|
||||
|
||||
services.AddSingleton<ITimelineEventStore, InMemoryTimelineEventStore>();
|
||||
services.AddSingleton<ITimelineEventEmitter, NoOpTimelineEventEmitter>();
|
||||
services.AddSingleton<IHybridLogicalClock>(_ =>
|
||||
new StellaOps.HybridLogicalClock.HybridLogicalClock(
|
||||
TimeProvider.System,
|
||||
"test-node",
|
||||
new InMemoryHlcStateStore(),
|
||||
NullLogger<StellaOps.HybridLogicalClock.HybridLogicalClock>.Instance));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Minimal Program class reference for WebApplicationFactory.
|
||||
/// </summary>
|
||||
public partial class Program { }
|
||||
internal sealed class NoOpTimelineEventEmitter : ITimelineEventEmitter
|
||||
{
|
||||
public Task<TimelineEvent> EmitAsync<TPayload>(
|
||||
string correlationId,
|
||||
string kind,
|
||||
TPayload payload,
|
||||
CancellationToken cancellationToken = default) where TPayload : notnull
|
||||
{
|
||||
var evt = new TimelineEvent
|
||||
{
|
||||
EventId = Guid.NewGuid().ToString("N"),
|
||||
CorrelationId = correlationId,
|
||||
Kind = kind,
|
||||
THlc = new HlcTimestamp { PhysicalTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), LogicalCounter = 0, NodeId = "test-node" },
|
||||
TsWall = DateTimeOffset.UtcNow,
|
||||
Service = "Test",
|
||||
Payload = payload.ToString() ?? "{}",
|
||||
PayloadDigest = new byte[32],
|
||||
EngineVersion = new EngineVersionRef("Test", "1.0.0", "test-digest"),
|
||||
SchemaVersion = 1
|
||||
};
|
||||
|
||||
return Task.FromResult(evt);
|
||||
}
|
||||
|
||||
public Task<IReadOnlyList<TimelineEvent>> EmitBatchAsync(
|
||||
IEnumerable<PendingEvent> events,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var result = events.Select(e => new TimelineEvent
|
||||
{
|
||||
EventId = Guid.NewGuid().ToString("N"),
|
||||
CorrelationId = e.CorrelationId,
|
||||
Kind = e.Kind,
|
||||
THlc = new HlcTimestamp { PhysicalTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), LogicalCounter = 0, NodeId = "test-node" },
|
||||
TsWall = DateTimeOffset.UtcNow,
|
||||
Service = "Test",
|
||||
Payload = e.Payload?.ToString() ?? "{}",
|
||||
PayloadDigest = new byte[32],
|
||||
EngineVersion = new EngineVersionRef("Test", "1.0.0", "test-digest"),
|
||||
SchemaVersion = 1
|
||||
}).ToList();
|
||||
|
||||
return Task.FromResult<IReadOnlyList<TimelineEvent>>(result);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user