@@ -744,7 +744,7 @@ func TestJetStreamClusterStreamOrphanMsgsAndReplicasDrifting(t *testing.T) {
744744 var expectedErr error
745745 var msgId string
746746 var smv StoreMsg
747- for i , mset := range msets {
747+ for _ , mset := range msets {
748748 mset .mu .RLock ()
749749 sm , err := mset .store .LoadMsg (seq , & smv )
750750 mset .mu .RUnlock ()
@@ -754,17 +754,14 @@ func TestJetStreamClusterStreamOrphanMsgsAndReplicasDrifting(t *testing.T) {
754754 // by all msets for that seq to prove consistency across replicas.
755755 // If one of the msets either returns no error or doesn't return
756756 // the same error, then that replica has drifted.
757- if msgId != _EMPTY_ {
758- t .Fatalf ("Expected MsgId %q for seq %d, but got error: %v" , msgId , seq , err )
759- } else if expectedErr == nil {
757+ if expectedErr == nil {
760758 expectedErr = err
761759 } else {
762760 require_Error (t , err , expectedErr )
763761 }
764762 continue
765763 }
766- // Only set expected msg ID if it's for the very first time.
767- if msgId == _EMPTY_ && i == 0 {
764+ if msgId == _EMPTY_ {
768765 msgId = string (sm .hdr )
769766 } else if msgId != string (sm .hdr ) {
770767 t .Fatalf ("MsgIds do not match for seq %d: %q vs %q" , seq , msgId , sm .hdr )
@@ -4673,3 +4670,116 @@ func TestJetStreamClusterRoutedAPIRecoverPerformance(t *testing.T) {
46734670 ljs .mu .Lock ()
46744671 t .Logf ("Took %s to clear %d items" , time .Since (start ), count )
46754672}
4673+
4674+ func TestJetStreamClusterStreamAckMsgR1SignalsRemovedMsg (t * testing.T ) {
4675+ c := createJetStreamClusterExplicit (t , "R3S" , 3 )
4676+ defer c .shutdown ()
4677+
4678+ nc , js := jsClientConnect (t , c .randomServer ())
4679+ defer nc .Close ()
4680+
4681+ _ , err := js .AddStream (& nats.StreamConfig {
4682+ Name : "TEST" ,
4683+ Subjects : []string {"foo" },
4684+ Retention : nats .WorkQueuePolicy ,
4685+ Replicas : 1 ,
4686+ })
4687+ require_NoError (t , err )
4688+
4689+ _ , err = js .AddConsumer ("TEST" , & nats.ConsumerConfig {
4690+ Durable : "CONSUMER" ,
4691+ Replicas : 1 ,
4692+ AckPolicy : nats .AckExplicitPolicy ,
4693+ })
4694+ require_NoError (t , err )
4695+
4696+ _ , err = js .Publish ("foo" , nil )
4697+ require_NoError (t , err )
4698+
4699+ s := c .streamLeader (globalAccountName , "TEST" )
4700+ acc , err := s .lookupAccount (globalAccountName )
4701+ require_NoError (t , err )
4702+ mset , err := acc .lookupStream ("TEST" )
4703+ require_NoError (t , err )
4704+ o := mset .lookupConsumer ("CONSUMER" )
4705+ require_NotNil (t , o )
4706+
4707+ // Too high sequence, should register pre-ack and return true allowing for retries.
4708+ require_True (t , mset .ackMsg (o , 100 ))
4709+
4710+ var smv StoreMsg
4711+ sm , err := mset .store .LoadMsg (1 , & smv )
4712+ require_NoError (t , err )
4713+ require_Equal (t , sm .subj , "foo" )
4714+
4715+ // Now do a proper ack, should immediately remove the message since it's R1.
4716+ require_True (t , mset .ackMsg (o , 1 ))
4717+ _ , err = mset .store .LoadMsg (1 , & smv )
4718+ require_Error (t , err , ErrStoreMsgNotFound )
4719+ }
4720+
4721+ func TestJetStreamClusterStreamAckMsgR3SignalsRemovedMsg (t * testing.T ) {
4722+ c := createJetStreamClusterExplicit (t , "R3S" , 3 )
4723+ defer c .shutdown ()
4724+
4725+ nc , js := jsClientConnect (t , c .randomServer ())
4726+ defer nc .Close ()
4727+
4728+ _ , err := js .AddStream (& nats.StreamConfig {
4729+ Name : "TEST" ,
4730+ Subjects : []string {"foo" },
4731+ Retention : nats .WorkQueuePolicy ,
4732+ Replicas : 3 ,
4733+ })
4734+ require_NoError (t , err )
4735+
4736+ _ , err = js .AddConsumer ("TEST" , & nats.ConsumerConfig {
4737+ Durable : "CONSUMER" ,
4738+ Replicas : 3 ,
4739+ AckPolicy : nats .AckExplicitPolicy ,
4740+ })
4741+ require_NoError (t , err )
4742+
4743+ _ , err = js .Publish ("foo" , nil )
4744+ require_NoError (t , err )
4745+
4746+ getStreamAndConsumer := func (s * Server ) (* stream , * consumer , error ) {
4747+ t .Helper ()
4748+ acc , err := s .lookupAccount (globalAccountName )
4749+ if err != nil {
4750+ return nil , nil , err
4751+ }
4752+ mset , err := acc .lookupStream ("TEST" )
4753+ if err != nil {
4754+ return nil , nil , err
4755+ }
4756+ o := mset .lookupConsumer ("CONSUMER" )
4757+ if err != nil {
4758+ return nil , nil , err
4759+ }
4760+ return mset , o , nil
4761+ }
4762+
4763+ sl := c .consumerLeader (globalAccountName , "TEST" , "CONSUMER" )
4764+ sf := c .randomNonConsumerLeader (globalAccountName , "TEST" , "CONSUMER" )
4765+
4766+ msetL , ol , err := getStreamAndConsumer (sl )
4767+ require_NoError (t , err )
4768+ msetF , of , err := getStreamAndConsumer (sf )
4769+ require_NoError (t , err )
4770+
4771+ // Too high sequence, should register pre-ack and return true allowing for retries.
4772+ require_True (t , msetL .ackMsg (ol , 100 ))
4773+ require_True (t , msetF .ackMsg (of , 100 ))
4774+
4775+ // Let all servers ack the message.
4776+ var smv StoreMsg
4777+ for _ , s := range c .servers {
4778+ mset , _ , err := getStreamAndConsumer (s )
4779+ require_NoError (t , err )
4780+ require_True (t , mset .ackMsg (of , 1 ))
4781+
4782+ _ , err = mset .store .LoadMsg (1 , & smv )
4783+ require_Error (t , err , ErrStoreMsgNotFound )
4784+ }
4785+ }
0 commit comments