Implements Interest retention policy logic that tracks which consumers are interested in each message subject and whether they have acknowledged delivery, retaining messages until all interested consumers have acked. Go reference: stream.go checkInterestState/noInterest.
92 lines
2.8 KiB
C#
92 lines
2.8 KiB
C#
using NATS.Server.JetStream;
|
|
|
|
namespace NATS.Server.Tests.JetStream;
|
|
|
|
/// <summary>
|
|
/// Tests for InterestRetentionPolicy per-consumer ack tracking.
|
|
/// Go reference: stream.go checkInterestState/noInterest.
|
|
/// </summary>
|
|
public class InterestRetentionTests
|
|
{
|
|
[Fact]
|
|
public void ShouldRetain_true_when_consumers_have_not_acked()
|
|
{
|
|
var policy = new InterestRetentionPolicy();
|
|
policy.RegisterInterest("consumer-A", "orders.>");
|
|
policy.RegisterInterest("consumer-B", "orders.>");
|
|
|
|
policy.ShouldRetain(1, "orders.new").ShouldBeTrue();
|
|
}
|
|
|
|
[Fact]
|
|
public void ShouldRetain_false_when_all_consumers_acked()
|
|
{
|
|
var policy = new InterestRetentionPolicy();
|
|
policy.RegisterInterest("consumer-A", "orders.>");
|
|
policy.RegisterInterest("consumer-B", "orders.>");
|
|
|
|
policy.AcknowledgeDelivery("consumer-A", 1);
|
|
policy.ShouldRetain(1, "orders.new").ShouldBeTrue(); // B hasn't acked
|
|
|
|
policy.AcknowledgeDelivery("consumer-B", 1);
|
|
policy.ShouldRetain(1, "orders.new").ShouldBeFalse(); // both acked
|
|
}
|
|
|
|
[Fact]
|
|
public void ShouldRetain_ignores_consumers_without_interest()
|
|
{
|
|
var policy = new InterestRetentionPolicy();
|
|
policy.RegisterInterest("consumer-A", "orders.>");
|
|
policy.RegisterInterest("consumer-B", "billing.>"); // no interest in orders
|
|
|
|
policy.AcknowledgeDelivery("consumer-A", 1);
|
|
policy.ShouldRetain(1, "orders.new").ShouldBeFalse(); // B has no interest
|
|
}
|
|
|
|
[Fact]
|
|
public void UnregisterInterest_removes_consumer()
|
|
{
|
|
var policy = new InterestRetentionPolicy();
|
|
policy.RegisterInterest("consumer-A", "x.>");
|
|
policy.RegisterInterest("consumer-B", "x.>");
|
|
|
|
policy.UnregisterInterest("consumer-B");
|
|
|
|
// Only A needs to ack
|
|
policy.AcknowledgeDelivery("consumer-A", 1);
|
|
policy.ShouldRetain(1, "x.y").ShouldBeFalse();
|
|
}
|
|
|
|
[Fact]
|
|
public void ShouldRetain_false_when_no_consumers_registered()
|
|
{
|
|
var policy = new InterestRetentionPolicy();
|
|
policy.ShouldRetain(1, "any.subject").ShouldBeFalse();
|
|
}
|
|
|
|
[Fact]
|
|
public void Multiple_sequences_tracked_independently()
|
|
{
|
|
var policy = new InterestRetentionPolicy();
|
|
policy.RegisterInterest("c1", "x.>");
|
|
|
|
policy.AcknowledgeDelivery("c1", 1);
|
|
policy.ShouldRetain(1, "x.y").ShouldBeFalse();
|
|
policy.ShouldRetain(2, "x.y").ShouldBeTrue(); // seq 2 not acked
|
|
}
|
|
|
|
[Fact]
|
|
public void ConsumerCount_tracks_registrations()
|
|
{
|
|
var policy = new InterestRetentionPolicy();
|
|
policy.ConsumerCount.ShouldBe(0);
|
|
|
|
policy.RegisterInterest("c1", "x.>");
|
|
policy.RegisterInterest("c2", "y.>");
|
|
policy.ConsumerCount.ShouldBe(2);
|
|
|
|
policy.UnregisterInterest("c1");
|
|
policy.ConsumerCount.ShouldBe(1);
|
|
}
|
|
}
|