github.com/nats-io/nats-server/v2@v2.11.0-preview.2/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 "strconv" 25 "strings" 26 "sync" 27 "sync/atomic" 28 "testing" 29 "time" 30 31 "github.com/nats-io/nats.go" 32 "github.com/nats-io/nuid" 33 ) 34 35 func TestJetStreamConsumerMultipleFiltersRemoveFilters(t *testing.T) { 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 func TestJetStreamConsumerMultipleFiltersRace(t *testing.T) { 84 s := RunBasicJetStreamServer(t) 85 defer s.Shutdown() 86 87 nc, js := jsClientConnect(t, s) 88 defer nc.Close() 89 acc := s.GlobalAccount() 90 91 mset, err := acc.addStream(&StreamConfig{ 92 Name: "TEST", 93 Retention: LimitsPolicy, 94 Subjects: []string{"one", "two", "three", "four"}, 95 MaxAge: time.Second * 90, 96 }) 97 require_NoError(t, err) 98 99 var seqs []uint64 100 var mu sync.Mutex 101 102 total := 10_000 103 var wg sync.WaitGroup 104 105 send := func(subj string) { 106 defer wg.Done() 107 for i := 0; i < total; i++ { 108 sendStreamMsg(t, nc, subj, "data") 109 } 110 } 111 wg.Add(4) 112 go send("one") 113 go send("two") 114 go send("three") 115 go send("four") 116 wg.Wait() 117 118 mset.addConsumer(&ConsumerConfig{ 119 Durable: "consumer", 120 FilterSubjects: []string{"one", "two", "three"}, 121 AckPolicy: AckExplicit, 122 }) 123 124 done := make(chan struct{}) 125 wg.Add(10) 126 for i := 0; i < 10; i++ { 127 go func(t *testing.T) { 128 defer wg.Done() 129 130 c, err := js.PullSubscribe(_EMPTY_, "consumer", nats.Bind("TEST", "consumer")) 131 require_NoError(t, err) 132 133 for { 134 select { 135 case <-done: 136 return 137 default: 138 } 139 msgs, err := c.Fetch(10, nats.MaxWait(2*time.Second)) 140 // We don't want to stop before at expected number of messages, as we want 141 // to also test against getting to many messages. 142 // Because of that, we ignore timeout and connection closed errors. 143 if err != nil && err != nats.ErrTimeout && err != nats.ErrConnectionClosed { 144 t.Errorf("error while fetching messages: %v", err) 145 } 146 147 for _, msg := range msgs { 148 info, err := msg.Metadata() 149 require_NoError(t, err) 150 mu.Lock() 151 seqs = append(seqs, info.Sequence.Consumer) 152 mu.Unlock() 153 msg.Ack() 154 } 155 } 156 }(t) 157 } 158 159 checkFor(t, 30*time.Second, 100*time.Millisecond, func() error { 160 mu.Lock() 161 defer mu.Unlock() 162 if len(seqs) != 3*total { 163 return fmt.Errorf("found %d messages instead of %d", len(seqs), 3*total) 164 } 165 sort.Slice(seqs, func(i, j int) bool { 166 return seqs[i] < seqs[j] 167 }) 168 for i := 1; i < len(seqs); i++ { 169 if seqs[i] != seqs[i-1]+1 { 170 fmt.Printf("seqs: %+v\n", seqs) 171 return fmt.Errorf("sequence mismatch at %v", i) 172 } 173 } 174 return nil 175 }) 176 close(done) 177 wg.Wait() 178 } 179 180 func TestJetStreamConsumerMultipleConsumersSingleFilter(t *testing.T) { 181 s := RunBasicJetStreamServer(t) 182 defer s.Shutdown() 183 184 nc, js := jsClientConnect(t, s) 185 defer nc.Close() 186 acc := s.GlobalAccount() 187 188 // Setup few subjects with varying messages count. 189 subjects := []struct { 190 subject string 191 messages int 192 wc bool 193 }{ 194 {subject: "one", messages: 5000}, 195 {subject: "two", messages: 7500}, 196 {subject: "three", messages: 2500}, 197 {subject: "four", messages: 1000}, 198 {subject: "five.>", messages: 3000, wc: true}, 199 } 200 201 totalMsgs := 0 202 for _, subject := range subjects { 203 totalMsgs += subject.messages 204 } 205 206 // Setup consumers, filtering some of the messages from the stream. 207 consumers := []*struct { 208 name string 209 subjects []string 210 expectedMsgs int 211 delivered atomic.Int32 212 }{ 213 {name: "C1", subjects: []string{"one"}, expectedMsgs: 5000}, 214 {name: "C2", subjects: []string{"two"}, expectedMsgs: 7500}, 215 {name: "C3", subjects: []string{"one"}, expectedMsgs: 5000}, 216 {name: "C4", subjects: []string{"one"}, expectedMsgs: 5000}, 217 } 218 219 mset, err := acc.addStream(&StreamConfig{ 220 Name: "TEST", 221 Retention: LimitsPolicy, 222 Subjects: []string{"one", "two", "three", "four", "five.>"}, 223 MaxAge: time.Second * 90, 224 }) 225 require_NoError(t, err) 226 227 for c, consumer := range consumers { 228 _, err := mset.addConsumer(&ConsumerConfig{ 229 Durable: consumer.name, 230 FilterSubjects: consumer.subjects, 231 AckPolicy: AckExplicit, 232 DeliverPolicy: DeliverAll, 233 AckWait: time.Second * 30, 234 DeliverSubject: nc.NewInbox(), 235 }) 236 require_NoError(t, err) 237 go func(c int, name string) { 238 _, err = js.Subscribe("", func(m *nats.Msg) { 239 require_NoError(t, m.Ack()) 240 require_NoError(t, err) 241 consumers[c].delivered.Add(1) 242 243 }, nats.Bind("TEST", name)) 244 require_NoError(t, err) 245 }(c, consumer.name) 246 } 247 248 // Publish with random intervals, while consumers are active. 249 var wg sync.WaitGroup 250 for _, subject := range subjects { 251 wg.Add(subject.messages) 252 go func(subject string, messages int, wc bool) { 253 nc, js := jsClientConnect(t, s) 254 defer nc.Close() 255 time.Sleep(time.Duration(rand.Int63n(1000)+1) * time.Millisecond) 256 for i := 0; i < messages; i++ { 257 time.Sleep(time.Duration(rand.Int63n(1000)+1) * time.Microsecond) 258 // If subject has wildcard, add random last subject token. 259 pubSubject := subject 260 if wc { 261 pubSubject = fmt.Sprintf("%v.%v", subject, rand.Int63n(10)) 262 } 263 _, err := js.PublishAsync(pubSubject, []byte("data")) 264 require_NoError(t, err) 265 wg.Done() 266 } 267 }(subject.subject, subject.messages, subject.wc) 268 } 269 wg.Wait() 270 271 checkFor(t, time.Second*10, time.Millisecond*500, func() error { 272 for _, consumer := range consumers { 273 info, err := js.ConsumerInfo("TEST", consumer.name) 274 require_NoError(t, err) 275 if info.Delivered.Consumer != uint64(consumer.expectedMsgs) { 276 return fmt.Errorf("%v:expected consumer delivered seq %v, got %v. actually delivered: %v", 277 consumer.name, consumer.expectedMsgs, info.Delivered.Consumer, consumer.delivered.Load()) 278 } 279 if info.AckFloor.Consumer != uint64(consumer.expectedMsgs) { 280 return fmt.Errorf("%v: expected consumer ack floor %v, got %v", consumer.name, totalMsgs, info.AckFloor.Consumer) 281 } 282 if consumer.delivered.Load() != int32(consumer.expectedMsgs) { 283 284 return fmt.Errorf("%v: expected %v, got %v", consumer.name, consumer.expectedMsgs, consumer.delivered.Load()) 285 } 286 } 287 return nil 288 }) 289 290 } 291 292 func TestJetStreamConsumerMultipleConsumersMultipleFilters(t *testing.T) { 293 s := RunBasicJetStreamServer(t) 294 defer s.Shutdown() 295 296 nc, js := jsClientConnect(t, s) 297 defer nc.Close() 298 acc := s.GlobalAccount() 299 300 // Setup few subjects with varying messages count. 301 subjects := []struct { 302 subject string 303 messages int 304 wc bool 305 }{ 306 {subject: "one", messages: 50}, 307 {subject: "two", messages: 75}, 308 {subject: "three", messages: 250}, 309 {subject: "four", messages: 10}, 310 {subject: "five.>", messages: 300, wc: true}, 311 } 312 313 totalMsgs := 0 314 for _, subject := range subjects { 315 totalMsgs += subject.messages 316 } 317 318 // Setup consumers, filtering some of the messages from the stream. 319 consumers := []*struct { 320 name string 321 subjects []string 322 expectedMsgs int 323 delivered atomic.Int32 324 }{ 325 {name: "C1", subjects: []string{"one", "two"}, expectedMsgs: 125}, 326 {name: "C2", subjects: []string{"two", "three"}, expectedMsgs: 325}, 327 {name: "C3", subjects: []string{"one", "three"}, expectedMsgs: 300}, 328 {name: "C4", subjects: []string{"one", "five.>"}, expectedMsgs: 350}, 329 } 330 331 mset, err := acc.addStream(&StreamConfig{ 332 Name: "TEST", 333 Retention: LimitsPolicy, 334 Subjects: []string{"one", "two", "three", "four", "five.>"}, 335 MaxAge: time.Second * 90, 336 }) 337 require_NoError(t, err) 338 339 for c, consumer := range consumers { 340 _, err := mset.addConsumer(&ConsumerConfig{ 341 Durable: consumer.name, 342 FilterSubjects: consumer.subjects, 343 AckPolicy: AckExplicit, 344 DeliverPolicy: DeliverAll, 345 AckWait: time.Second * 30, 346 DeliverSubject: nc.NewInbox(), 347 }) 348 require_NoError(t, err) 349 go func(c int, name string) { 350 _, err = js.Subscribe("", func(m *nats.Msg) { 351 require_NoError(t, m.Ack()) 352 require_NoError(t, err) 353 consumers[c].delivered.Add(1) 354 355 }, nats.Bind("TEST", name)) 356 require_NoError(t, err) 357 }(c, consumer.name) 358 } 359 360 // Publish with random intervals, while consumers are active. 361 var wg sync.WaitGroup 362 for _, subject := range subjects { 363 wg.Add(subject.messages) 364 go func(subject string, messages int, wc bool) { 365 nc, js := jsClientConnect(t, s) 366 defer nc.Close() 367 time.Sleep(time.Duration(rand.Int63n(1000)+1) * time.Millisecond) 368 for i := 0; i < messages; i++ { 369 time.Sleep(time.Duration(rand.Int63n(1000)+1) * time.Microsecond) 370 // If subject has wildcard, add random last subject token. 371 pubSubject := subject 372 if wc { 373 pubSubject = fmt.Sprintf("%v.%v", subject, rand.Int63n(10)) 374 } 375 ack, err := js.PublishAsync(pubSubject, []byte("data")) 376 require_NoError(t, err) 377 go func() { 378 ack.Ok() 379 wg.Done() 380 }() 381 } 382 }(subject.subject, subject.messages, subject.wc) 383 } 384 done := make(chan struct{}) 385 go func() { 386 wg.Wait() 387 close(done) 388 }() 389 390 select { 391 case <-time.After(time.Second * 15): 392 t.Fatalf("Timed out waiting for acks") 393 case <-done: 394 } 395 wg.Wait() 396 397 checkFor(t, time.Second*15, time.Second*1, func() error { 398 for _, consumer := range consumers { 399 info, err := js.ConsumerInfo("TEST", consumer.name) 400 require_NoError(t, err) 401 if info.Delivered.Consumer != uint64(consumer.expectedMsgs) { 402 return fmt.Errorf("%v:expected consumer delivered seq %v, got %v. actually delivered: %v", 403 consumer.name, consumer.expectedMsgs, info.Delivered.Consumer, consumer.delivered.Load()) 404 } 405 if info.AckFloor.Consumer != uint64(consumer.expectedMsgs) { 406 return fmt.Errorf("%v: expected consumer ack floor %v, got %v", consumer.name, totalMsgs, info.AckFloor.Consumer) 407 } 408 if consumer.delivered.Load() != int32(consumer.expectedMsgs) { 409 410 return fmt.Errorf("%v: expected %v, got %v", consumer.name, consumer.expectedMsgs, consumer.delivered.Load()) 411 } 412 } 413 return nil 414 }) 415 416 } 417 418 func TestJetStreamConsumerMultipleFiltersSequence(t *testing.T) { 419 s := RunBasicJetStreamServer(t) 420 defer s.Shutdown() 421 422 nc, js := jsClientConnect(t, s) 423 defer nc.Close() 424 acc := s.GlobalAccount() 425 426 mset, err := acc.addStream(&StreamConfig{ 427 Name: "TEST", 428 Retention: LimitsPolicy, 429 Subjects: []string{"one", "two", "three", "four", "five.>"}, 430 MaxAge: time.Second * 90, 431 }) 432 require_NoError(t, err) 433 434 _, err = mset.addConsumer(&ConsumerConfig{ 435 Durable: "DUR", 436 FilterSubjects: []string{"one", "two"}, 437 AckPolicy: AckExplicit, 438 DeliverPolicy: DeliverAll, 439 AckWait: time.Second * 30, 440 DeliverSubject: nc.NewInbox(), 441 }) 442 require_NoError(t, err) 443 444 for i := 0; i < 20; i++ { 445 sendStreamMsg(t, nc, "one", fmt.Sprintf("%d", i)) 446 } 447 for i := 20; i < 40; i++ { 448 sendStreamMsg(t, nc, "two", fmt.Sprintf("%d", i)) 449 } 450 for i := 40; i < 60; i++ { 451 sendStreamMsg(t, nc, "one", fmt.Sprintf("%d", i)) 452 } 453 454 sub, err := js.SubscribeSync("", nats.Bind("TEST", "DUR")) 455 require_NoError(t, err) 456 457 for i := 0; i < 60; i++ { 458 msg, err := sub.NextMsg(time.Second * 1) 459 require_NoError(t, err) 460 require_True(t, string(msg.Data) == fmt.Sprintf("%d", i)) 461 } 462 } 463 464 func TestJetStreamConsumerActions(t *testing.T) { 465 s := RunBasicJetStreamServer(t) 466 defer s.Shutdown() 467 468 nc, _ := jsClientConnect(t, s) 469 defer nc.Close() 470 acc := s.GlobalAccount() 471 472 mset, err := acc.addStream(&StreamConfig{ 473 Name: "TEST", 474 Retention: LimitsPolicy, 475 Subjects: []string{"one", "two", "three", "four", "five.>"}, 476 MaxAge: time.Second * 90, 477 }) 478 require_NoError(t, err) 479 480 // Create Consumer. No consumers existed before, so should be fine. 481 _, err = mset.addConsumerWithAction(&ConsumerConfig{ 482 Durable: "DUR", 483 FilterSubjects: []string{"one", "two"}, 484 AckPolicy: AckExplicit, 485 DeliverPolicy: DeliverAll, 486 AckWait: time.Second * 30, 487 }, ActionCreate) 488 require_NoError(t, err) 489 // Create consumer again. Should be ok if action is CREATE but config is exactly the same. 490 _, err = mset.addConsumerWithAction(&ConsumerConfig{ 491 Durable: "DUR", 492 FilterSubjects: []string{"one", "two"}, 493 AckPolicy: AckExplicit, 494 DeliverPolicy: DeliverAll, 495 AckWait: time.Second * 30, 496 }, ActionCreate) 497 require_NoError(t, err) 498 // Create consumer again. Should error if action is CREATE. 499 _, err = mset.addConsumerWithAction(&ConsumerConfig{ 500 Durable: "DUR", 501 FilterSubjects: []string{"one"}, 502 AckPolicy: AckExplicit, 503 DeliverPolicy: DeliverAll, 504 AckWait: time.Second * 30, 505 }, ActionCreate) 506 require_Error(t, err) 507 508 // Update existing consumer. Should be fine, as consumer exists. 509 _, err = mset.addConsumerWithAction(&ConsumerConfig{ 510 Durable: "DUR", 511 FilterSubjects: []string{"one"}, 512 AckPolicy: AckExplicit, 513 DeliverPolicy: DeliverAll, 514 AckWait: time.Second * 30, 515 }, ActionUpdate) 516 require_NoError(t, err) 517 518 // Update consumer. Should error, as this consumer does not exist. 519 _, err = mset.addConsumerWithAction(&ConsumerConfig{ 520 Durable: "NEW", 521 FilterSubjects: []string{"one"}, 522 AckPolicy: AckExplicit, 523 DeliverPolicy: DeliverAll, 524 AckWait: time.Second * 30, 525 }, ActionUpdate) 526 require_Error(t, err) 527 528 // Create new ephemeral. Should be fine as the consumer doesn't exist already 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_NoError(t, err) 537 538 // Trying to create it again right away. Should error as it already exists (and hasn't been cleaned up yet) 539 _, err = mset.addConsumerWithAction(&ConsumerConfig{ 540 Name: "EPH", 541 FilterSubjects: []string{"one"}, 542 AckPolicy: AckExplicit, 543 DeliverPolicy: DeliverAll, 544 AckWait: time.Second * 30, 545 }, ActionCreate) 546 require_Error(t, err) 547 } 548 549 func TestJetStreamConsumerActionsOnWorkQueuePolicyStream(t *testing.T) { 550 s := RunBasicJetStreamServer(t) 551 defer s.Shutdown() 552 553 nc, _ := jsClientConnect(t, s) 554 defer nc.Close() 555 acc := s.GlobalAccount() 556 557 mset, err := acc.addStream(&StreamConfig{ 558 Name: "TEST", 559 Retention: WorkQueuePolicy, 560 Subjects: []string{"one", "two", "three", "four", "five.>"}, 561 }) 562 require_NoError(t, err) 563 564 _, err = mset.addConsumerWithAction(&ConsumerConfig{ 565 Durable: "C1", 566 FilterSubjects: []string{"one", "two"}, 567 AckPolicy: AckExplicit, 568 }, ActionCreate) 569 require_NoError(t, err) 570 571 _, err = mset.addConsumerWithAction(&ConsumerConfig{ 572 Durable: "C2", 573 FilterSubjects: []string{"three", "four"}, 574 AckPolicy: AckExplicit, 575 }, ActionCreate) 576 require_NoError(t, err) 577 578 _, err = mset.addConsumerWithAction(&ConsumerConfig{ 579 Durable: "C3", 580 FilterSubjects: []string{"five.*"}, 581 AckPolicy: AckExplicit, 582 }, ActionCreate) 583 require_NoError(t, err) 584 585 // Updating a consumer by removing a previous subject filter. 586 _, err = mset.addConsumerWithAction(&ConsumerConfig{ 587 Durable: "C1", 588 FilterSubjects: []string{"one"}, // Remove a subject. 589 AckPolicy: AckExplicit, 590 }, ActionUpdate) 591 require_NoError(t, err) 592 593 // Updating a consumer without overlapping subjects. 594 _, err = mset.addConsumerWithAction(&ConsumerConfig{ 595 Durable: "C2", 596 FilterSubjects: []string{"three", "four", "two"}, // Add previously removed subject. 597 AckPolicy: AckExplicit, 598 }, ActionUpdate) 599 require_NoError(t, err) 600 601 // Creating a consumer with overlapping subjects should return an error. 602 _, err = mset.addConsumerWithAction(&ConsumerConfig{ 603 Durable: "C4", 604 FilterSubjects: []string{"one", "two", "three", "four"}, 605 AckPolicy: AckExplicit, 606 }, ActionCreate) 607 require_Error(t, err) 608 if !IsNatsErr(err, JSConsumerWQConsumerNotUniqueErr) { 609 t.Errorf("want error %q, got %q", ApiErrors[JSConsumerWQConsumerNotUniqueErr], err) 610 } 611 612 // Updating a consumer with overlapping subjects should return an error. 613 _, err = mset.addConsumerWithAction(&ConsumerConfig{ 614 Durable: "C3", 615 FilterSubjects: []string{"one", "two", "three", "four"}, 616 AckPolicy: AckExplicit, 617 }, ActionUpdate) 618 require_Error(t, err) 619 if !IsNatsErr(err, JSConsumerWQConsumerNotUniqueErr) { 620 t.Errorf("want error %q, got %q", ApiErrors[JSConsumerWQConsumerNotUniqueErr], err) 621 } 622 } 623 624 func TestJetStreamConsumerActionsViaAPI(t *testing.T) { 625 s := RunBasicJetStreamServer(t) 626 defer s.Shutdown() 627 628 nc, _ := jsClientConnect(t, s) 629 defer nc.Close() 630 acc := s.GlobalAccount() 631 632 _, err := acc.addStream(&StreamConfig{ 633 Name: "TEST", 634 Retention: LimitsPolicy, 635 Subjects: []string{"one"}, 636 MaxAge: time.Second * 90, 637 }) 638 require_NoError(t, err) 639 640 // Update non-existing consumer, which should fail. 641 request, err := json.Marshal(&CreateConsumerRequest{ 642 Action: ActionUpdate, 643 Config: ConsumerConfig{ 644 Durable: "hello", 645 }, 646 Stream: "TEST", 647 }) 648 require_NoError(t, err) 649 650 resp, err := nc.Request("$JS.API.CONSUMER.DURABLE.CREATE.TEST.hello", []byte(request), time.Second*6) 651 require_NoError(t, err) 652 var ccResp JSApiConsumerCreateResponse 653 err = json.Unmarshal(resp.Data, &ccResp) 654 require_NoError(t, err) 655 require_Error(t, ccResp.Error) 656 657 // create non existing consumer - which should be fine. 658 ccResp.Error = nil 659 request, err = json.Marshal(&CreateConsumerRequest{ 660 Action: ActionCreate, 661 Config: ConsumerConfig{ 662 Durable: "hello", 663 }, 664 Stream: "TEST", 665 }) 666 require_NoError(t, err) 667 668 resp, err = nc.Request("$JS.API.CONSUMER.DURABLE.CREATE.TEST.hello", []byte(request), time.Second*6) 669 require_NoError(t, err) 670 err = json.Unmarshal(resp.Data, &ccResp) 671 require_NoError(t, err) 672 if ccResp.Error != nil { 673 t.Fatalf("expected nil, got %v", ccResp.Error) 674 } 675 676 // re-create existing consumer - which should be an error. 677 ccResp.Error = nil 678 request, err = json.Marshal(&CreateConsumerRequest{ 679 Action: ActionCreate, 680 Config: ConsumerConfig{ 681 Durable: "hello", 682 FilterSubject: "one", 683 }, 684 Stream: "TEST", 685 }) 686 require_NoError(t, err) 687 resp, err = nc.Request("$JS.API.CONSUMER.DURABLE.CREATE.TEST.hello", []byte(request), time.Second*6) 688 require_NoError(t, err) 689 err = json.Unmarshal(resp.Data, &ccResp) 690 require_NoError(t, err) 691 if ccResp.Error == nil { 692 t.Fatalf("expected err, got nil") 693 } 694 695 // create a named ephemeral consumer 696 ccResp.Error = nil 697 request, err = json.Marshal(&CreateConsumerRequest{ 698 Action: ActionCreate, 699 Config: ConsumerConfig{ 700 Name: "ephemeral", 701 FilterSubject: "one", 702 }, 703 Stream: "TEST", 704 }) 705 require_NoError(t, err) 706 resp, err = nc.Request("$JS.API.CONSUMER.CREATE.TEST.ephemeral", []byte(request), time.Second*6) 707 require_NoError(t, err) 708 err = json.Unmarshal(resp.Data, &ccResp) 709 require_NoError(t, err) 710 711 // re-create existing consumer - which should be an error. 712 ccResp.Error = nil 713 request, err = json.Marshal(&CreateConsumerRequest{ 714 Action: ActionCreate, 715 Config: ConsumerConfig{ 716 Name: "ephemeral", 717 FilterSubject: "one", 718 }, 719 Stream: "TEST", 720 }) 721 require_NoError(t, err) 722 resp, err = nc.Request("$JS.API.CONSUMER.CREATE.TEST.ephemeral", []byte(request), time.Second*6) 723 require_NoError(t, err) 724 err = json.Unmarshal(resp.Data, &ccResp) 725 require_NoError(t, err) 726 if ccResp.Error == nil { 727 t.Fatalf("expected err, got nil") 728 } 729 } 730 731 func TestJetStreamConsumerActionsUnmarshal(t *testing.T) { 732 tests := []struct { 733 name string 734 given []byte 735 expected ConsumerAction 736 expectErr bool 737 }{ 738 {name: "action create", given: []byte(`{"action": "create"}`), expected: ActionCreate}, 739 {name: "action update", given: []byte(`{"action": "update"}`), expected: ActionUpdate}, 740 {name: "no action", given: []byte("{}"), expected: ActionCreateOrUpdate}, 741 {name: "unknown", given: []byte(`{"action": "unknown"}`), expected: ActionCreateOrUpdate, expectErr: true}, 742 } 743 744 for _, test := range tests { 745 t.Run(test.name, func(t *testing.T) { 746 747 var request CreateConsumerRequest 748 err := json.Unmarshal(test.given, &request) 749 fmt.Printf("given: %v, expected: %v\n", test.expectErr, err) 750 if !test.expectErr { 751 require_NoError(t, err) 752 } else { 753 require_Error(t, err) 754 } 755 require_True(t, test.expected == request.Action) 756 }) 757 } 758 } 759 760 func TestJetStreamConsumerMultipleFiltersLastPerSubject(t *testing.T) { 761 c := createJetStreamClusterExplicit(t, "R3S", 3) 762 defer c.shutdown() 763 764 nc, js := jsClientConnect(t, c.randomServer()) 765 defer nc.Close() 766 767 _, error := js.AddStream(&nats.StreamConfig{ 768 Name: "TEST", 769 Subjects: []string{"one", "two"}, 770 Replicas: 3, 771 }) 772 require_NoError(t, error) 773 774 sendStreamMsg(t, nc, "one", "1") 775 sendStreamMsg(t, nc, "one", "2") 776 sendStreamMsg(t, nc, "one", "3") 777 sendStreamMsg(t, nc, "two", "1") 778 sendStreamMsg(t, nc, "two", "2") 779 sendStreamMsg(t, nc, "two", "3") 780 781 _, err := js.AddConsumer("TEST", &nats.ConsumerConfig{ 782 Name: "C", 783 FilterSubjects: []string{"one", "two"}, 784 DeliverPolicy: nats.DeliverLastPerSubjectPolicy, 785 Replicas: 3, 786 DeliverSubject: "deliver", 787 }) 788 require_NoError(t, err) 789 790 consumer, err := js.SubscribeSync("", nats.Bind("TEST", "C")) 791 require_NoError(t, err) 792 793 // expect last message for subject "one" 794 msg, err := consumer.NextMsg(time.Second) 795 require_NoError(t, err) 796 require_Equal(t, "3", string(msg.Data)) 797 require_Equal(t, "one", msg.Subject) 798 799 // expect last message for subject "two" 800 msg, err = consumer.NextMsg(time.Second) 801 require_NoError(t, err) 802 require_Equal(t, "3", string(msg.Data)) 803 require_Equal(t, "two", msg.Subject) 804 805 } 806 807 func consumerWithFilterSubjects(filterSubjects []string) *consumer { 808 c := consumer{} 809 for _, filter := range filterSubjects { 810 sub := &subjectFilter{ 811 subject: filter, 812 hasWildcard: subjectHasWildcard(filter), 813 tokenizedSubject: tokenizeSubjectIntoSlice(nil, filter), 814 } 815 c.subjf = append(c.subjf, sub) 816 } 817 818 return &c 819 } 820 821 func filterSubjects(n int) []string { 822 fs := make([]string, 0, n) 823 for { 824 literals := []string{"foo", "bar", nuid.Next(), "xyz", "abcdef"} 825 fs = append(fs, strings.Join(literals, ".")) 826 if len(fs) == n { 827 return fs 828 } 829 // Create more filterSubjects by going through the literals and replacing one with the '*' wildcard. 830 l := len(literals) 831 for i := 0; i < l; i++ { 832 e := make([]string, l) 833 for j := 0; j < l; j++ { 834 if j == i { 835 e[j] = "*" 836 } else { 837 e[j] = literals[j] 838 } 839 } 840 fs = append(fs, strings.Join(e, ".")) 841 if len(fs) == n { 842 return fs 843 } 844 } 845 } 846 } 847 848 func TestJetStreamConsumerIsFilteredMatch(t *testing.T) { 849 for _, test := range []struct { 850 name string 851 filterSubjects []string 852 subject string 853 result bool 854 }{ 855 {"no filter", []string{}, "foo.bar", true}, 856 {"literal match", []string{"foo.baz", "foo.bar"}, "foo.bar", true}, 857 {"literal mismatch", []string{"foo.baz", "foo.bar"}, "foo.ban", false}, 858 {"wildcard > match", []string{"bar.>", "foo.>"}, "foo.bar", true}, 859 {"wildcard > match", []string{"bar.>", "foo.>"}, "bar.foo", true}, 860 {"wildcard > mismatch", []string{"bar.>", "foo.>"}, "baz.foo", false}, 861 {"wildcard * match", []string{"bar.*", "foo.*"}, "foo.bar", true}, 862 {"wildcard * match", []string{"bar.*", "foo.*"}, "bar.foo", true}, 863 {"wildcard * mismatch", []string{"bar.*", "foo.*"}, "baz.foo", false}, 864 {"wildcard * match", []string{"foo.*.x", "foo.*.y"}, "foo.bar.x", true}, 865 {"wildcard * match", []string{"foo.*.x", "foo.*.y", "foo.*.z"}, "foo.bar.z", true}, 866 {"many mismatch", filterSubjects(100), "foo.bar.do.not.match.any.filter.subject", false}, 867 {"many match", filterSubjects(100), "foo.bar.12345.xyz.abcdef", true}, // will be matched by "foo.bar.*.xyz.abcdef" 868 } { 869 test := test 870 871 t.Run(test.name, func(t *testing.T) { 872 t.Parallel() 873 874 c := consumerWithFilterSubjects(test.filterSubjects) 875 if res := c.isFilteredMatch(test.subject); res != test.result { 876 t.Fatalf("Subject %q filtered match of %v, should be %v, got %v", 877 test.subject, test.filterSubjects, test.result, res) 878 } 879 }) 880 } 881 } 882 883 func TestJetStreamConsumerWorkQueuePolicyOverlap(t *testing.T) { 884 s := RunBasicJetStreamServer(t) 885 defer s.Shutdown() 886 887 nc, js := jsClientConnect(t, s) 888 defer nc.Close() 889 890 _, err := js.AddStream(&nats.StreamConfig{ 891 Name: "TEST", 892 Subjects: []string{"foo.*.*"}, 893 Retention: nats.WorkQueuePolicy, 894 }) 895 require_NoError(t, err) 896 897 _, err = js.AddConsumer("TEST", &nats.ConsumerConfig{ 898 Durable: "ConsumerA", 899 FilterSubject: "foo.bar.*", 900 AckPolicy: nats.AckExplicitPolicy, 901 }) 902 require_NoError(t, err) 903 904 _, err = js.AddConsumer("TEST", &nats.ConsumerConfig{ 905 Durable: "ConsumerB", 906 FilterSubject: "foo.*.bar", 907 AckPolicy: nats.AckExplicitPolicy, 908 }) 909 require_Error(t, err) 910 require_True(t, strings.Contains(err.Error(), "unique")) 911 } 912 913 func TestJetStreamConsumerIsEqualOrSubsetMatch(t *testing.T) { 914 for _, test := range []struct { 915 name string 916 filterSubjects []string 917 subject string 918 result bool 919 }{ 920 {"no filter", []string{}, "foo.bar", false}, 921 {"literal match", []string{"foo.baz", "foo.bar"}, "foo.bar", true}, 922 {"literal mismatch", []string{"foo.baz", "foo.bar"}, "foo.ban", false}, 923 {"literal match", []string{"bar.>", "foo.>"}, "foo.>", true}, 924 {"subset match", []string{"bar.foo.>", "foo.bar.>"}, "bar.>", true}, 925 {"subset mismatch", []string{"bar.>", "foo.>"}, "baz.foo.>", false}, 926 {"literal match", filterSubjects(100), "foo.bar.*.xyz.abcdef", true}, 927 {"subset match", filterSubjects(100), "foo.bar.>", true}, 928 } { 929 test := test 930 931 t.Run(test.name, func(t *testing.T) { 932 t.Parallel() 933 934 c := consumerWithFilterSubjects(test.filterSubjects) 935 if res := c.isEqualOrSubsetMatch(test.subject); res != test.result { 936 t.Fatalf("Subject %q subset match of %v, should be %v, got %v", 937 test.subject, test.filterSubjects, test.result, res) 938 } 939 }) 940 } 941 } 942 943 func TestJetStreamConsumerBackOff(t *testing.T) { 944 s := RunBasicJetStreamServer(t) 945 defer s.Shutdown() 946 947 nc, js := jsClientConnect(t, s) 948 defer nc.Close() 949 950 for _, test := range []struct { 951 name string 952 config nats.ConsumerConfig 953 shouldErr bool 954 }{ 955 { 956 name: "backoff_with_max_deliver", 957 config: nats.ConsumerConfig{ 958 MaxDeliver: 3, 959 BackOff: []time.Duration{time.Second, time.Minute}, 960 }, 961 shouldErr: false, 962 }, 963 { 964 name: "backoff_with_max_deliver_smaller", 965 config: nats.ConsumerConfig{ 966 MaxDeliver: 2, 967 BackOff: []time.Duration{time.Second, time.Minute, time.Hour}, 968 }, 969 shouldErr: true, 970 }, 971 { 972 name: "backoff_with_default_max_deliver", 973 config: nats.ConsumerConfig{ 974 BackOff: []time.Duration{time.Second, time.Minute, time.Hour}, 975 }, 976 shouldErr: false, 977 }, 978 } { 979 t.Run(test.name, func(t *testing.T) { 980 _, err := js.AddStream(&nats.StreamConfig{ 981 Name: test.name, 982 Subjects: []string{test.name}, 983 }) 984 require_NoError(t, err) 985 986 _, err = js.AddConsumer(test.name, &test.config) 987 require_True(t, test.shouldErr == (err != nil)) 988 if test.shouldErr { 989 require_True(t, strings.Contains(err.Error(), "max deliver")) 990 } 991 992 // test if updating consumers works too. 993 test.config.Durable = "consumer" 994 _, err = js.AddConsumer(test.name, &nats.ConsumerConfig{ 995 Durable: test.config.Durable, 996 }) 997 require_NoError(t, err) 998 999 test.config.Description = "Updated" 1000 _, err = js.UpdateConsumer(test.name, &test.config) 1001 require_True(t, test.shouldErr == (err != nil)) 1002 if test.shouldErr { 1003 require_True(t, strings.Contains(err.Error(), "max deliver")) 1004 } 1005 }) 1006 1007 } 1008 } 1009 1010 func TestJetStreamConsumerDelete(t *testing.T) { 1011 tests := []struct { 1012 name string 1013 replicas int 1014 }{ 1015 {"single server", 1}, 1016 {"clustered", 3}, 1017 } 1018 1019 for _, test := range tests { 1020 t.Run(test.name, func(t *testing.T) { 1021 var s *Server 1022 if test.replicas == 1 { 1023 s = RunBasicJetStreamServer(t) 1024 defer s.Shutdown() 1025 } else { 1026 c := createJetStreamClusterExplicit(t, "R3S", test.replicas) 1027 defer c.shutdown() 1028 s = c.randomServer() 1029 } 1030 1031 nc, js := jsClientConnect(t, s) 1032 defer nc.Close() 1033 1034 _, err := js.AddStream(&nats.StreamConfig{ 1035 Name: "TEST", 1036 Subjects: []string{"events.>"}, 1037 MaxAge: time.Second * 90, 1038 Replicas: test.replicas, 1039 }) 1040 require_NoError(t, err) 1041 1042 _, err = js.AddConsumer("TEST", &nats.ConsumerConfig{ 1043 Durable: "consumer", 1044 FilterSubject: "events.>", 1045 Replicas: test.replicas, 1046 }) 1047 require_NoError(t, err) 1048 1049 js.Publish("events.1", []byte("hello")) 1050 1051 cr := JSApiConsumerGetNextRequest{ 1052 Batch: 10, 1053 Expires: time.Second * 30, 1054 } 1055 crBytes, err := json.Marshal(cr) 1056 require_NoError(t, err) 1057 1058 inbox := nats.NewInbox() 1059 consumerSub, err := nc.SubscribeSync(inbox) 1060 require_NoError(t, err) 1061 1062 err = nc.PublishRequest(fmt.Sprintf(JSApiRequestNextT, "TEST", "consumer"), inbox, crBytes) 1063 require_NoError(t, err) 1064 1065 msg, err := consumerSub.NextMsg(time.Second * 30) 1066 require_NoError(t, err) 1067 require_Equal(t, "hello", string(msg.Data)) 1068 1069 js.DeleteConsumer("TEST", "consumer") 1070 1071 msg, err = consumerSub.NextMsg(time.Second * 30) 1072 require_NoError(t, err) 1073 1074 if !strings.Contains(string(msg.Header.Get("Description")), "Consumer Deleted") { 1075 t.Fatalf("Expected exclusive consumer error, got %q", msg.Header.Get("Description")) 1076 } 1077 }) 1078 1079 } 1080 } 1081 1082 func TestFetchWithDrain(t *testing.T) { 1083 s := RunBasicJetStreamServer(t) 1084 defer s.Shutdown() 1085 1086 nc, js := jsClientConnect(t, s) 1087 defer nc.Close() 1088 1089 _, err := js.AddStream(&nats.StreamConfig{ 1090 Name: "TEST", 1091 Subjects: []string{"foo"}, 1092 Retention: nats.LimitsPolicy, 1093 }) 1094 require_NoError(t, err) 1095 1096 _, err = js.AddConsumer("TEST", &nats.ConsumerConfig{ 1097 Durable: "C", 1098 AckPolicy: nats.AckExplicitPolicy, 1099 AckWait: time.Second * 10, 1100 }) 1101 require_NoError(t, err) 1102 1103 const messages = 10_000 1104 1105 for i := 0; i < messages; i++ { 1106 sendStreamMsg(t, nc, "foo", fmt.Sprintf("%d", i+1)) 1107 } 1108 1109 cr := JSApiConsumerGetNextRequest{ 1110 Batch: 100_000, 1111 Expires: time.Second * 10, 1112 } 1113 crBytes, err := json.Marshal(cr) 1114 require_NoError(t, err) 1115 1116 msgs := make(map[int]int) 1117 1118 processMsg := func(t *testing.T, sub *nats.Subscription, msgs map[int]int) bool { 1119 msg, err := sub.NextMsg(time.Second * 1) 1120 if err != nil { 1121 return false 1122 } 1123 metadata, err := msg.Metadata() 1124 require_NoError(t, err) 1125 err = msg.Ack() 1126 require_NoError(t, err) 1127 1128 v, err := strconv.Atoi(string(msg.Data)) 1129 require_NoError(t, err) 1130 require_Equal(t, uint64(v), metadata.Sequence.Stream) 1131 1132 _, ok := msgs[int(metadata.Sequence.Stream)] 1133 if _, ok := msgs[int(metadata.Sequence.Stream-1)]; !ok && len(msgs) > 0 { 1134 t.Logf("Stream Sequence gap detected: current %d", metadata.Sequence.Stream) 1135 } 1136 if ok { 1137 t.Fatalf("Message has been seen before") 1138 } 1139 1140 msgs[int(metadata.Sequence.Stream)] = int(metadata.NumDelivered) 1141 1142 require_NoError(t, err) 1143 return true 1144 } 1145 1146 for { 1147 inbox := nats.NewInbox() 1148 sub, err := nc.SubscribeSync(inbox) 1149 require_NoError(t, err) 1150 1151 err = nc.PublishRequest(fmt.Sprintf(JSApiRequestNextT, "TEST", "C"), inbox, crBytes) 1152 require_NoError(t, err) 1153 1154 // Drain after first message processed. 1155 processMsg(t, sub, msgs) 1156 sub.Drain() 1157 1158 for { 1159 if !processMsg(t, sub, msgs) { 1160 if len(msgs) == messages { 1161 return 1162 } 1163 break 1164 } 1165 } 1166 } 1167 } 1168 1169 func Benchmark____JetStreamConsumerIsFilteredMatch(b *testing.B) { 1170 subject := "foo.bar.do.not.match.any.filter.subject" 1171 for n := 1; n <= 1024; n *= 2 { 1172 name := fmt.Sprintf("%d filter subjects", int(n)) 1173 c := consumerWithFilterSubjects(filterSubjects(int(n))) 1174 b.Run(name, func(b *testing.B) { 1175 c.isFilteredMatch(subject) 1176 }) 1177 } 1178 }