feat: enforce account-scoped remote delivery semantics

This commit is contained in:
Joseph Doherty
2026-02-23 14:36:44 -05:00
parent ec373d36f6
commit 6a05308143
10 changed files with 531 additions and 44 deletions

View File

@@ -871,7 +871,7 @@ public sealed class NatsServer : IMessageRouter, ISubListAccess, IDisposable
private void ProcessRoutedMessage(RouteMessage message)
{
DeliverRemoteMessage(message.Subject, message.ReplyTo, message.Payload);
DeliverRemoteMessage(message.Account, message.Subject, message.ReplyTo, message.Payload);
}
private void ProcessGatewayMessage(GatewayMessage message)
@@ -880,7 +880,7 @@ public sealed class NatsServer : IMessageRouter, ISubListAccess, IDisposable
if (ReplyMapper.TryRestoreGatewayReply(replyTo, out var restoredReply))
replyTo = restoredReply;
DeliverRemoteMessage(message.Subject, replyTo, message.Payload);
DeliverRemoteMessage(message.Account, message.Subject, replyTo, message.Payload);
}
private void ProcessLeafMessage(LeafMessage message)
@@ -892,12 +892,13 @@ public sealed class NatsServer : IMessageRouter, ISubListAccess, IDisposable
if (LeafLoopDetector.TryUnmark(subject, out var unmarked))
subject = unmarked;
DeliverRemoteMessage(subject, message.ReplyTo, message.Payload);
DeliverRemoteMessage(message.Account, subject, message.ReplyTo, message.Payload);
}
private void DeliverRemoteMessage(string subject, string? replyTo, ReadOnlyMemory<byte> payload)
private void DeliverRemoteMessage(string account, string subject, string? replyTo, ReadOnlyMemory<byte> payload)
{
var result = _globalAccount.SubList.Match(subject);
var targetAccount = GetOrCreateAccount(account);
var result = targetAccount.SubList.Match(subject);
foreach (var sub in result.PlainSubs)
DeliverMessage(sub, subject, replyTo, default, payload);
@@ -948,17 +949,17 @@ public sealed class NatsServer : IMessageRouter, ISubListAccess, IDisposable
var senderAccount = sender.Account ?? _globalAccount;
if (_routeManager != null && senderAccount.SubList.HasRemoteInterest(senderAccount.Name, subject))
_routeManager.ForwardRoutedMessageAsync(subject, replyTo, payload, default).GetAwaiter().GetResult();
_routeManager.ForwardRoutedMessageAsync(senderAccount.Name, subject, replyTo, payload, default).GetAwaiter().GetResult();
if (_gatewayManager != null && senderAccount.SubList.HasRemoteInterest(senderAccount.Name, subject))
{
var mappedReplyTo = ReplyMapper.ToGatewayReply(replyTo, ServerId);
_gatewayManager.ForwardMessageAsync(subject, mappedReplyTo, payload, default).GetAwaiter().GetResult();
_gatewayManager.ForwardMessageAsync(senderAccount.Name, subject, mappedReplyTo, payload, default).GetAwaiter().GetResult();
}
if (_leafNodeManager != null && senderAccount.SubList.HasRemoteInterest(senderAccount.Name, subject))
{
var markedSubject = LeafLoopDetector.Mark(subject, ServerId);
_leafNodeManager.ForwardMessageAsync(markedSubject, replyTo, payload, default).GetAwaiter().GetResult();
_leafNodeManager.ForwardMessageAsync(senderAccount.Name, markedSubject, replyTo, payload, default).GetAwaiter().GetResult();
}
var subList = sender.Account?.SubList ?? _globalAccount.SubList;