feat: port session 01 — Foundation Types (const, errors, proto, ring, rate_counter, sdm)

Ports server/const.go, errors.go, proto.go, ring.go, rate_counter.go, sdm.go.
- ServerConstants: all protocol constants and version info from const.go
- ServerErrors: ~60 sentinel exceptions plus errCtx/configErr/processConfigErr types
- ProtoWire: protobuf varint encode/decode helpers (proto.go)
- RateCounter: sliding-window rate limiter (rate_counter.go)
- ClosedRingBuffer: fixed-size ring buffer for /connz (ring.go)
- StreamDeletionMeta: SDM tracking for JetStream cluster consensus (sdm.go)
- 5 unit tests passing (errors, ring buffer, rate counter)
- errors_gen.go (code generator tool) and nkey.go Server methods marked n_a
This commit is contained in:
Joseph Doherty
2026-02-26 09:15:20 -05:00
parent 66628bc25a
commit 8050ee1897
12 changed files with 1538 additions and 9 deletions

View File

@@ -0,0 +1,81 @@
// Copyright 2021-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/rate_counter.go in the NATS server Go source.
namespace ZB.MOM.NatsNet.Server.Internal;
/// <summary>
/// A sliding-window rate limiter that allows at most <c>limit</c> events
/// per <see cref="Interval"/> window.
/// Mirrors <c>rateCounter</c> in server/rate_counter.go.
/// </summary>
public sealed class RateCounter
{
private readonly long _limit;
private long _count;
private ulong _blocked;
private DateTime _end;
// Exposed for tests (mirrors direct field access in rate_counter_test.go).
public TimeSpan Interval;
private readonly object _lock = new();
public RateCounter(long limit)
{
_limit = limit;
Interval = TimeSpan.FromSeconds(1);
}
/// <summary>
/// Returns true if the event is within the rate limit for the current window.
/// Mirrors <c>rateCounter.allow</c>.
/// </summary>
public bool Allow()
{
var now = DateTime.UtcNow;
lock (_lock)
{
if (now > _end)
{
_count = 0;
_end = now + Interval;
}
else
{
_count++;
}
var allow = _count < _limit;
if (!allow)
_blocked++;
return allow;
}
}
/// <summary>
/// Returns and resets the count of blocked events since the last call.
/// Mirrors <c>rateCounter.countBlocked</c>.
/// </summary>
public ulong CountBlocked()
{
lock (_lock)
{
var blocked = _blocked;
_blocked = 0;
return blocked;
}
}
}