using StellaOps.Determinism;
namespace StellaOps.Provcache.Events;
///
/// Event published when an advisory feed advances to a new epoch.
/// Provcache subscribers use this to invalidate cache entries
/// that were computed against older feed epochs.
///
///
/// Stream name: stellaops:events:feed-epoch-advanced
///
public sealed record FeedEpochAdvancedEvent
{
///
/// Stream name for feed epoch events.
///
public const string StreamName = "stellaops:events:feed-epoch-advanced";
///
/// Event type identifier for serialization.
///
public const string EventType = "feed.epoch.advanced.v1";
///
/// Unique identifier for this event instance.
///
public required Guid EventId { get; init; }
///
/// Timestamp when the event occurred (UTC).
///
public required DateTimeOffset Timestamp { get; init; }
///
/// The feed identifier (e.g., "cve", "ghsa", "osv", "redhat-oval").
///
public required string FeedId { get; init; }
///
/// The previous epoch identifier.
/// Format varies by feed (e.g., "2024-12-24T12:00:00Z", "v2024.52").
///
public required string PreviousEpoch { get; init; }
///
/// The new epoch identifier.
///
public required string NewEpoch { get; init; }
///
/// When the new epoch became effective.
/// Cache entries with feed_epoch older than this should be invalidated.
///
public required DateTimeOffset EffectiveAt { get; init; }
///
/// Number of advisories added in this epoch (for metrics).
///
public int? AdvisoriesAdded { get; init; }
///
/// Number of advisories modified in this epoch (for metrics).
///
public int? AdvisoriesModified { get; init; }
///
/// Number of advisories withdrawn in this epoch (for metrics).
///
public int? AdvisoriesWithdrawn { get; init; }
///
/// Tenant ID if multi-tenant (null for global feeds).
///
public string? TenantId { get; init; }
///
/// Correlation ID for distributed tracing.
///
public string? CorrelationId { get; init; }
///
/// Creates a new FeedEpochAdvancedEvent.
///
/// The feed identifier.
/// The previous epoch identifier.
/// The new epoch identifier.
/// When the new epoch became effective.
/// Number of advisories added (for metrics).
/// Number of advisories modified (for metrics).
/// Number of advisories withdrawn (for metrics).
/// Tenant ID if multi-tenant.
/// Correlation ID for tracing.
/// Optional event ID (defaults to new GUID).
/// Optional timestamp (defaults to current UTC time).
/// Optional GUID provider for deterministic IDs.
/// Optional time provider for deterministic timestamps.
public static FeedEpochAdvancedEvent Create(
string feedId,
string previousEpoch,
string newEpoch,
DateTimeOffset effectiveAt,
int? advisoriesAdded = null,
int? advisoriesModified = null,
int? advisoriesWithdrawn = null,
string? tenantId = null,
string? correlationId = null,
Guid? eventId = null,
DateTimeOffset? timestamp = null,
IGuidProvider? guidProvider = null,
TimeProvider? timeProvider = null)
{
var guidSource = guidProvider ?? SystemGuidProvider.Instance;
var timeSource = timeProvider ?? TimeProvider.System;
return new FeedEpochAdvancedEvent
{
EventId = eventId ?? guidSource.NewGuid(),
Timestamp = timestamp ?? timeSource.GetUtcNow(),
FeedId = feedId,
PreviousEpoch = previousEpoch,
NewEpoch = newEpoch,
EffectiveAt = effectiveAt,
AdvisoriesAdded = advisoriesAdded,
AdvisoriesModified = advisoriesModified,
AdvisoriesWithdrawn = advisoriesWithdrawn,
TenantId = tenantId,
CorrelationId = correlationId
};
}
}