feat(batch45): implement events server methods — stats, remote tracking, connection events
Port 80 features from server/events.go including the full events infrastructure: internal send/receive loops, system subscription machinery, statsz heartbeats, remote server tracking, connection event advisories, user-info handler, OCSP peer reject events, remote latency merge, kick/ldm client, and helper functions. Add ClearConnectionHeartbeatTimer/SetConnectionHeartbeatTimer to Account, add MsgHandler/SysMsgHandler delegates and supporting types (ServerApiResponse, EventFilterOptions, StatszEventOptions, UserInfo, KickClientReq, LdmClientReq, AccNumSubsReq) to EventTypes.cs, and add Seq field to ServerInfo for heartbeat sequence tracking.
This commit is contained in:
@@ -4507,6 +4507,28 @@ public sealed partial class Account : INatsAccount
|
|||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clears the connection-heartbeat timer. Caller must hold the account lock.
|
||||||
|
/// Mirrors Go <c>(a *Account) clearConnectionTimer()</c> in server/events.go.
|
||||||
|
/// </summary>
|
||||||
|
internal void ClearConnectionHeartbeatTimer()
|
||||||
|
{
|
||||||
|
ClearTimerLocked(ref _ctmr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Starts or resets the connection-heartbeat timer.
|
||||||
|
/// Caller must hold the account lock.
|
||||||
|
/// Mirrors Go inline timer setup in <c>sendAccConnsUpdate()</c>.
|
||||||
|
/// </summary>
|
||||||
|
internal void SetConnectionHeartbeatTimer(long delayMs, Action callback)
|
||||||
|
{
|
||||||
|
if (_ctmr == null)
|
||||||
|
_ctmr = new Timer(_ => callback(), null, delayMs, Timeout.Infinite);
|
||||||
|
else
|
||||||
|
_ctmr.Change(delayMs, Timeout.Infinite);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Stops and nulls out a timer. Lock must be held by the caller.
|
/// Stops and nulls out a timer. Lock must be held by the caller.
|
||||||
/// Mirrors Go <c>clearTimer(t **time.Timer)</c>.
|
/// Mirrors Go <c>clearTimer(t **time.Timer)</c>.
|
||||||
|
|||||||
82
dotnet/src/ZB.MOM.NatsNet.Server/Events/EventHelpers.cs
Normal file
82
dotnet/src/ZB.MOM.NatsNet.Server/Events/EventHelpers.cs
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
// Copyright 2018-2026 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/events.go (package-level helpers) in the NATS server Go source.
|
||||||
|
|
||||||
|
namespace ZB.MOM.NatsNet.Server;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Package-level helper functions used by the events subsystem.
|
||||||
|
/// Mirrors Go package-level functions in server/events.go.
|
||||||
|
/// </summary>
|
||||||
|
internal static class EventHelpers
|
||||||
|
{
|
||||||
|
// =========================================================================
|
||||||
|
// accForClient — mirrors Go accForClient
|
||||||
|
// =========================================================================
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the account name for the given client connection.
|
||||||
|
/// Mirrors Go <c>accForClient(c *client) string</c> in server/events.go.
|
||||||
|
/// </summary>
|
||||||
|
internal static string AccForClient(ClientConnection c)
|
||||||
|
{
|
||||||
|
var acc = c._account as Account;
|
||||||
|
return acc?.Name ?? "N/A";
|
||||||
|
}
|
||||||
|
|
||||||
|
// =========================================================================
|
||||||
|
// issuerForClient — mirrors Go issuerForClient
|
||||||
|
// =========================================================================
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the issuer key for the given client connection.
|
||||||
|
/// In Go this inspects c.user.SigningKey / c.user.Account.Name.
|
||||||
|
/// In .NET the NkeyUser signing key is not stored on ClientConnection;
|
||||||
|
/// we return an empty string (same as Go when c.user == nil).
|
||||||
|
/// Mirrors Go <c>issuerForClient(c *client) string</c> in server/events.go.
|
||||||
|
/// </summary>
|
||||||
|
internal static string IssuerForClient(ClientConnection c)
|
||||||
|
{
|
||||||
|
// ClientConnection does not expose a stored User/NkeyUser reference
|
||||||
|
// with a SigningKey after registration. Return empty (safe default).
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
// =========================================================================
|
||||||
|
// respondToUpdate — mirrors Go respondToUpdate
|
||||||
|
// =========================================================================
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sends an account JWT update response back to the requesting server.
|
||||||
|
/// Mirrors Go <c>respondToUpdate(s *Server, respSubj, acc, message string, err error)</c>
|
||||||
|
/// in server/accounts.go (called from events.go).
|
||||||
|
/// </summary>
|
||||||
|
internal static void RespondToUpdate(NatsServer s, string respSubj, string acc, string message, Exception? err)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(respSubj))
|
||||||
|
return;
|
||||||
|
|
||||||
|
string response;
|
||||||
|
if (err != null)
|
||||||
|
response = string.IsNullOrEmpty(acc)
|
||||||
|
? $"{message}: {err.Message}"
|
||||||
|
: $"[{acc}] {message}: {err.Message}";
|
||||||
|
else
|
||||||
|
response = string.IsNullOrEmpty(acc)
|
||||||
|
? message
|
||||||
|
: $"[{acc}] {message}";
|
||||||
|
|
||||||
|
s.SendInternalMsg(respSubj, string.Empty, null, response);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -151,13 +151,212 @@ public static class EventIntervals
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public delegate void SysMsgHandler(
|
public delegate void SysMsgHandler(
|
||||||
Subscription sub,
|
Subscription sub,
|
||||||
NatsClient client,
|
ClientConnection client,
|
||||||
Account acc,
|
Account acc,
|
||||||
string subject,
|
string subject,
|
||||||
string reply,
|
string reply,
|
||||||
byte[] hdr,
|
byte[] hdr,
|
||||||
byte[] msg);
|
byte[] msg);
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// MsgHandler — subscription message callback delegate
|
||||||
|
// Mirrors Go <c>msgHandler</c> func type in server/events.go.
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Callback for a subscription message. Identical signature to
|
||||||
|
/// <see cref="SysMsgHandler"/>; the distinction exists in Go but is
|
||||||
|
/// collapsed here since both carry the same parameters.
|
||||||
|
/// Mirrors Go <c>msgHandler</c> in server/events.go.
|
||||||
|
/// </summary>
|
||||||
|
public delegate void MsgHandler(
|
||||||
|
Subscription sub,
|
||||||
|
ClientConnection client,
|
||||||
|
Account acc,
|
||||||
|
string subject,
|
||||||
|
string reply,
|
||||||
|
byte[] hdr,
|
||||||
|
byte[] msg);
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// ServerApiError — error payload for server API responses
|
||||||
|
// Mirrors Go <c>ApiError</c> used in server/events.go responses.
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Error payload returned in <see cref="ServerApiResponse"/> when a
|
||||||
|
/// monitoring z-endpoint request fails.
|
||||||
|
/// Mirrors Go <c>ApiError</c> struct used by server API responses.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class ServerApiError
|
||||||
|
{
|
||||||
|
[System.Text.Json.Serialization.JsonPropertyName("code")]
|
||||||
|
public int Code { get; set; }
|
||||||
|
|
||||||
|
[System.Text.Json.Serialization.JsonPropertyName("description")]
|
||||||
|
public string Description { get; set; } = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// ServerApiResponse — wrapper for server API (z-endpoint) responses
|
||||||
|
// Mirrors Go <c>ServerAPIResponse</c> in server/events.go.
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Standard envelope returned by server monitoring API (varz, connz, etc.)
|
||||||
|
/// published via the internal system bus.
|
||||||
|
/// Mirrors Go <c>ServerAPIResponse</c> in server/events.go.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class ServerApiResponse
|
||||||
|
{
|
||||||
|
[System.Text.Json.Serialization.JsonPropertyName("server")]
|
||||||
|
public ServerInfo? Server { get; set; }
|
||||||
|
|
||||||
|
[System.Text.Json.Serialization.JsonPropertyName("data")]
|
||||||
|
[System.Text.Json.Serialization.JsonIgnore(Condition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
public object? Data { get; set; }
|
||||||
|
|
||||||
|
[System.Text.Json.Serialization.JsonPropertyName("error")]
|
||||||
|
[System.Text.Json.Serialization.JsonIgnore(Condition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
public ServerApiError? Error { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// EventFilterOptions — server filter options for z-endpoint requests
|
||||||
|
// Mirrors Go <c>EventFilterOptions</c> in server/events.go.
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Filter parameters sent in monitoring z-endpoint request messages that
|
||||||
|
/// allow targeting a specific server, cluster, or set of tags.
|
||||||
|
/// Mirrors Go <c>EventFilterOptions</c> in server/events.go.
|
||||||
|
/// </summary>
|
||||||
|
public class EventFilterOptions
|
||||||
|
{
|
||||||
|
[System.Text.Json.Serialization.JsonPropertyName("server_name")]
|
||||||
|
[System.Text.Json.Serialization.JsonIgnore(Condition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
public string? Name { get; set; }
|
||||||
|
|
||||||
|
[System.Text.Json.Serialization.JsonPropertyName("cluster")]
|
||||||
|
[System.Text.Json.Serialization.JsonIgnore(Condition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
public string? Cluster { get; set; }
|
||||||
|
|
||||||
|
[System.Text.Json.Serialization.JsonPropertyName("host")]
|
||||||
|
[System.Text.Json.Serialization.JsonIgnore(Condition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
public string? Host { get; set; }
|
||||||
|
|
||||||
|
[System.Text.Json.Serialization.JsonPropertyName("domain")]
|
||||||
|
[System.Text.Json.Serialization.JsonIgnore(Condition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
public string? Domain { get; set; }
|
||||||
|
|
||||||
|
[System.Text.Json.Serialization.JsonPropertyName("tags")]
|
||||||
|
[System.Text.Json.Serialization.JsonIgnore(Condition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
public List<string>? Tags { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// When true, name/cluster/host must match exactly; when false, substring
|
||||||
|
/// matching is used.
|
||||||
|
/// Mirrors Go <c>EventFilterOptions.ExactMatch</c>.
|
||||||
|
/// </summary>
|
||||||
|
[System.Text.Json.Serialization.JsonPropertyName("exact")]
|
||||||
|
public bool ExactMatch { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// UserInfo — user info response payload for $SYS.REQ.USER.INFO
|
||||||
|
// Mirrors Go <c>UserInfo</c> struct in server/events.go.
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Response payload returned by the <c>$SYS.REQ.USER.INFO</c> endpoint.
|
||||||
|
/// Contains the authenticated user's identity, account, permissions, and
|
||||||
|
/// claim expiry.
|
||||||
|
/// Mirrors Go <c>UserInfo</c> struct in server/events.go.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class UserInfo
|
||||||
|
{
|
||||||
|
[System.Text.Json.Serialization.JsonPropertyName("userId")]
|
||||||
|
public string UserId { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[System.Text.Json.Serialization.JsonPropertyName("account")]
|
||||||
|
public string Account { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[System.Text.Json.Serialization.JsonPropertyName("permissions")]
|
||||||
|
[System.Text.Json.Serialization.JsonIgnore(Condition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
public object? Permissions { get; set; }
|
||||||
|
|
||||||
|
[System.Text.Json.Serialization.JsonPropertyName("expires")]
|
||||||
|
[System.Text.Json.Serialization.JsonIgnore(Condition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingDefault)]
|
||||||
|
public DateTime Expires { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// KickClientReq / LdmClientReq — client control request payloads
|
||||||
|
// Mirrors Go anonymous structs used in server/events.go.
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Request payload for <c>$SYS.REQ.SERVER.{id}.KICK</c>, which asks this
|
||||||
|
/// server to forcefully disconnect the client with the given CID.
|
||||||
|
/// Mirrors the anonymous struct used in <c>Server.kickClient()</c>.
|
||||||
|
/// </summary>
|
||||||
|
internal sealed class KickClientReq
|
||||||
|
{
|
||||||
|
[System.Text.Json.Serialization.JsonPropertyName("cid")]
|
||||||
|
public ulong Cid { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Request payload for <c>$SYS.REQ.SERVER.{id}.LDM</c>, which asks this
|
||||||
|
/// server to put the client with the given CID into lame-duck mode.
|
||||||
|
/// Mirrors the anonymous struct used in <c>Server.ldmClient()</c>.
|
||||||
|
/// </summary>
|
||||||
|
internal sealed class LdmClientReq
|
||||||
|
{
|
||||||
|
[System.Text.Json.Serialization.JsonPropertyName("cid")]
|
||||||
|
public ulong Cid { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// StatszEventOptions — options for statsz z-endpoint requests
|
||||||
|
// Mirrors Go <c>StatszEventOptions</c> in server/events.go.
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Options embedded in z-endpoint request messages that allow filtering and
|
||||||
|
/// configuring the statsz response.
|
||||||
|
/// Mirrors Go <c>StatszEventOptions</c> in server/events.go.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class StatszEventOptions : EventFilterOptions
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// AccNumSubsReq — request payload for subscription count queries
|
||||||
|
// Mirrors Go <c>accNumSubsReq</c> struct in server/events.go.
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Payload for <c>$SYS.REQ.ACCOUNT.NSUBS</c> requests, which ask a remote
|
||||||
|
/// server how many local subscriptions exist for a given account + subject.
|
||||||
|
/// Mirrors Go <c>accNumSubsReq</c> in server/events.go.
|
||||||
|
/// </summary>
|
||||||
|
internal sealed class AccNumSubsReq
|
||||||
|
{
|
||||||
|
[System.Text.Json.Serialization.JsonPropertyName("server")]
|
||||||
|
public ServerInfo Server { get; set; } = new();
|
||||||
|
|
||||||
|
[System.Text.Json.Serialization.JsonPropertyName("acc")]
|
||||||
|
public string Account { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[System.Text.Json.Serialization.JsonPropertyName("subject")]
|
||||||
|
public string Subject { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[System.Text.Json.Serialization.JsonPropertyName("queue")]
|
||||||
|
[System.Text.Json.Serialization.JsonIgnore(Condition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
public string? Queue { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// InSysMsg — queued internal system message
|
// InSysMsg — queued internal system message
|
||||||
// Mirrors Go <c>inSysMsg</c> struct in server/events.go.
|
// Mirrors Go <c>inSysMsg</c> struct in server/events.go.
|
||||||
@@ -170,9 +369,9 @@ public delegate void SysMsgHandler(
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
internal sealed class InSysMsg
|
internal sealed class InSysMsg
|
||||||
{
|
{
|
||||||
public Subscription? Sub { get; set; }
|
public Subscription? Sub { get; set; }
|
||||||
public NatsClient? Client { get; set; }
|
public ClientConnection? Client { get; set; }
|
||||||
public Account? Acc { get; set; }
|
public Account? Acc { get; set; }
|
||||||
public string Subject { get; set; } = string.Empty;
|
public string Subject { get; set; } = string.Empty;
|
||||||
public string Reply { get; set; } = string.Empty;
|
public string Reply { get; set; } = string.Empty;
|
||||||
public byte[]? Hdr { get; set; }
|
public byte[]? Hdr { get; set; }
|
||||||
@@ -195,10 +394,10 @@ internal sealed class InSysMsg
|
|||||||
internal sealed class InternalState
|
internal sealed class InternalState
|
||||||
{
|
{
|
||||||
// ---- identity / sequencing ----
|
// ---- identity / sequencing ----
|
||||||
public Account? Account { get; set; }
|
public Account? Account { get; set; }
|
||||||
public NatsClient? Client { get; set; }
|
public ClientConnection? Client { get; set; }
|
||||||
public ulong Seq { get; set; }
|
public ulong Seq { get; set; }
|
||||||
public int Sid { get; set; }
|
public int Sid { get; set; }
|
||||||
|
|
||||||
// ---- remote server tracking ----
|
// ---- remote server tracking ----
|
||||||
/// <summary>Map of server ID → serverUpdate. Mirrors Go <c>servers map[string]*serverUpdate</c>.</summary>
|
/// <summary>Map of server ID → serverUpdate. Mirrors Go <c>servers map[string]*serverUpdate</c>.</summary>
|
||||||
@@ -216,7 +415,7 @@ internal sealed class InternalState
|
|||||||
/// Pending reply subject → handler map.
|
/// Pending reply subject → handler map.
|
||||||
/// Mirrors Go <c>replies map[string]msgHandler</c>.
|
/// Mirrors Go <c>replies map[string]msgHandler</c>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Dictionary<string, Action<Subscription, NatsClient, Account, string, string, byte[], byte[]>> Replies { get; set; } = new();
|
public Dictionary<string, Action<Subscription, ClientConnection, Account, string, string, byte[], byte[]>> Replies { get; set; } = new();
|
||||||
|
|
||||||
// ---- queues ----
|
// ---- queues ----
|
||||||
/// <summary>Outbound message send queue. Mirrors Go <c>sendq *ipQueue[*pubMsg]</c>.</summary>
|
/// <summary>Outbound message send queue. Mirrors Go <c>sendq *ipQueue[*pubMsg]</c>.</summary>
|
||||||
@@ -289,8 +488,8 @@ internal sealed class ServerUpdate
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
internal sealed class PubMsg
|
internal sealed class PubMsg
|
||||||
{
|
{
|
||||||
public NatsClient? Client { get; set; }
|
public ClientConnection? Client { get; set; }
|
||||||
public string Subject { get; set; } = string.Empty;
|
public string Subject { get; set; } = string.Empty;
|
||||||
public string Reply { get; set; } = string.Empty;
|
public string Reply { get; set; } = string.Empty;
|
||||||
public ServerInfo? Si { get; set; }
|
public ServerInfo? Si { get; set; }
|
||||||
public byte[]? Hdr { get; set; }
|
public byte[]? Hdr { get; set; }
|
||||||
|
|||||||
2196
dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.Events.cs
Normal file
2196
dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.Events.cs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -88,6 +88,12 @@ public sealed class ServerInfo
|
|||||||
// LeafNode-specific
|
// LeafNode-specific
|
||||||
[JsonPropertyName("leafnode_urls")] public string[]? LeafNodeUrls { get; set; }
|
[JsonPropertyName("leafnode_urls")] public string[]? LeafNodeUrls { get; set; }
|
||||||
|
|
||||||
|
// Events / heartbeat sequence number.
|
||||||
|
// Mirrors Go <c>Info.Seq uint64</c> used in server heartbeat messages.
|
||||||
|
[JsonPropertyName("seq")]
|
||||||
|
[System.Text.Json.Serialization.JsonIgnore(Condition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingDefault)]
|
||||||
|
public ulong Seq { get; set; }
|
||||||
|
|
||||||
/// <summary>Returns a shallow clone of this <see cref="ServerInfo"/>.</summary>
|
/// <summary>Returns a shallow clone of this <see cref="ServerInfo"/>.</summary>
|
||||||
internal ServerInfo ShallowClone() => (ServerInfo)MemberwiseClone();
|
internal ServerInfo ShallowClone() => (ServerInfo)MemberwiseClone();
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
porting.db
BIN
porting.db
Binary file not shown.
@@ -1,6 +1,6 @@
|
|||||||
# NATS .NET Porting Status Report
|
# NATS .NET Porting Status Report
|
||||||
|
|
||||||
Generated: 2026-03-01 12:56:43 UTC
|
Generated: 2026-03-01 14:41:00 UTC
|
||||||
|
|
||||||
## Modules (12 total)
|
## Modules (12 total)
|
||||||
|
|
||||||
@@ -13,10 +13,10 @@ Generated: 2026-03-01 12:56:43 UTC
|
|||||||
| Status | Count |
|
| Status | Count |
|
||||||
|--------|-------|
|
|--------|-------|
|
||||||
| complete | 22 |
|
| complete | 22 |
|
||||||
| deferred | 363 |
|
| deferred | 284 |
|
||||||
| n_a | 24 |
|
| n_a | 24 |
|
||||||
| stub | 1 |
|
| stub | 1 |
|
||||||
| verified | 3263 |
|
| verified | 3342 |
|
||||||
|
|
||||||
## Unit Tests (3257 total)
|
## Unit Tests (3257 total)
|
||||||
|
|
||||||
@@ -35,4 +35,4 @@ Generated: 2026-03-01 12:56:43 UTC
|
|||||||
|
|
||||||
## Overall Progress
|
## Overall Progress
|
||||||
|
|
||||||
**5694/6942 items complete (82.0%)**
|
**5773/6942 items complete (83.2%)**
|
||||||
|
|||||||
Reference in New Issue
Block a user