tests fixes and sprints work

This commit is contained in:
master
2026-01-22 19:08:46 +02:00
parent c32fff8f86
commit 726d70dc7f
881 changed files with 134434 additions and 6228 deletions

View File

@@ -8,6 +8,7 @@
using System.Collections.Immutable;
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;

View File

@@ -243,11 +243,11 @@ public sealed class CrossRegionSync : ICrossRegionSync, IAsyncDisposable
return _syncStates.TryGetValue(peerRegionId, out var state) ? state : null;
}
private async Task HandleReplicateAsync(SyncMessage message, CancellationToken ct)
private async Task<SyncResponse> HandleReplicateAsync(SyncMessage message, CancellationToken ct)
{
if (message.Entry is null)
{
return;
return new SyncResponse { Success = false, Error = "Missing entry" };
}
var localEntry = await _store.GetAsync(message.Entry.Key, ct);
@@ -271,6 +271,8 @@ public sealed class CrossRegionSync : ICrossRegionSync, IAsyncDisposable
// Concurrent modification - conflict
await RecordConflictAsync(localEntry, message.Entry, ct);
}
return new SyncResponse { Success = true };
}
private async Task<SyncResponse> HandleRequestSyncAsync(

View File

@@ -20,7 +20,7 @@ public sealed class FederationHub : BackgroundService
public event EventHandler<RegionEventArgs>? RegionJoined;
public event EventHandler<RegionEventArgs>? RegionLeft;
public event EventHandler<RegionEventArgs>? RegionHealthChanged;
public event EventHandler<GlobalPromotionEventArgs>? GlobalPromotionRequested;
public event EventHandler<HubPromotionEventArgs>? GlobalPromotionRequested;
public FederationHub(
IRegionRegistry registry,
@@ -138,8 +138,8 @@ public sealed class FederationHub : BackgroundService
/// <summary>
/// Initiates a global promotion across all regions.
/// </summary>
public async Task<GlobalPromotionResult> InitiateGlobalPromotionAsync(
GlobalPromotionRequest request,
public async Task<HubPromotionResult> InitiateGlobalPromotionAsync(
HubPromotionRequest request,
CancellationToken ct = default)
{
ArgumentNullException.ThrowIfNull(request);
@@ -153,21 +153,21 @@ public sealed class FederationHub : BackgroundService
? _regions.Values.Where(r => request.TargetRegions.Contains(r.RegionId)).ToList()
: _regions.Values.Where(r => r.Status == RegionStatus.Active).ToList();
var promotion = new GlobalPromotion
var promotion = new HubPromotion
{
Id = request.PromotionId,
ReleaseId = request.ReleaseId,
ReleaseName = request.ReleaseName,
Strategy = request.Strategy,
TargetRegions = targetRegions.Select(r => r.RegionId).ToImmutableArray(),
Status = GlobalPromotionStatus.InProgress,
Status = HubPromotionStatus.InProgress,
StartedAt = _timeProvider.GetUtcNow(),
RegionStatuses = targetRegions.ToDictionary(
r => r.RegionId,
_ => RegionPromotionStatus.Pending).ToImmutableDictionary()
_ => HubRegionPromotionStatus.Pending).ToImmutableDictionary()
};
GlobalPromotionRequested?.Invoke(this, new GlobalPromotionEventArgs
GlobalPromotionRequested?.Invoke(this, new HubPromotionEventArgs
{
Promotion = promotion
});
@@ -175,15 +175,15 @@ public sealed class FederationHub : BackgroundService
// Execute based on strategy
var results = request.Strategy switch
{
GlobalPromotionStrategy.Parallel => await ExecuteParallelPromotionAsync(promotion, request, ct),
GlobalPromotionStrategy.Sequential => await ExecuteSequentialPromotionAsync(promotion, request, ct),
GlobalPromotionStrategy.RollingWave => await ExecuteRollingWavePromotionAsync(promotion, request, ct),
HubPromotionStrategy.Parallel => await ExecuteParallelPromotionAsync(promotion, request, ct),
HubPromotionStrategy.Sequential => await ExecuteSequentialPromotionAsync(promotion, request, ct),
HubPromotionStrategy.RollingWave => await ExecuteRollingWavePromotionAsync(promotion, request, ct),
_ => await ExecuteSequentialPromotionAsync(promotion, request, ct)
};
var success = results.All(r => r.Success);
return new GlobalPromotionResult
return new HubPromotionResult
{
PromotionId = promotion.Id,
Success = success,
@@ -263,9 +263,9 @@ public sealed class FederationHub : BackgroundService
}
}
private async Task<List<RegionPromotionResult>> ExecuteParallelPromotionAsync(
GlobalPromotion promotion,
GlobalPromotionRequest request,
private async Task<List<HubRegionPromotionResult>> ExecuteParallelPromotionAsync(
HubPromotion promotion,
HubPromotionRequest request,
CancellationToken ct)
{
var tasks = promotion.TargetRegions.Select(regionId =>
@@ -275,12 +275,12 @@ public sealed class FederationHub : BackgroundService
return results.ToList();
}
private async Task<List<RegionPromotionResult>> ExecuteSequentialPromotionAsync(
GlobalPromotion promotion,
GlobalPromotionRequest request,
private async Task<List<HubRegionPromotionResult>> ExecuteSequentialPromotionAsync(
HubPromotion promotion,
HubPromotionRequest request,
CancellationToken ct)
{
var results = new List<RegionPromotionResult>();
var results = new List<HubRegionPromotionResult>();
foreach (var regionId in promotion.TargetRegions)
{
@@ -296,12 +296,12 @@ public sealed class FederationHub : BackgroundService
return results;
}
private async Task<List<RegionPromotionResult>> ExecuteRollingWavePromotionAsync(
GlobalPromotion promotion,
GlobalPromotionRequest request,
private async Task<List<HubRegionPromotionResult>> ExecuteRollingWavePromotionAsync(
HubPromotion promotion,
HubPromotionRequest request,
CancellationToken ct)
{
var results = new List<RegionPromotionResult>();
var results = new List<HubRegionPromotionResult>();
var waveSize = request.WaveSize ?? 2;
var waves = promotion.TargetRegions
.Select((r, i) => (Region: r, Wave: i / waveSize))
@@ -331,14 +331,14 @@ public sealed class FederationHub : BackgroundService
return results;
}
private async Task<RegionPromotionResult> ExecuteRegionPromotionAsync(
private async Task<HubRegionPromotionResult> ExecuteRegionPromotionAsync(
string regionId,
GlobalPromotionRequest request,
HubPromotionRequest request,
CancellationToken ct)
{
if (!_regions.TryGetValue(regionId, out var region))
{
return new RegionPromotionResult
return new HubRegionPromotionResult
{
RegionId = regionId,
Success = false,
@@ -360,7 +360,7 @@ public sealed class FederationHub : BackgroundService
}
}, ct);
return new RegionPromotionResult
return new HubRegionPromotionResult
{
RegionId = regionId,
Success = true,
@@ -373,7 +373,7 @@ public sealed class FederationHub : BackgroundService
"Failed to promote to region {RegionId}",
regionId);
return new RegionPromotionResult
return new HubRegionPromotionResult
{
RegionId = regionId,
Success = false,
@@ -483,12 +483,12 @@ public sealed record RegistrationResult
/// <summary>
/// Request for global promotion.
/// </summary>
public sealed record GlobalPromotionRequest
public sealed record HubPromotionRequest
{
public required Guid PromotionId { get; init; }
public required Guid ReleaseId { get; init; }
public required string ReleaseName { get; init; }
public GlobalPromotionStrategy Strategy { get; init; } = GlobalPromotionStrategy.Sequential;
public HubPromotionStrategy Strategy { get; init; } = HubPromotionStrategy.Sequential;
public ImmutableArray<string> TargetRegions { get; init; } = [];
public bool StopOnFailure { get; init; } = true;
public int? WaveSize { get; init; }
@@ -498,7 +498,7 @@ public sealed record GlobalPromotionRequest
/// <summary>
/// Global promotion strategy.
/// </summary>
public enum GlobalPromotionStrategy
public enum HubPromotionStrategy
{
Sequential,
Parallel,
@@ -508,18 +508,18 @@ public enum GlobalPromotionStrategy
/// <summary>
/// Result of global promotion.
/// </summary>
public sealed record GlobalPromotionResult
public sealed record HubPromotionResult
{
public required Guid PromotionId { get; init; }
public required bool Success { get; init; }
public required ImmutableArray<RegionPromotionResult> RegionResults { get; init; }
public required ImmutableArray<HubRegionPromotionResult> RegionResults { get; init; }
public required TimeSpan Duration { get; init; }
}
/// <summary>
/// Result for a single region.
/// </summary>
public sealed record RegionPromotionResult
public sealed record HubRegionPromotionResult
{
public required string RegionId { get; init; }
public required bool Success { get; init; }
@@ -543,23 +543,23 @@ public sealed record FederationStatus
/// <summary>
/// A global promotion.
/// </summary>
public sealed record GlobalPromotion
public sealed record HubPromotion
{
public required Guid Id { get; init; }
public required Guid ReleaseId { get; init; }
public required string ReleaseName { get; init; }
public required GlobalPromotionStrategy Strategy { get; init; }
public required HubPromotionStrategy Strategy { get; init; }
public required ImmutableArray<string> TargetRegions { get; init; }
public required GlobalPromotionStatus Status { get; init; }
public required HubPromotionStatus Status { get; init; }
public required DateTimeOffset StartedAt { get; init; }
public DateTimeOffset? CompletedAt { get; init; }
public required ImmutableDictionary<string, RegionPromotionStatus> RegionStatuses { get; init; }
public required ImmutableDictionary<string, HubRegionPromotionStatus> RegionStatuses { get; init; }
}
/// <summary>
/// Global promotion status.
/// </summary>
public enum GlobalPromotionStatus
public enum HubPromotionStatus
{
Pending,
InProgress,
@@ -571,7 +571,7 @@ public enum GlobalPromotionStatus
/// <summary>
/// Region promotion status.
/// </summary>
public enum RegionPromotionStatus
public enum HubRegionPromotionStatus
{
Pending,
InProgress,
@@ -592,9 +592,9 @@ public sealed class RegionEventArgs : EventArgs
/// <summary>
/// Event args for global promotion.
/// </summary>
public sealed class GlobalPromotionEventArgs : EventArgs
public sealed class HubPromotionEventArgs : EventArgs
{
public required GlobalPromotion Promotion { get; init; }
public required HubPromotion Promotion { get; init; }
}
/// <summary>

View File

@@ -10,8 +10,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" />
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
</Project>