feat: add jetstream stream lifecycle api
This commit is contained in:
78
src/NATS.Server/JetStream/StreamManager.cs
Normal file
78
src/NATS.Server/JetStream/StreamManager.cs
Normal file
@@ -0,0 +1,78 @@
|
||||
using System.Collections.Concurrent;
|
||||
using NATS.Server.JetStream.Api;
|
||||
using NATS.Server.JetStream.Models;
|
||||
using NATS.Server.JetStream.Storage;
|
||||
using NATS.Server.Subscriptions;
|
||||
|
||||
namespace NATS.Server.JetStream;
|
||||
|
||||
public sealed class StreamManager
|
||||
{
|
||||
private readonly ConcurrentDictionary<string, StreamHandle> _streams =
|
||||
new(StringComparer.Ordinal);
|
||||
|
||||
public IReadOnlyCollection<string> StreamNames => _streams.Keys.ToArray();
|
||||
|
||||
public JetStreamApiResponse CreateOrUpdate(StreamConfig config)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(config.Name))
|
||||
return JetStreamApiResponse.ErrorResponse(400, "stream name required");
|
||||
|
||||
var normalized = NormalizeConfig(config);
|
||||
var handle = _streams.AddOrUpdate(
|
||||
normalized.Name,
|
||||
_ => new StreamHandle(normalized, new MemStore()),
|
||||
(_, existing) => existing with { Config = normalized });
|
||||
|
||||
return BuildStreamInfoResponse(handle);
|
||||
}
|
||||
|
||||
public JetStreamApiResponse GetInfo(string name)
|
||||
{
|
||||
if (_streams.TryGetValue(name, out var stream))
|
||||
return BuildStreamInfoResponse(stream);
|
||||
|
||||
return JetStreamApiResponse.NotFound($"$JS.API.STREAM.INFO.{name}");
|
||||
}
|
||||
|
||||
public bool TryGet(string name, out StreamHandle handle) => _streams.TryGetValue(name, out handle!);
|
||||
|
||||
public StreamHandle? FindBySubject(string subject)
|
||||
{
|
||||
foreach (var stream in _streams.Values)
|
||||
{
|
||||
if (stream.Config.Subjects.Any(p => SubjectMatch.MatchLiteral(subject, p)))
|
||||
return stream;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static StreamConfig NormalizeConfig(StreamConfig config)
|
||||
{
|
||||
var copy = new StreamConfig
|
||||
{
|
||||
Name = config.Name,
|
||||
Subjects = config.Subjects.Count == 0 ? [] : [.. config.Subjects],
|
||||
MaxMsgs = config.MaxMsgs,
|
||||
Replicas = config.Replicas,
|
||||
};
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
private static JetStreamApiResponse BuildStreamInfoResponse(StreamHandle handle)
|
||||
{
|
||||
var state = handle.Store.GetStateAsync(default).GetAwaiter().GetResult();
|
||||
return new JetStreamApiResponse
|
||||
{
|
||||
StreamInfo = new JetStreamStreamInfo
|
||||
{
|
||||
Config = handle.Config,
|
||||
State = state,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public sealed record StreamHandle(StreamConfig Config, IStreamStore Store);
|
||||
Reference in New Issue
Block a user