feat: port session 19 — JetStream Core
- JetStreamTypes: JetStreamConfig, JetStreamStats, JetStreamAccountLimits, JetStreamTier, JetStreamAccountStats, JetStream engine, JsAccount, JsaUsage - JetStreamApiTypes: 50+ JSApi request/response types, API subject constants - JetStreamErrors: JsApiError + JsApiErrors with all 203 error codes - JetStreamVersioning: version constants and API level helpers - JetStreamBatching: Batching, BatchGroup, BatchStagedDiff, BatchApply - Removed JetStreamConfig/JetStreamState stubs from NatsServerTypes.cs - 374 features complete (IDs 1368-1519, 1751-1972)
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
// Copyright 2024-2025 The NATS Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// Adapted from server/jetstream_versioning.go in the NATS server Go source.
|
||||
|
||||
namespace ZB.MOM.NatsNet.Server;
|
||||
|
||||
/// <summary>
|
||||
/// JetStream API level versioning constants and helpers.
|
||||
/// Mirrors server/jetstream_versioning.go.
|
||||
/// </summary>
|
||||
public static class JetStreamVersioning
|
||||
{
|
||||
/// <summary>Maximum supported JetStream API level for this server.</summary>
|
||||
public const int JsApiLevel = 3;
|
||||
|
||||
/// <summary>Metadata key that carries the required API level for a stream or consumer asset.</summary>
|
||||
public const string JsRequiredLevelMetadataKey = "_nats.req.level";
|
||||
|
||||
/// <summary>Metadata key that carries the server version that created/updated the asset.</summary>
|
||||
public const string JsServerVersionMetadataKey = "_nats.ver";
|
||||
|
||||
/// <summary>Metadata key that carries the server API level that created/updated the asset.</summary>
|
||||
public const string JsServerLevelMetadataKey = "_nats.level";
|
||||
|
||||
// ---- API level feature gates ----
|
||||
// These document which API level each feature requires.
|
||||
// They correspond to the requires() calls in setStaticStreamMetadata / setStaticConsumerMetadata.
|
||||
|
||||
/// <summary>API level required for per-message TTL and SubjectDeleteMarkerTTL (v2.11).</summary>
|
||||
public const int ApiLevelForTTL = 1;
|
||||
|
||||
/// <summary>API level required for consumer PauseUntil (v2.11).</summary>
|
||||
public const int ApiLevelForConsumerPause = 1;
|
||||
|
||||
/// <summary>API level required for priority groups (v2.11).</summary>
|
||||
public const int ApiLevelForPriorityGroups = 1;
|
||||
|
||||
/// <summary>API level required for counter CRDTs (v2.12).</summary>
|
||||
public const int ApiLevelForCounters = 2;
|
||||
|
||||
/// <summary>API level required for atomic batch publishing (v2.12).</summary>
|
||||
public const int ApiLevelForAtomicPublish = 2;
|
||||
|
||||
/// <summary>API level required for message scheduling (v2.12).</summary>
|
||||
public const int ApiLevelForMsgSchedules = 2;
|
||||
|
||||
/// <summary>API level required for async persist mode (v2.12).</summary>
|
||||
public const int ApiLevelForAsyncPersist = 2;
|
||||
|
||||
// ---- Helper methods ----
|
||||
|
||||
/// <summary>
|
||||
/// Returns the required API level string from stream or consumer metadata,
|
||||
/// or an empty string if not set.
|
||||
/// Mirrors <c>getRequiredApiLevel</c>.
|
||||
/// </summary>
|
||||
public static string GetRequiredApiLevel(IDictionary<string, string>? metadata)
|
||||
{
|
||||
if (metadata is not null && metadata.TryGetValue(JsRequiredLevelMetadataKey, out var l) && l.Length > 0)
|
||||
return l;
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether this server supports the required API level encoded in the asset's metadata.
|
||||
/// Mirrors <c>supportsRequiredApiLevel</c>.
|
||||
/// </summary>
|
||||
public static bool SupportsRequiredApiLevel(IDictionary<string, string>? metadata)
|
||||
{
|
||||
var l = GetRequiredApiLevel(metadata);
|
||||
if (l.Length == 0) return true;
|
||||
return int.TryParse(l, out var level) && level <= JsApiLevel;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes dynamic (per-response) versioning fields from metadata.
|
||||
/// These should never be stored; only added in API responses.
|
||||
/// Mirrors <c>deleteDynamicMetadata</c>.
|
||||
/// </summary>
|
||||
public static void DeleteDynamicMetadata(IDictionary<string, string> metadata)
|
||||
{
|
||||
metadata.Remove(JsServerVersionMetadataKey);
|
||||
metadata.Remove(JsServerLevelMetadataKey);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether a request should be rejected based on the Nats-Required-Api-Level header value.
|
||||
/// Mirrors <c>errorOnRequiredApiLevel</c>.
|
||||
/// </summary>
|
||||
public static bool ErrorOnRequiredApiLevel(string? reqApiLevelHeader)
|
||||
{
|
||||
if (string.IsNullOrEmpty(reqApiLevelHeader)) return false;
|
||||
return !int.TryParse(reqApiLevelHeader, out var minLevel) || JsApiLevel < minLevel;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user