feat: complete remaining jetstream parity implementation plan

This commit is contained in:
Joseph Doherty
2026-02-23 10:16:16 -05:00
parent c7bbf45c8f
commit f46b331921
59 changed files with 1734 additions and 54 deletions

View File

@@ -5,6 +5,7 @@ using NATS.Server.JetStream.Cluster;
using NATS.Server.JetStream.MirrorSource;
using NATS.Server.JetStream.Models;
using NATS.Server.JetStream.Publish;
using NATS.Server.JetStream.Snapshots;
using NATS.Server.JetStream.Storage;
using NATS.Server.Subscriptions;
@@ -22,6 +23,7 @@ public sealed class StreamManager
new(StringComparer.Ordinal);
private readonly ConcurrentDictionary<string, List<SourceCoordinator>> _sourcesByOrigin =
new(StringComparer.Ordinal);
private readonly StreamSnapshotService _snapshotService = new();
public StreamManager(JetStreamMetaGroup? metaGroup = null, Account? account = null)
{
@@ -31,6 +33,9 @@ public sealed class StreamManager
public IReadOnlyCollection<string> StreamNames => _streams.Keys.ToArray();
public IReadOnlyList<string> ListNames()
=> [.. _streams.Keys.OrderBy(x => x, StringComparer.Ordinal)];
public JetStreamApiResponse CreateOrUpdate(StreamConfig config)
{
if (string.IsNullOrWhiteSpace(config.Name))
@@ -67,6 +72,59 @@ public sealed class StreamManager
public bool TryGet(string name, out StreamHandle handle) => _streams.TryGetValue(name, out handle!);
public bool Delete(string name)
{
if (!_streams.TryRemove(name, out _))
return false;
_replicaGroups.TryRemove(name, out _);
_account?.ReleaseStream();
RebuildReplicationCoordinators();
return true;
}
public bool Purge(string name)
{
if (!_streams.TryGetValue(name, out var stream))
return false;
stream.Store.PurgeAsync(default).GetAwaiter().GetResult();
return true;
}
public StoredMessage? GetMessage(string name, ulong sequence)
{
if (!_streams.TryGetValue(name, out var stream))
return null;
return stream.Store.LoadAsync(sequence, default).GetAwaiter().GetResult();
}
public bool DeleteMessage(string name, ulong sequence)
{
if (!_streams.TryGetValue(name, out var stream))
return false;
return stream.Store.RemoveAsync(sequence, default).GetAwaiter().GetResult();
}
public byte[]? CreateSnapshot(string name)
{
if (!_streams.TryGetValue(name, out var stream))
return null;
return _snapshotService.SnapshotAsync(stream, default).GetAwaiter().GetResult();
}
public bool RestoreSnapshot(string name, ReadOnlyMemory<byte> snapshot)
{
if (!_streams.TryGetValue(name, out var stream))
return false;
_snapshotService.RestoreAsync(stream, snapshot, default).GetAwaiter().GetResult();
return true;
}
public ValueTask<StreamState> GetStateAsync(string name, CancellationToken ct)
{
if (_streams.TryGetValue(name, out var stream))
@@ -123,6 +181,9 @@ public sealed class StreamManager
Name = config.Name,
Subjects = config.Subjects.Count == 0 ? [] : [.. config.Subjects],
MaxMsgs = config.MaxMsgs,
MaxConsumers = config.MaxConsumers,
Retention = config.Retention,
Discard = config.Discard,
Replicas = config.Replicas,
Mirror = config.Mirror,
Source = config.Source,