get.pme.sh/pnats@v0.0.0-20240304004023-26bb5a137ed0/server/jetstream_consumer_test.go (about)

     1  // Copyright 2022-2023 The NATS Authors
     2  // Licensed under the Apache License, Version 2.0 (the "License");
     3  // you may not use this file except in compliance with the License.
     4  // You may obtain a copy of the License at
     5  //
     6  // http://www.apache.org/licenses/LICENSE-2.0
     7  //
     8  // Unless required by applicable law or agreed to in writing, software
     9  // distributed under the License is distributed on an "AS IS" BASIS,
    10  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  //go:build !skip_js_tests
    15  // +build !skip_js_tests
    16  
    17  package server
    18  
    19  import (
    20  	"encoding/json"
    21  	"fmt"
    22  	"math/rand"
    23  	"sort"
    24  	"strings"
    25  	"sync"
    26  	"sync/atomic"
    27  	"testing"
    28  	"time"
    29  
    30  	"github.com/nats-io/nats.go"
    31  	"github.com/nats-io/nuid"
    32  )
    33  
    34  func TestJetStreamConsumerMultipleFiltersRemoveFilters(t *testing.T) {
    35  
    36  	s := RunBasicJetStreamServer(t)
    37  	defer s.Shutdown()
    38  
    39  	nc, js := jsClientConnect(t, s)
    40  	defer nc.Close()
    41  	acc := s.GlobalAccount()
    42  
    43  	mset, err := acc.addStream(&StreamConfig{
    44  		Name:      "TEST",
    45  		Retention: LimitsPolicy,
    46  		Subjects:  []string{"one", "two", "three"},
    47  		MaxAge:    time.Second * 90,
    48  	})
    49  	require_NoError(t, err)
    50  
    51  	_, err = mset.addConsumer(&ConsumerConfig{
    52  		Durable:        "consumer",
    53  		FilterSubjects: []string{"one", "two"},
    54  	})
    55  	require_NoError(t, err)
    56  
    57  	sendStreamMsg(t, nc, "one", "data")
    58  	sendStreamMsg(t, nc, "two", "data")
    59  	sendStreamMsg(t, nc, "three", "data")
    60  
    61  	consumer, err := js.PullSubscribe("", "consumer", nats.Bind("TEST", "consumer"))
    62  	require_NoError(t, err)
    63  
    64  	msgs, err := consumer.Fetch(1)
    65  	require_NoError(t, err)
    66  	require_True(t, len(msgs) == 1)
    67  
    68  	_, err = mset.addConsumer(&ConsumerConfig{
    69  		Durable:        "consumer",
    70  		FilterSubjects: []string{},
    71  	})
    72  	require_NoError(t, err)
    73  
    74  	msgs, err = consumer.Fetch(1)
    75  	require_NoError(t, err)
    76  	require_True(t, len(msgs) == 1)
    77  
    78  	msgs, err = consumer.Fetch(1)
    79  	require_NoError(t, err)
    80  	require_True(t, len(msgs) == 1)
    81  
    82  }
    83  
    84  func TestJetStreamConsumerMultipleFiltersRace(t *testing.T) {
    85  	s := RunBasicJetStreamServer(t)
    86  	defer s.Shutdown()
    87  
    88  	nc, js := jsClientConnect(t, s)
    89  	defer nc.Close()
    90  	acc := s.GlobalAccount()
    91  
    92  	mset, err := acc.addStream(&StreamConfig{
    93  		Name:      "TEST",
    94  		Retention: LimitsPolicy,
    95  		Subjects:  []string{"one", "two", "three", "four"},
    96  		MaxAge:    time.Second * 90,
    97  	})
    98  	require_NoError(t, err)
    99  
   100  	var seqs []uint64
   101  	var mu sync.Mutex
   102  
   103  	for i := 0; i < 10_000; i++ {
   104  		sendStreamMsg(t, nc, "one", "data")
   105  		sendStreamMsg(t, nc, "two", "data")
   106  		sendStreamMsg(t, nc, "three", "data")
   107  		sendStreamMsg(t, nc, "four", "data")
   108  	}
   109  
   110  	mset.addConsumer(&ConsumerConfig{
   111  		Durable:        "consumer",
   112  		FilterSubjects: []string{"one", "two", "three"},
   113  		AckPolicy:      AckExplicit,
   114  	})
   115  
   116  	done := make(chan struct{})
   117  	for i := 0; i < 10; i++ {
   118  		go func(t *testing.T) {
   119  
   120  			c, err := js.PullSubscribe("", "consumer", nats.Bind("TEST", "consumer"))
   121  			require_NoError(t, err)
   122  
   123  			for {
   124  				select {
   125  				case <-done:
   126  					return
   127  				default:
   128  				}
   129  				msgs, err := c.Fetch(10)
   130  				// We don't want to stop before at expected number of messages, as we want
   131  				// to also test against getting to many messages.
   132  				// Because of that, we ignore timeout and connection closed errors.
   133  				if err != nil && err != nats.ErrTimeout && err != nats.ErrConnectionClosed {
   134  					t.Errorf("error while fetching messages: %v", err)
   135  				}
   136  
   137  				for _, msg := range msgs {
   138  					info, err := msg.Metadata()
   139  					require_NoError(t, err)
   140  					mu.Lock()
   141  					seqs = append(seqs, info.Sequence.Consumer)
   142  					mu.Unlock()
   143  					msg.Ack()
   144  				}
   145  			}
   146  		}(t)
   147  	}
   148  
   149  	checkFor(t, time.Second*30, time.Second*1, func() error {
   150  		mu.Lock()
   151  		defer mu.Unlock()
   152  		if len(seqs) != 30_000 {
   153  			return fmt.Errorf("found %d messages instead of %d", len(seqs), 30_000)
   154  		}
   155  		sort.Slice(seqs, func(i, j int) bool {
   156  			return seqs[i] < seqs[j]
   157  		})
   158  		for i := 1; i < len(seqs); i++ {
   159  			if seqs[i] != seqs[i-1]+1 {
   160  				fmt.Printf("seqs: %+v\n", seqs)
   161  				return fmt.Errorf("sequence mismatch at %v", i)
   162  			}
   163  		}
   164  
   165  		return nil
   166  	})
   167  
   168  	close(done)
   169  
   170  }
   171  
   172  func TestJetStreamConsumerMultipleConsumersSingleFilter(t *testing.T) {
   173  	s := RunBasicJetStreamServer(t)
   174  	defer s.Shutdown()
   175  
   176  	nc, js := jsClientConnect(t, s)
   177  	defer nc.Close()
   178  	acc := s.GlobalAccount()
   179  
   180  	// Setup few subjects with varying messages count.
   181  	subjects := []struct {
   182  		subject  string
   183  		messages int
   184  		wc       bool
   185  	}{
   186  		{subject: "one", messages: 5000},
   187  		{subject: "two", messages: 7500},
   188  		{subject: "three", messages: 2500},
   189  		{subject: "four", messages: 1000},
   190  		{subject: "five.>", messages: 3000, wc: true},
   191  	}
   192  
   193  	totalMsgs := 0
   194  	for _, subject := range subjects {
   195  		totalMsgs += subject.messages
   196  	}
   197  
   198  	// Setup consumers, filtering some of the messages from the stream.
   199  	consumers := []*struct {
   200  		name         string
   201  		subjects     []string
   202  		expectedMsgs int
   203  		delivered    atomic.Int32
   204  	}{
   205  		{name: "C1", subjects: []string{"one"}, expectedMsgs: 5000},
   206  		{name: "C2", subjects: []string{"two"}, expectedMsgs: 7500},
   207  		{name: "C3", subjects: []string{"one"}, expectedMsgs: 5000},
   208  		{name: "C4", subjects: []string{"one"}, expectedMsgs: 5000},
   209  	}
   210  
   211  	mset, err := acc.addStream(&StreamConfig{
   212  		Name:      "TEST",
   213  		Retention: LimitsPolicy,
   214  		Subjects:  []string{"one", "two", "three", "four", "five.>"},
   215  		MaxAge:    time.Second * 90,
   216  	})
   217  	require_NoError(t, err)
   218  
   219  	for c, consumer := range consumers {
   220  		_, err := mset.addConsumer(&ConsumerConfig{
   221  			Durable:        consumer.name,
   222  			FilterSubjects: consumer.subjects,
   223  			AckPolicy:      AckExplicit,
   224  			DeliverPolicy:  DeliverAll,
   225  			AckWait:        time.Second * 30,
   226  			DeliverSubject: nc.NewInbox(),
   227  		})
   228  		require_NoError(t, err)
   229  		go func(c int, name string) {
   230  			_, err = js.Subscribe("", func(m *nats.Msg) {
   231  				require_NoError(t, m.Ack())
   232  				require_NoError(t, err)
   233  				consumers[c].delivered.Add(1)
   234  
   235  			}, nats.Bind("TEST", name))
   236  			require_NoError(t, err)
   237  		}(c, consumer.name)
   238  	}
   239  
   240  	// Publish with random intervals, while consumers are active.
   241  	var wg sync.WaitGroup
   242  	for _, subject := range subjects {
   243  		wg.Add(subject.messages)
   244  		go func(subject string, messages int, wc bool) {
   245  			nc, js := jsClientConnect(t, s)
   246  			defer nc.Close()
   247  			time.Sleep(time.Duration(rand.Int63n(1000)+1) * time.Millisecond)
   248  			for i := 0; i < messages; i++ {
   249  				time.Sleep(time.Duration(rand.Int63n(1000)+1) * time.Microsecond)
   250  				// If subject has wildcard, add random last subject token.
   251  				pubSubject := subject
   252  				if wc {
   253  					pubSubject = fmt.Sprintf("%v.%v", subject, rand.Int63n(10))
   254  				}
   255  				_, err := js.PublishAsync(pubSubject, []byte("data"))
   256  				require_NoError(t, err)
   257  				wg.Done()
   258  			}
   259  		}(subject.subject, subject.messages, subject.wc)
   260  	}
   261  	wg.Wait()
   262  
   263  	checkFor(t, time.Second*10, time.Millisecond*500, func() error {
   264  		for _, consumer := range consumers {
   265  			info, err := js.ConsumerInfo("TEST", consumer.name)
   266  			require_NoError(t, err)
   267  			if info.Delivered.Consumer != uint64(consumer.expectedMsgs) {
   268  				return fmt.Errorf("%v:expected consumer delivered seq %v, got %v. actually delivered: %v", consumer.name, consumer.expectedMsgs, info.Delivered.Consumer, consumer.delivered.Load())
   269  			}
   270  			if info.AckFloor.Consumer != uint64(consumer.expectedMsgs) {
   271  				return fmt.Errorf("%v: expected consumer ack floor %v, got %v", consumer.name, totalMsgs, info.AckFloor.Consumer)
   272  			}
   273  			if consumer.delivered.Load() != int32(consumer.expectedMsgs) {
   274  
   275  				return fmt.Errorf("%v: expected %v, got %v", consumer.name, consumer.expectedMsgs, consumer.delivered.Load())
   276  			}
   277  		}
   278  		return nil
   279  	})
   280  
   281  }
   282  
   283  func TestJetStreamConsumerMultipleConsumersMultipleFilters(t *testing.T) {
   284  	s := RunBasicJetStreamServer(t)
   285  	defer s.Shutdown()
   286  
   287  	nc, js := jsClientConnect(t, s)
   288  	defer nc.Close()
   289  	acc := s.GlobalAccount()
   290  
   291  	// Setup few subjects with varying messages count.
   292  	subjects := []struct {
   293  		subject  string
   294  		messages int
   295  		wc       bool
   296  	}{
   297  		{subject: "one", messages: 50},
   298  		{subject: "two", messages: 75},
   299  		{subject: "three", messages: 250},
   300  		{subject: "four", messages: 10},
   301  		{subject: "five.>", messages: 300, wc: true},
   302  	}
   303  
   304  	totalMsgs := 0
   305  	for _, subject := range subjects {
   306  		totalMsgs += subject.messages
   307  	}
   308  
   309  	// Setup consumers, filtering some of the messages from the stream.
   310  	consumers := []*struct {
   311  		name         string
   312  		subjects     []string
   313  		expectedMsgs int
   314  		delivered    atomic.Int32
   315  	}{
   316  		{name: "C1", subjects: []string{"one", "two"}, expectedMsgs: 125},
   317  		{name: "C2", subjects: []string{"two", "three"}, expectedMsgs: 325},
   318  		{name: "C3", subjects: []string{"one", "three"}, expectedMsgs: 300},
   319  		{name: "C4", subjects: []string{"one", "five.>"}, expectedMsgs: 350},
   320  	}
   321  
   322  	mset, err := acc.addStream(&StreamConfig{
   323  		Name:      "TEST",
   324  		Retention: LimitsPolicy,
   325  		Subjects:  []string{"one", "two", "three", "four", "five.>"},
   326  		MaxAge:    time.Second * 90,
   327  	})
   328  	require_NoError(t, err)
   329  
   330  	for c, consumer := range consumers {
   331  		_, err := mset.addConsumer(&ConsumerConfig{
   332  			Durable:        consumer.name,
   333  			FilterSubjects: consumer.subjects,
   334  			AckPolicy:      AckExplicit,
   335  			DeliverPolicy:  DeliverAll,
   336  			AckWait:        time.Second * 30,
   337  			DeliverSubject: nc.NewInbox(),
   338  		})
   339  		require_NoError(t, err)
   340  		go func(c int, name string) {
   341  			_, err = js.Subscribe("", func(m *nats.Msg) {
   342  				require_NoError(t, m.Ack())
   343  				require_NoError(t, err)
   344  				consumers[c].delivered.Add(1)
   345  
   346  			}, nats.Bind("TEST", name))
   347  			require_NoError(t, err)
   348  		}(c, consumer.name)
   349  	}
   350  
   351  	// Publish with random intervals, while consumers are active.
   352  	var wg sync.WaitGroup
   353  	for _, subject := range subjects {
   354  		wg.Add(subject.messages)
   355  		go func(subject string, messages int, wc bool) {
   356  			nc, js := jsClientConnect(t, s)
   357  			defer nc.Close()
   358  			time.Sleep(time.Duration(rand.Int63n(1000)+1) * time.Millisecond)
   359  			for i := 0; i < messages; i++ {
   360  				time.Sleep(time.Duration(rand.Int63n(1000)+1) * time.Microsecond)
   361  				// If subject has wildcard, add random last subject token.
   362  				pubSubject := subject
   363  				if wc {
   364  					pubSubject = fmt.Sprintf("%v.%v", subject, rand.Int63n(10))
   365  				}
   366  				ack, err := js.PublishAsync(pubSubject, []byte("data"))
   367  				require_NoError(t, err)
   368  				go func() {
   369  					ack.Ok()
   370  					wg.Done()
   371  				}()
   372  			}
   373  		}(subject.subject, subject.messages, subject.wc)
   374  	}
   375  	done := make(chan struct{})
   376  	go func() {
   377  		wg.Wait()
   378  		close(done)
   379  	}()
   380  
   381  	select {
   382  	case <-time.After(time.Second * 15):
   383  		t.Fatalf("Timed out waiting for acks")
   384  	case <-done:
   385  	}
   386  	wg.Wait()
   387  
   388  	checkFor(t, time.Second*15, time.Second*1, func() error {
   389  		for _, consumer := range consumers {
   390  			info, err := js.ConsumerInfo("TEST", consumer.name)
   391  			require_NoError(t, err)
   392  			if info.Delivered.Consumer != uint64(consumer.expectedMsgs) {
   393  				return fmt.Errorf("%v:expected consumer delivered seq %v, got %v. actually delivered: %v", consumer.name, consumer.expectedMsgs, info.Delivered.Consumer, consumer.delivered.Load())
   394  			}
   395  			if info.AckFloor.Consumer != uint64(consumer.expectedMsgs) {
   396  				return fmt.Errorf("%v: expected consumer ack floor %v, got %v", consumer.name, totalMsgs, info.AckFloor.Consumer)
   397  			}
   398  			if consumer.delivered.Load() != int32(consumer.expectedMsgs) {
   399  
   400  				return fmt.Errorf("%v: expected %v, got %v", consumer.name, consumer.expectedMsgs, consumer.delivered.Load())
   401  			}
   402  		}
   403  		return nil
   404  	})
   405  
   406  }
   407  
   408  func TestJetStreamConsumerMultipleFiltersSequence(t *testing.T) {
   409  	s := RunBasicJetStreamServer(t)
   410  	defer s.Shutdown()
   411  
   412  	nc, js := jsClientConnect(t, s)
   413  	defer nc.Close()
   414  	acc := s.GlobalAccount()
   415  
   416  	mset, err := acc.addStream(&StreamConfig{
   417  		Name:      "TEST",
   418  		Retention: LimitsPolicy,
   419  		Subjects:  []string{"one", "two", "three", "four", "five.>"},
   420  		MaxAge:    time.Second * 90,
   421  	})
   422  	require_NoError(t, err)
   423  
   424  	_, err = mset.addConsumer(&ConsumerConfig{
   425  		Durable:        "DUR",
   426  		FilterSubjects: []string{"one", "two"},
   427  		AckPolicy:      AckExplicit,
   428  		DeliverPolicy:  DeliverAll,
   429  		AckWait:        time.Second * 30,
   430  		DeliverSubject: nc.NewInbox(),
   431  	})
   432  	require_NoError(t, err)
   433  
   434  	for i := 0; i < 20; i++ {
   435  		sendStreamMsg(t, nc, "one", fmt.Sprintf("%d", i))
   436  	}
   437  	for i := 20; i < 40; i++ {
   438  		sendStreamMsg(t, nc, "two", fmt.Sprintf("%d", i))
   439  	}
   440  	for i := 40; i < 60; i++ {
   441  		sendStreamMsg(t, nc, "one", fmt.Sprintf("%d", i))
   442  	}
   443  
   444  	sub, err := js.SubscribeSync("", nats.Bind("TEST", "DUR"))
   445  	require_NoError(t, err)
   446  
   447  	for i := 0; i < 60; i++ {
   448  		msg, err := sub.NextMsg(time.Second * 1)
   449  		require_NoError(t, err)
   450  		require_True(t, string(msg.Data) == fmt.Sprintf("%d", i))
   451  	}
   452  }
   453  
   454  func TestJetStreamConsumerActions(t *testing.T) {
   455  	s := RunBasicJetStreamServer(t)
   456  	defer s.Shutdown()
   457  
   458  	nc, _ := jsClientConnect(t, s)
   459  	defer nc.Close()
   460  	acc := s.GlobalAccount()
   461  
   462  	mset, err := acc.addStream(&StreamConfig{
   463  		Name:      "TEST",
   464  		Retention: LimitsPolicy,
   465  		Subjects:  []string{"one", "two", "three", "four", "five.>"},
   466  		MaxAge:    time.Second * 90,
   467  	})
   468  	require_NoError(t, err)
   469  
   470  	// Create Consumer. No consumers existed before, so should be fine.
   471  	_, err = mset.addConsumerWithAction(&ConsumerConfig{
   472  		Durable:        "DUR",
   473  		FilterSubjects: []string{"one", "two"},
   474  		AckPolicy:      AckExplicit,
   475  		DeliverPolicy:  DeliverAll,
   476  		AckWait:        time.Second * 30,
   477  	}, ActionCreate)
   478  	require_NoError(t, err)
   479  	// Create consumer again. Should be ok if action is CREATE but config is exactly the same.
   480  	_, err = mset.addConsumerWithAction(&ConsumerConfig{
   481  		Durable:        "DUR",
   482  		FilterSubjects: []string{"one", "two"},
   483  		AckPolicy:      AckExplicit,
   484  		DeliverPolicy:  DeliverAll,
   485  		AckWait:        time.Second * 30,
   486  	}, ActionCreate)
   487  	require_NoError(t, err)
   488  	// Create consumer again. Should error if action is CREATE.
   489  	_, err = mset.addConsumerWithAction(&ConsumerConfig{
   490  		Durable:        "DUR",
   491  		FilterSubjects: []string{"one"},
   492  		AckPolicy:      AckExplicit,
   493  		DeliverPolicy:  DeliverAll,
   494  		AckWait:        time.Second * 30,
   495  	}, ActionCreate)
   496  	require_Error(t, err)
   497  
   498  	// Update existing consumer. Should be fine, as consumer exists.
   499  	_, err = mset.addConsumerWithAction(&ConsumerConfig{
   500  		Durable:        "DUR",
   501  		FilterSubjects: []string{"one"},
   502  		AckPolicy:      AckExplicit,
   503  		DeliverPolicy:  DeliverAll,
   504  		AckWait:        time.Second * 30,
   505  	}, ActionUpdate)
   506  	require_NoError(t, err)
   507  
   508  	// Update consumer. Should error, as this consumer does not exist.
   509  	_, err = mset.addConsumerWithAction(&ConsumerConfig{
   510  		Durable:        "NEW",
   511  		FilterSubjects: []string{"one"},
   512  		AckPolicy:      AckExplicit,
   513  		DeliverPolicy:  DeliverAll,
   514  		AckWait:        time.Second * 30,
   515  	}, ActionUpdate)
   516  	require_Error(t, err)
   517  
   518  	// Create new ephemeral. Should be fine as the consumer doesn't exist already
   519  	_, err = mset.addConsumerWithAction(&ConsumerConfig{
   520  		Name:           "EPH",
   521  		FilterSubjects: []string{"one"},
   522  		AckPolicy:      AckExplicit,
   523  		DeliverPolicy:  DeliverAll,
   524  		AckWait:        time.Second * 30,
   525  	}, ActionCreate)
   526  	require_NoError(t, err)
   527  
   528  	// Trying to create it again right away. Should error as it already exists (and hasn't been cleaned up yet)
   529  	_, err = mset.addConsumerWithAction(&ConsumerConfig{
   530  		Name:           "EPH",
   531  		FilterSubjects: []string{"one"},
   532  		AckPolicy:      AckExplicit,
   533  		DeliverPolicy:  DeliverAll,
   534  		AckWait:        time.Second * 30,
   535  	}, ActionCreate)
   536  	require_Error(t, err)
   537  }
   538  
   539  func TestJetStreamConsumerActionsOnWorkQueuePolicyStream(t *testing.T) {
   540  	s := RunBasicJetStreamServer(t)
   541  	defer s.Shutdown()
   542  
   543  	nc, _ := jsClientConnect(t, s)
   544  	defer nc.Close()
   545  	acc := s.GlobalAccount()
   546  
   547  	mset, err := acc.addStream(&StreamConfig{
   548  		Name:      "TEST",
   549  		Retention: WorkQueuePolicy,
   550  		Subjects:  []string{"one", "two", "three", "four", "five.>"},
   551  	})
   552  	require_NoError(t, err)
   553  
   554  	_, err = mset.addConsumerWithAction(&ConsumerConfig{
   555  		Durable:        "C1",
   556  		FilterSubjects: []string{"one", "two"},
   557  		AckPolicy:      AckExplicit,
   558  	}, ActionCreate)
   559  	require_NoError(t, err)
   560  
   561  	_, err = mset.addConsumerWithAction(&ConsumerConfig{
   562  		Durable:        "C2",
   563  		FilterSubjects: []string{"three", "four"},
   564  		AckPolicy:      AckExplicit,
   565  	}, ActionCreate)
   566  	require_NoError(t, err)
   567  
   568  	_, err = mset.addConsumerWithAction(&ConsumerConfig{
   569  		Durable:        "C3",
   570  		FilterSubjects: []string{"five.*"},
   571  		AckPolicy:      AckExplicit,
   572  	}, ActionCreate)
   573  	require_NoError(t, err)
   574  
   575  	// Updating a consumer by removing a previous subject filter.
   576  	_, err = mset.addConsumerWithAction(&ConsumerConfig{
   577  		Durable:        "C1",
   578  		FilterSubjects: []string{"one"}, // Remove a subject.
   579  		AckPolicy:      AckExplicit,
   580  	}, ActionUpdate)
   581  	require_NoError(t, err)
   582  
   583  	// Updating a consumer without overlapping subjects.
   584  	_, err = mset.addConsumerWithAction(&ConsumerConfig{
   585  		Durable:        "C2",
   586  		FilterSubjects: []string{"three", "four", "two"}, // Add previously removed subject.
   587  		AckPolicy:      AckExplicit,
   588  	}, ActionUpdate)
   589  	require_NoError(t, err)
   590  
   591  	// Creating a consumer with overlapping subjects should return an error.
   592  	_, err = mset.addConsumerWithAction(&ConsumerConfig{
   593  		Durable:        "C4",
   594  		FilterSubjects: []string{"one", "two", "three", "four"},
   595  		AckPolicy:      AckExplicit,
   596  	}, ActionCreate)
   597  	require_Error(t, err)
   598  	if !IsNatsErr(err, JSConsumerWQConsumerNotUniqueErr) {
   599  		t.Errorf("want error %q, got %q", ApiErrors[JSConsumerWQConsumerNotUniqueErr], err)
   600  	}
   601  
   602  	// Updating a consumer with overlapping subjects should return an error.
   603  	_, err = mset.addConsumerWithAction(&ConsumerConfig{
   604  		Durable:        "C3",
   605  		FilterSubjects: []string{"one", "two", "three", "four"},
   606  		AckPolicy:      AckExplicit,
   607  	}, ActionUpdate)
   608  	require_Error(t, err)
   609  	if !IsNatsErr(err, JSConsumerWQConsumerNotUniqueErr) {
   610  		t.Errorf("want error %q, got %q", ApiErrors[JSConsumerWQConsumerNotUniqueErr], err)
   611  	}
   612  }
   613  
   614  func TestJetStreamConsumerActionsViaAPI(t *testing.T) {
   615  
   616  	s := RunBasicJetStreamServer(t)
   617  	defer s.Shutdown()
   618  
   619  	nc, _ := jsClientConnect(t, s)
   620  	defer nc.Close()
   621  	acc := s.GlobalAccount()
   622  
   623  	_, err := acc.addStream(&StreamConfig{
   624  		Name:      "TEST",
   625  		Retention: LimitsPolicy,
   626  		Subjects:  []string{"one"},
   627  		MaxAge:    time.Second * 90,
   628  	})
   629  	require_NoError(t, err)
   630  
   631  	// Update non-existing consumer, which should fail.
   632  	request, err := json.Marshal(&CreateConsumerRequest{
   633  		Action: ActionUpdate,
   634  		Config: ConsumerConfig{
   635  			Durable: "hello",
   636  		},
   637  		Stream: "TEST",
   638  	})
   639  	require_NoError(t, err)
   640  
   641  	resp, err := nc.Request("$JS.API.CONSUMER.DURABLE.CREATE.TEST.hello", []byte(request), time.Second*6)
   642  	require_NoError(t, err)
   643  	var ccResp JSApiConsumerCreateResponse
   644  	err = json.Unmarshal(resp.Data, &ccResp)
   645  	require_NoError(t, err)
   646  	require_Error(t, ccResp.Error)
   647  
   648  	// create non existing consumer - which should be fine.
   649  	ccResp.Error = nil
   650  	request, err = json.Marshal(&CreateConsumerRequest{
   651  		Action: ActionCreate,
   652  		Config: ConsumerConfig{
   653  			Durable: "hello",
   654  		},
   655  		Stream: "TEST",
   656  	})
   657  	require_NoError(t, err)
   658  
   659  	resp, err = nc.Request("$JS.API.CONSUMER.DURABLE.CREATE.TEST.hello", []byte(request), time.Second*6)
   660  	require_NoError(t, err)
   661  	err = json.Unmarshal(resp.Data, &ccResp)
   662  	require_NoError(t, err)
   663  	if ccResp.Error != nil {
   664  		t.Fatalf("expected nil, got %v", ccResp.Error)
   665  	}
   666  
   667  	// re-create existing consumer - which should be an error.
   668  	ccResp.Error = nil
   669  	request, err = json.Marshal(&CreateConsumerRequest{
   670  		Action: ActionCreate,
   671  		Config: ConsumerConfig{
   672  			Durable:       "hello",
   673  			FilterSubject: "one",
   674  		},
   675  		Stream: "TEST",
   676  	})
   677  	require_NoError(t, err)
   678  	resp, err = nc.Request("$JS.API.CONSUMER.DURABLE.CREATE.TEST.hello", []byte(request), time.Second*6)
   679  	require_NoError(t, err)
   680  	err = json.Unmarshal(resp.Data, &ccResp)
   681  	require_NoError(t, err)
   682  	if ccResp.Error == nil {
   683  		t.Fatalf("expected err, got nil")
   684  	}
   685  
   686  	// create a named ephemeral consumer
   687  	ccResp.Error = nil
   688  	request, err = json.Marshal(&CreateConsumerRequest{
   689  		Action: ActionCreate,
   690  		Config: ConsumerConfig{
   691  			Name:          "ephemeral",
   692  			FilterSubject: "one",
   693  		},
   694  		Stream: "TEST",
   695  	})
   696  	require_NoError(t, err)
   697  	resp, err = nc.Request("$JS.API.CONSUMER.CREATE.TEST.ephemeral", []byte(request), time.Second*6)
   698  	require_NoError(t, err)
   699  	err = json.Unmarshal(resp.Data, &ccResp)
   700  	require_NoError(t, err)
   701  
   702  	// re-create existing consumer - which should be an error.
   703  	ccResp.Error = nil
   704  	request, err = json.Marshal(&CreateConsumerRequest{
   705  		Action: ActionCreate,
   706  		Config: ConsumerConfig{
   707  			Name:          "ephemeral",
   708  			FilterSubject: "one",
   709  		},
   710  		Stream: "TEST",
   711  	})
   712  	require_NoError(t, err)
   713  	resp, err = nc.Request("$JS.API.CONSUMER.CREATE.TEST.ephemeral", []byte(request), time.Second*6)
   714  	require_NoError(t, err)
   715  	err = json.Unmarshal(resp.Data, &ccResp)
   716  	require_NoError(t, err)
   717  	if ccResp.Error == nil {
   718  		t.Fatalf("expected err, got nil")
   719  	}
   720  }
   721  
   722  func TestJetStreamConsumerActionsUnmarshal(t *testing.T) {
   723  	tests := []struct {
   724  		name      string
   725  		given     []byte
   726  		expected  ConsumerAction
   727  		expectErr bool
   728  	}{
   729  		{name: "action create", given: []byte(`{"action": "create"}`), expected: ActionCreate},
   730  		{name: "action update", given: []byte(`{"action": "update"}`), expected: ActionUpdate},
   731  		{name: "no action", given: []byte("{}"), expected: ActionCreateOrUpdate},
   732  		{name: "unknown", given: []byte(`{"action": "unknown"}`), expected: ActionCreateOrUpdate, expectErr: true},
   733  	}
   734  
   735  	for _, test := range tests {
   736  		t.Run(test.name, func(t *testing.T) {
   737  
   738  			var request CreateConsumerRequest
   739  			err := json.Unmarshal(test.given, &request)
   740  			fmt.Printf("given: %v, expected: %v\n", test.expectErr, err)
   741  			if !test.expectErr {
   742  				require_NoError(t, err)
   743  			} else {
   744  				require_Error(t, err)
   745  			}
   746  			require_True(t, test.expected == request.Action)
   747  		})
   748  	}
   749  }
   750  
   751  func TestJetStreamConsumerMultipleFiltersLastPerSubject(t *testing.T) {
   752  	c := createJetStreamClusterExplicit(t, "R3S", 3)
   753  	defer c.shutdown()
   754  
   755  	nc, js := jsClientConnect(t, c.randomServer())
   756  	defer nc.Close()
   757  
   758  	_, error := js.AddStream(&nats.StreamConfig{
   759  		Name:     "TEST",
   760  		Subjects: []string{"one", "two"},
   761  		Replicas: 3,
   762  	})
   763  	require_NoError(t, error)
   764  
   765  	sendStreamMsg(t, nc, "one", "1")
   766  	sendStreamMsg(t, nc, "one", "2")
   767  	sendStreamMsg(t, nc, "one", "3")
   768  	sendStreamMsg(t, nc, "two", "1")
   769  	sendStreamMsg(t, nc, "two", "2")
   770  	sendStreamMsg(t, nc, "two", "3")
   771  
   772  	_, err := js.AddConsumer("TEST", &nats.ConsumerConfig{
   773  		Name:           "C",
   774  		FilterSubjects: []string{"one", "two"},
   775  		DeliverPolicy:  nats.DeliverLastPerSubjectPolicy,
   776  		Replicas:       3,
   777  		DeliverSubject: "deliver",
   778  	})
   779  	require_NoError(t, err)
   780  
   781  	consumer, err := js.SubscribeSync("", nats.Bind("TEST", "C"))
   782  	require_NoError(t, err)
   783  
   784  	// expect last message for subject "one"
   785  	msg, err := consumer.NextMsg(time.Second)
   786  	require_NoError(t, err)
   787  	require_Equal(t, "3", string(msg.Data))
   788  	require_Equal(t, "one", msg.Subject)
   789  
   790  	// expect last message for subject "two"
   791  	msg, err = consumer.NextMsg(time.Second)
   792  	require_NoError(t, err)
   793  	require_Equal(t, "3", string(msg.Data))
   794  	require_Equal(t, "two", msg.Subject)
   795  
   796  }
   797  
   798  func consumerWithFilterSubjects(filterSubjects []string) *consumer {
   799  	c := consumer{}
   800  	for _, filter := range filterSubjects {
   801  		sub := &subjectFilter{
   802  			subject:          filter,
   803  			hasWildcard:      subjectHasWildcard(filter),
   804  			tokenizedSubject: tokenizeSubjectIntoSlice(nil, filter),
   805  		}
   806  		c.subjf = append(c.subjf, sub)
   807  	}
   808  
   809  	return &c
   810  }
   811  
   812  func filterSubjects(n int) []string {
   813  	fs := make([]string, 0, n)
   814  	for {
   815  		literals := []string{"foo", "bar", nuid.Next(), "xyz", "abcdef"}
   816  		fs = append(fs, strings.Join(literals, "."))
   817  		if len(fs) == n {
   818  			return fs
   819  		}
   820  		// Create more filterSubjects by going through the literals and replacing one with the '*' wildcard.
   821  		l := len(literals)
   822  		for i := 0; i < l; i++ {
   823  			e := make([]string, l)
   824  			for j := 0; j < l; j++ {
   825  				if j == i {
   826  					e[j] = "*"
   827  				} else {
   828  					e[j] = literals[j]
   829  				}
   830  			}
   831  			fs = append(fs, strings.Join(e, "."))
   832  			if len(fs) == n {
   833  				return fs
   834  			}
   835  		}
   836  	}
   837  }
   838  
   839  func TestJetStreamConsumerIsFilteredMatch(t *testing.T) {
   840  	for _, test := range []struct {
   841  		name           string
   842  		filterSubjects []string
   843  		subject        string
   844  		result         bool
   845  	}{
   846  		{"no filter", []string{}, "foo.bar", true},
   847  		{"literal match", []string{"foo.baz", "foo.bar"}, "foo.bar", true},
   848  		{"literal mismatch", []string{"foo.baz", "foo.bar"}, "foo.ban", false},
   849  		{"wildcard > match", []string{"bar.>", "foo.>"}, "foo.bar", true},
   850  		{"wildcard > match", []string{"bar.>", "foo.>"}, "bar.foo", true},
   851  		{"wildcard > mismatch", []string{"bar.>", "foo.>"}, "baz.foo", false},
   852  		{"wildcard * match", []string{"bar.*", "foo.*"}, "foo.bar", true},
   853  		{"wildcard * match", []string{"bar.*", "foo.*"}, "bar.foo", true},
   854  		{"wildcard * mismatch", []string{"bar.*", "foo.*"}, "baz.foo", false},
   855  		{"wildcard * match", []string{"foo.*.x", "foo.*.y"}, "foo.bar.x", true},
   856  		{"wildcard * match", []string{"foo.*.x", "foo.*.y", "foo.*.z"}, "foo.bar.z", true},
   857  		{"many mismatch", filterSubjects(100), "foo.bar.do.not.match.any.filter.subject", false},
   858  		{"many match", filterSubjects(100), "foo.bar.12345.xyz.abcdef", true}, // will be matched by "foo.bar.*.xyz.abcdef"
   859  	} {
   860  		test := test
   861  
   862  		t.Run(test.name, func(t *testing.T) {
   863  			t.Parallel()
   864  
   865  			c := consumerWithFilterSubjects(test.filterSubjects)
   866  			if res := c.isFilteredMatch(test.subject); res != test.result {
   867  				t.Fatalf("Subject %q filtered match of %v, should be %v, got %v",
   868  					test.subject, test.filterSubjects, test.result, res)
   869  			}
   870  		})
   871  	}
   872  }
   873  
   874  func TestJetStreamConsumerIsEqualOrSubsetMatch(t *testing.T) {
   875  	for _, test := range []struct {
   876  		name           string
   877  		filterSubjects []string
   878  		subject        string
   879  		result         bool
   880  	}{
   881  		{"no filter", []string{}, "foo.bar", false},
   882  		{"literal match", []string{"foo.baz", "foo.bar"}, "foo.bar", true},
   883  		{"literal mismatch", []string{"foo.baz", "foo.bar"}, "foo.ban", false},
   884  		{"literal match", []string{"bar.>", "foo.>"}, "foo.>", true},
   885  		{"subset match", []string{"bar.foo.>", "foo.bar.>"}, "bar.>", true},
   886  		{"subset mismatch", []string{"bar.>", "foo.>"}, "baz.foo.>", false},
   887  		{"literal match", filterSubjects(100), "foo.bar.*.xyz.abcdef", true},
   888  		{"subset match", filterSubjects(100), "foo.bar.>", true},
   889  	} {
   890  		test := test
   891  
   892  		t.Run(test.name, func(t *testing.T) {
   893  			t.Parallel()
   894  
   895  			c := consumerWithFilterSubjects(test.filterSubjects)
   896  			if res := c.isEqualOrSubsetMatch(test.subject); res != test.result {
   897  				t.Fatalf("Subject %q subset match of %v, should be %v, got %v",
   898  					test.subject, test.filterSubjects, test.result, res)
   899  			}
   900  		})
   901  	}
   902  }
   903  
   904  func Benchmark____JetStreamConsumerIsFilteredMatch(b *testing.B) {
   905  	subject := "foo.bar.do.not.match.any.filter.subject"
   906  	for n := 1; n <= 1024; n *= 2 {
   907  		name := fmt.Sprintf("%d filter subjects", int(n))
   908  		c := consumerWithFilterSubjects(filterSubjects(int(n)))
   909  		b.Run(name, func(b *testing.B) {
   910  			c.isFilteredMatch(subject)
   911  		})
   912  	}
   913  }