up
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using StellaOps.Messaging;
|
||||
using StellaOps.Messaging.Abstractions;
|
||||
using StellaOps.Scanner.WebService.Contracts;
|
||||
using StellaOps.Scanner.WebService.Options;
|
||||
|
||||
namespace StellaOps.Scanner.WebService.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Transport-agnostic implementation of <see cref="IPlatformEventPublisher"/> using StellaOps.Messaging abstractions.
|
||||
/// Works with any configured transport (Valkey, PostgreSQL, InMemory).
|
||||
/// </summary>
|
||||
internal sealed class MessagingPlatformEventPublisher : IPlatformEventPublisher
|
||||
{
|
||||
private readonly IEventStream<OrchestratorEvent> _eventStream;
|
||||
private readonly ILogger<MessagingPlatformEventPublisher> _logger;
|
||||
private readonly TimeSpan _publishTimeout;
|
||||
private readonly long? _maxStreamLength;
|
||||
|
||||
public MessagingPlatformEventPublisher(
|
||||
IEventStreamFactory eventStreamFactory,
|
||||
IOptions<ScannerWebServiceOptions> options,
|
||||
ILogger<MessagingPlatformEventPublisher> logger)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(eventStreamFactory);
|
||||
ArgumentNullException.ThrowIfNull(options);
|
||||
|
||||
var eventsOptions = options.Value.Events ?? throw new InvalidOperationException("Events options are required when messaging publisher is registered.");
|
||||
if (!eventsOptions.Enabled)
|
||||
{
|
||||
throw new InvalidOperationException("MessagingPlatformEventPublisher requires events emission to be enabled.");
|
||||
}
|
||||
|
||||
var streamName = string.IsNullOrWhiteSpace(eventsOptions.Stream) ? "stella.events" : eventsOptions.Stream;
|
||||
_maxStreamLength = eventsOptions.MaxStreamLength > 0 ? eventsOptions.MaxStreamLength : null;
|
||||
_publishTimeout = TimeSpan.FromSeconds(eventsOptions.PublishTimeoutSeconds <= 0 ? 5 : eventsOptions.PublishTimeoutSeconds);
|
||||
|
||||
_eventStream = eventStreamFactory.Create<OrchestratorEvent>(new EventStreamOptions
|
||||
{
|
||||
StreamName = streamName,
|
||||
MaxLength = _maxStreamLength,
|
||||
ApproximateTrimming = true,
|
||||
});
|
||||
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
|
||||
_logger.LogInformation("Initialized messaging platform event publisher for stream {Stream}.", streamName);
|
||||
}
|
||||
|
||||
public async Task PublishAsync(OrchestratorEvent @event, CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(@event);
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
var publishOptions = new EventPublishOptions
|
||||
{
|
||||
IdempotencyKey = @event.IdempotencyKey,
|
||||
TenantId = @event.Tenant,
|
||||
CorrelationId = @event.CorrelationId,
|
||||
MaxStreamLength = _maxStreamLength,
|
||||
Headers = new Dictionary<string, string>
|
||||
{
|
||||
["kind"] = @event.Kind,
|
||||
["occurredAt"] = @event.OccurredAt.ToString("O")
|
||||
}
|
||||
};
|
||||
|
||||
var publishTask = _eventStream.PublishAsync(@event, publishOptions, cancellationToken);
|
||||
|
||||
if (_publishTimeout > TimeSpan.Zero)
|
||||
{
|
||||
await publishTask.AsTask().WaitAsync(_publishTimeout, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
await publishTask.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user