@@ -24742,7 +24742,7 @@ func TestJetStreamWouldExceedLimits(t *testing.T) {
24742
24742
require_True(t, js.wouldExceedLimits(FileStorage, int(js.config.MaxStore)+1))
24743
24743
}
24744
24744
24745
- func TestJetStreamConsumerDecrementPendingCountOnSkippedMsg (t *testing.T) {
24745
+ func TestJetStreamConsumerDontDecrementPendingCountOnSkippedMsg (t *testing.T) {
24746
24746
s := RunBasicJetStreamServer(t)
24747
24747
defer s.Shutdown()
24748
24748
@@ -24768,7 +24768,7 @@ func TestJetStreamConsumerDecrementPendingCountOnSkippedMsg(t *testing.T) {
24768
24768
npc := o.npc
24769
24769
o.mu.RUnlock()
24770
24770
if npc != expected {
24771
- return fmt.Errorf("expected npc=%d, got %d", npc, expected )
24771
+ return fmt.Errorf("expected npc=%d, got %d", expected, npc )
24772
24772
}
24773
24773
return nil
24774
24774
})
@@ -24807,9 +24807,66 @@ func TestJetStreamConsumerDecrementPendingCountOnSkippedMsg(t *testing.T) {
24807
24807
o.decStreamPending(2, "foo")
24808
24808
requireExpected(1)
24809
24809
24810
- // This is the deleted message that was skipped, and we can decrement the pending count
24811
- // because it's not pending and only as long as the ack floor hasn't moved up yet.
24810
+ // This is the deleted message that was skipped, we've hit the race condition and are not able to
24811
+ // fix it at this point. If we decrement then we could have decremented it twice if the message
24812
+ // was removed as a result of an Ack with Interest or WorkQueue retention, instead of due to contention.
24812
24813
o.decStreamPending(3, "foo")
24814
+ requireExpected(1)
24815
+ }
24816
+
24817
+ func TestJetStreamConsumerPendingCountAfterMsgAckAboveFloor(t *testing.T) {
24818
+ s := RunBasicJetStreamServer(t)
24819
+ defer s.Shutdown()
24820
+
24821
+ nc, js := jsClientConnect(t, s)
24822
+ defer nc.Close()
24823
+
24824
+ _, err := js.AddStream(&nats.StreamConfig{
24825
+ Name: "TEST",
24826
+ Subjects: []string{"foo"},
24827
+ Retention: nats.WorkQueuePolicy,
24828
+ })
24829
+ require_NoError(t, err)
24830
+
24831
+ for i := 0; i < 2; i++ {
24832
+ _, err = js.Publish("foo", nil)
24833
+ require_NoError(t, err)
24834
+ }
24835
+
24836
+ sub, err := js.PullSubscribe("foo", "CONSUMER")
24837
+ require_NoError(t, err)
24838
+
24839
+ acc, err := s.lookupAccount(globalAccountName)
24840
+ require_NoError(t, err)
24841
+ mset, err := acc.lookupStream("TEST")
24842
+ require_NoError(t, err)
24843
+ o := mset.lookupConsumer("CONSUMER")
24844
+
24845
+ requireExpected := func(expected int64) {
24846
+ t.Helper()
24847
+ checkFor(t, time.Second, 10*time.Millisecond, func() error {
24848
+ o.mu.RLock()
24849
+ npc := o.npc
24850
+ o.mu.RUnlock()
24851
+ if npc != expected {
24852
+ return fmt.Errorf("expected npc=%d, got %d", expected, npc)
24853
+ }
24854
+ return nil
24855
+ })
24856
+ }
24857
+
24858
+ // Expect 2 messages pending.
24859
+ requireExpected(2)
24860
+
24861
+ // Fetch 2 messages and ack the last.
24862
+ msgs, err := sub.Fetch(2)
24863
+ require_NoError(t, err)
24864
+ require_Len(t, len(msgs), 2)
24865
+ msg := msgs[1]
24866
+ err = msg.AckSync()
24867
+ require_NoError(t, err)
24868
+
24869
+ // We've fetched 2 message so should report 0 pending.
24813
24870
requireExpected(0)
24814
24871
}
24815
24872
0 commit comments