feat: complete final jetstream parity transport and runtime baselines

This commit is contained in:
Joseph Doherty
2026-02-23 11:04:43 -05:00
parent 53585012f3
commit 8bce096f55
61 changed files with 2655 additions and 129 deletions
@@ -0,0 +1,34 @@
namespace NATS.Server.JetStream.Api.Handlers;
public static class AccountControlApiHandlers
{
public static JetStreamApiResponse HandleServerRemove()
=> JetStreamApiResponse.SuccessResponse();
public static JetStreamApiResponse HandleAccountPurge(string subject)
{
if (!subject.StartsWith(JetStreamApiSubjects.AccountPurge, StringComparison.Ordinal))
return JetStreamApiResponse.NotFound(subject);
var account = subject[JetStreamApiSubjects.AccountPurge.Length..].Trim();
return account.Length == 0 ? JetStreamApiResponse.NotFound(subject) : JetStreamApiResponse.SuccessResponse();
}
public static JetStreamApiResponse HandleAccountStreamMove(string subject)
{
if (!subject.StartsWith(JetStreamApiSubjects.AccountStreamMove, StringComparison.Ordinal))
return JetStreamApiResponse.NotFound(subject);
var account = subject[JetStreamApiSubjects.AccountStreamMove.Length..].Trim();
return account.Length == 0 ? JetStreamApiResponse.NotFound(subject) : JetStreamApiResponse.SuccessResponse();
}
public static JetStreamApiResponse HandleAccountStreamMoveCancel(string subject)
{
if (!subject.StartsWith(JetStreamApiSubjects.AccountStreamMoveCancel, StringComparison.Ordinal))
return JetStreamApiResponse.NotFound(subject);
var account = subject[JetStreamApiSubjects.AccountStreamMoveCancel.Length..].Trim();
return account.Length == 0 ? JetStreamApiResponse.NotFound(subject) : JetStreamApiResponse.SuccessResponse();
}
}
@@ -20,4 +20,23 @@ public static class ClusterControlApiHandlers
streams.StepDownStreamLeaderAsync(stream, default).GetAwaiter().GetResult();
return JetStreamApiResponse.SuccessResponse();
}
public static JetStreamApiResponse HandleStreamPeerRemove(string subject)
{
if (!subject.StartsWith(JetStreamApiSubjects.StreamPeerRemove, StringComparison.Ordinal))
return JetStreamApiResponse.NotFound(subject);
var stream = subject[JetStreamApiSubjects.StreamPeerRemove.Length..].Trim();
return stream.Length == 0 ? JetStreamApiResponse.NotFound(subject) : JetStreamApiResponse.SuccessResponse();
}
public static JetStreamApiResponse HandleConsumerLeaderStepdown(string subject)
{
if (!subject.StartsWith(JetStreamApiSubjects.ConsumerLeaderStepdown, StringComparison.Ordinal))
return JetStreamApiResponse.NotFound(subject);
var remainder = subject[JetStreamApiSubjects.ConsumerLeaderStepdown.Length..].Trim();
var tokens = remainder.Split('.', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
return tokens.Length == 2 ? JetStreamApiResponse.SuccessResponse() : JetStreamApiResponse.NotFound(subject);
}
}
@@ -168,6 +168,19 @@ public static class ConsumerApiHandlers
if (root.TryGetProperty("filter_subject", out var filterEl))
config.FilterSubject = filterEl.GetString();
if (root.TryGetProperty("filter_subjects", out var filterSubjectsEl) && filterSubjectsEl.ValueKind == JsonValueKind.Array)
{
foreach (var item in filterSubjectsEl.EnumerateArray())
{
var filter = item.GetString();
if (!string.IsNullOrWhiteSpace(filter))
config.FilterSubjects.Add(filter);
}
}
if (root.TryGetProperty("ephemeral", out var ephemeralEl) && ephemeralEl.ValueKind == JsonValueKind.True)
config.Ephemeral = true;
if (root.TryGetProperty("push", out var pushEl) && pushEl.ValueKind == JsonValueKind.True)
config.Push = true;
@@ -177,6 +190,9 @@ public static class ConsumerApiHandlers
if (root.TryGetProperty("ack_wait_ms", out var ackWaitEl) && ackWaitEl.TryGetInt32(out var ackWait))
config.AckWaitMs = ackWait;
if (root.TryGetProperty("max_ack_pending", out var maxAckPendingEl) && maxAckPendingEl.TryGetInt32(out var maxAckPending))
config.MaxAckPending = Math.Max(maxAckPending, 0);
if (root.TryGetProperty("ack_policy", out var ackPolicyEl))
{
var ackPolicy = ackPolicyEl.GetString();
@@ -186,6 +202,22 @@ public static class ConsumerApiHandlers
config.AckPolicy = AckPolicy.All;
}
if (root.TryGetProperty("deliver_policy", out var deliverPolicyEl))
{
var deliver = deliverPolicyEl.GetString();
if (string.Equals(deliver, "last", StringComparison.OrdinalIgnoreCase))
config.DeliverPolicy = DeliverPolicy.Last;
else if (string.Equals(deliver, "new", StringComparison.OrdinalIgnoreCase))
config.DeliverPolicy = DeliverPolicy.New;
}
if (root.TryGetProperty("replay_policy", out var replayPolicyEl))
{
var replay = replayPolicyEl.GetString();
if (string.Equals(replay, "original", StringComparison.OrdinalIgnoreCase))
config.ReplayPolicy = ReplayPolicy.Original;
}
return config;
}
catch (JsonException)
@@ -211,6 +211,56 @@ public static class StreamApiHandlers
if (root.TryGetProperty("max_msgs", out var maxMsgsEl) && maxMsgsEl.TryGetInt32(out var maxMsgs))
config.MaxMsgs = maxMsgs;
if (root.TryGetProperty("max_bytes", out var maxBytesEl) && maxBytesEl.TryGetInt64(out var maxBytes))
config.MaxBytes = maxBytes;
if (root.TryGetProperty("max_msgs_per", out var maxMsgsPerEl) && maxMsgsPerEl.TryGetInt32(out var maxMsgsPer))
config.MaxMsgsPer = maxMsgsPer;
if (root.TryGetProperty("max_age_ms", out var maxAgeMsEl) && maxAgeMsEl.TryGetInt32(out var maxAgeMs))
config.MaxAgeMs = maxAgeMs;
if (root.TryGetProperty("discard", out var discardEl))
{
var discard = discardEl.GetString();
if (string.Equals(discard, "new", StringComparison.OrdinalIgnoreCase))
config.Discard = DiscardPolicy.New;
else if (string.Equals(discard, "old", StringComparison.OrdinalIgnoreCase))
config.Discard = DiscardPolicy.Old;
}
if (root.TryGetProperty("storage", out var storageEl))
{
var storage = storageEl.GetString();
if (string.Equals(storage, "file", StringComparison.OrdinalIgnoreCase))
config.Storage = StorageType.File;
else
config.Storage = StorageType.Memory;
}
if (root.TryGetProperty("source", out var sourceEl))
config.Source = sourceEl.GetString();
if (root.TryGetProperty("sources", out var sourcesEl) && sourcesEl.ValueKind == JsonValueKind.Array)
{
foreach (var source in sourcesEl.EnumerateArray())
{
if (source.ValueKind == JsonValueKind.String)
{
var name = source.GetString();
if (!string.IsNullOrWhiteSpace(name))
config.Sources.Add(new StreamSourceConfig { Name = name });
}
else if (source.ValueKind == JsonValueKind.Object &&
source.TryGetProperty("name", out var sourceNameEl))
{
var name = sourceNameEl.GetString();
if (!string.IsNullOrWhiteSpace(name))
config.Sources.Add(new StreamSourceConfig { Name = name });
}
}
}
if (root.TryGetProperty("replicas", out var replicasEl) && replicasEl.TryGetInt32(out var replicas))
config.Replicas = replicas;