using System.Collections.Concurrent; namespace NATS.Server.JetStream.Publish; public sealed class PublishPreconditions { private readonly ConcurrentDictionary _dedupe = new(StringComparer.Ordinal); public bool IsDuplicate(string? msgId, int duplicateWindowMs, out ulong existingSequence) { existingSequence = 0; if (string.IsNullOrEmpty(msgId)) return false; if (!_dedupe.TryGetValue(msgId, out var entry)) return false; if (duplicateWindowMs > 0 && DateTime.UtcNow - entry.TimestampUtc > TimeSpan.FromMilliseconds(duplicateWindowMs)) { _dedupe.TryRemove(msgId, out _); return false; } existingSequence = entry.Sequence; return true; } public void Record(string? msgId, ulong sequence) { if (string.IsNullOrEmpty(msgId)) return; _dedupe[msgId] = new DedupeEntry(sequence, DateTime.UtcNow); } public void TrimOlderThan(int duplicateWindowMs) { if (duplicateWindowMs <= 0) return; var cutoff = DateTime.UtcNow.AddMilliseconds(-duplicateWindowMs); foreach (var (key, entry) in _dedupe) { if (entry.TimestampUtc < cutoff) _dedupe.TryRemove(key, out _); } } public bool CheckExpectedLastSeq(ulong expectedLastSeq, ulong actualLastSeq) => expectedLastSeq == 0 || expectedLastSeq == actualLastSeq; private readonly record struct DedupeEntry(ulong Sequence, DateTime TimestampUtc); }