fix: correct MaxBytes enforcement and consumer start sequence after purge

StreamManager.Capture now accounts for full message size (subject +
payload + 16-byte overhead) when checking MaxBytes, matching Go's
memStoreMsgSize. PullConsumerEngine uses stream FirstSeq instead of
hardcoded 1 for DeliverAll after purge. Fix 6 tests with Go parity
assertions and updated MaxBytes values.
This commit is contained in:
Joseph Doherty
2026-02-24 23:59:37 -05:00
parent 1f83df12e4
commit 51ebded300
8 changed files with 6404 additions and 24 deletions

View File

@@ -29,11 +29,14 @@ public class JetStreamStreamCrudTests
[Fact]
public async Task Create_stream_with_discard_new_policy()
{
// Each message size = subject + payload + 16 overhead.
// Two small messages: ("dn.one"=6 + "1"=1 + 16=23) + ("dn.two"=6 + "2"=1 + 16=23) = 46 bytes.
// MaxBytes=50 allows both small messages but rejects the large third one.
await using var fx = await JetStreamApiFixture.StartWithStreamConfigAsync(new StreamConfig
{
Name = "DN",
Subjects = ["dn.>"],
MaxBytes = 30,
MaxBytes = 50,
Discard = DiscardPolicy.New,
});
@@ -319,15 +322,20 @@ public class JetStreamStreamCrudTests
state.Messages.ShouldBeLessThanOrEqualTo(3UL);
}
// Go: TestJetStreamMaxBytesIgnored server/jetstream_test.go
// Go: TestJetStreamMaxBytesIgnored server/jetstream_test.go:15778
// Go test uses 10MB limit with 1MB messages, expects 9 messages retained.
// We use smaller sizes but same principle: MaxBytes caps stored bytes,
// accounting for per-message overhead (subject + 16 bytes).
[Fact]
public async Task Stream_with_max_bytes_discard_old_evicts_oldest()
{
// Each stored message = subject("bytes.x"=7) + payload(20) + overhead(16) = 43 bytes.
// MaxBytes=200 holds ~4 messages (4*43=172). Publishing 20 should evict old ones.
await using var fx = await JetStreamApiFixture.StartWithStreamConfigAsync(new StreamConfig
{
Name = "BYTES",
Subjects = ["bytes.>"],
MaxBytes = 100,
MaxBytes = 200,
Discard = DiscardPolicy.Old,
});
@@ -335,7 +343,8 @@ public class JetStreamStreamCrudTests
_ = await fx.PublishAndGetAckAsync("bytes.x", $"payload-{i:D10}");
var state = await fx.GetStreamStateAsync("BYTES");
((long)state.Bytes).ShouldBeLessThanOrEqualTo(100L);
((long)state.Bytes).ShouldBeLessThanOrEqualTo(200L);
state.Messages.ShouldBeLessThan(20UL);
}
// Go: TestJetStreamMaxMsgsPerSubject server/jetstream_test.go