release orchestration strengthening

This commit is contained in:
master
2026-01-17 21:32:03 +02:00
parent 195dff2457
commit da27b9faa9
256 changed files with 94634 additions and 2269 deletions

View File

@@ -40,3 +40,8 @@ app.MapExportEndpoints();
app.MapHealthEndpoints();
app.Run();
namespace StellaOps.Timeline.WebService
{
public partial class Program { }
}

View File

@@ -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 });

View File

@@ -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);
}
}