feat: implement full MQTT Go parity across 5 phases — binary protocol, auth/TLS, cross-protocol bridging, monitoring, and JetStream persistence
Phase 1: Binary MQTT 3.1.1 wire protocol with PipeReader-based parsing, full packet type dispatch, and MQTT 3.1.1 compliance checks. Phase 2: Auth pipeline routing MQTT CONNECT through AuthService, TLS transport with SslStream wrapping, pinned cert validation. Phase 3: IMessageRouter refactor (NatsClient → INatsClient), MqttNatsClientAdapter for cross-protocol bridging, MqttTopicMapper with full Go-parity topic/subject translation. Phase 4: /connz mqtt_client field population, /varz actual MQTT port. Phase 5: JetStream persistence — MqttStreamInitializer creates 5 internal streams, MqttConsumerManager for QoS 1/2 consumers, subject-keyed session/retained lookups replacing linear scans. All 503 MQTT tests and 1589 Core tests pass.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
// QoS 1 outgoing message tracker for MQTT.
|
||||
// QoS 1 outgoing message tracker for MQTT with JetStream ack integration.
|
||||
// Go reference: golang/nats-server/server/mqtt.go
|
||||
// QoS 1 outbound tracking — mqttProcessPub (~line 1200)
|
||||
// trackPublish — maps packet IDs to stream sequences for ack tracking.
|
||||
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
@@ -8,8 +9,8 @@ namespace NATS.Server.Mqtt;
|
||||
|
||||
/// <summary>
|
||||
/// Tracks outgoing QoS 1 messages pending PUBACK from the client.
|
||||
/// Messages are stored with their packet ID and can be redelivered on reconnect.
|
||||
/// Go reference: server/mqtt.go — mqttProcessPub (QoS 1 outbound tracking).
|
||||
/// Maps packet IDs to JetStream stream sequences for ack-based cleanup.
|
||||
/// Go reference: server/mqtt.go — mqttProcessPub, trackPublish.
|
||||
/// </summary>
|
||||
public sealed class MqttQoS1Tracker
|
||||
{
|
||||
@@ -24,7 +25,7 @@ public sealed class MqttQoS1Tracker
|
||||
/// Registers an outgoing QoS 1 message and assigns a packet ID.
|
||||
/// Returns the assigned packet ID.
|
||||
/// </summary>
|
||||
public ushort Register(string topic, byte[] payload)
|
||||
public ushort Register(string topic, byte[] payload, ulong streamSequence = 0)
|
||||
{
|
||||
var id = GetNextPacketId();
|
||||
_pending[id] = new QoS1PendingMessage
|
||||
@@ -34,17 +35,18 @@ public sealed class MqttQoS1Tracker
|
||||
Payload = payload,
|
||||
SentAtUtc = DateTime.UtcNow,
|
||||
DeliveryCount = 1,
|
||||
StreamSequence = streamSequence,
|
||||
};
|
||||
return id;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Acknowledges receipt of a PUBACK for the given packet ID.
|
||||
/// Returns true if the message was found and removed.
|
||||
/// Returns the pending message if found, or null.
|
||||
/// </summary>
|
||||
public bool Acknowledge(ushort packetId)
|
||||
public QoS1PendingMessage? Acknowledge(ushort packetId)
|
||||
{
|
||||
return _pending.TryRemove(packetId, out _);
|
||||
return _pending.TryRemove(packetId, out var msg) ? msg : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -93,4 +95,11 @@ public sealed class QoS1PendingMessage
|
||||
public byte[] Payload { get; init; } = [];
|
||||
public DateTime SentAtUtc { get; set; }
|
||||
public int DeliveryCount { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// JetStream stream sequence for this message. 0 if not backed by JetStream.
|
||||
/// Used to ack the message in the stream on PUBACK.
|
||||
/// Go reference: server/mqtt.go trackPublish — maps packet ID → stream sequence.
|
||||
/// </summary>
|
||||
public ulong StreamSequence { get; init; }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user