github.com/altipla-consulting/ravendb-go-client@v0.1.3/tests/subscriptions_basic_test.go (about) 1 package tests 2 3 import ( 4 "errors" 5 "reflect" 6 "sync/atomic" 7 "testing" 8 "time" 9 10 ravendb "github.com/altipla-consulting/ravendb-go-client" 11 "github.com/stretchr/testify/assert" 12 ) 13 14 const ( 15 _reasonableWaitTime = time.Second * 5 // TODO: is it 60 seconds in Java? 16 ) 17 18 // returns true if timed out 19 func chanWaitTimedOut(ch chan bool, timeout time.Duration) bool { 20 select { 21 case <-ch: 22 return false 23 case <-time.After(timeout): 24 return true 25 } 26 } 27 28 // returns false if timed out 29 func getNextUser(docs chan *User, timeout time.Duration) (*User, bool) { 30 if timeout == 0 { 31 timeout = _reasonableWaitTime 32 } 33 select { 34 case u := <-docs: 35 return u, true 36 case <-time.After(timeout): 37 return nil, false 38 } 39 } 40 41 func subscriptionsBasic_canDeleteSubscription(t *testing.T, driver *RavenTestDriver) { 42 var err error 43 store := driver.getDocumentStoreMust(t) 44 defer store.Close() 45 46 id1, err := store.Subscriptions().CreateForType(reflect.TypeOf(&User{}), nil, "") 47 assert.NoError(t, err) 48 id2, err := store.Subscriptions().CreateForType(reflect.TypeOf(&User{}), nil, "") 49 assert.NoError(t, err) 50 51 subscriptions, err := store.Subscriptions().GetSubscriptions(0, 5, "") 52 assert.NoError(t, err) 53 assert.Equal(t, len(subscriptions), 2) 54 55 // test getSubscriptionState as well 56 subscriptionState, err := store.Subscriptions().GetSubscriptionState(id1, "") 57 assert.NoError(t, err) 58 cv := subscriptionState.ChangeVectorForNextBatchStartingPoint 59 assert.Nil(t, cv) 60 61 err = store.Subscriptions().Delete(id1, "") 62 assert.NoError(t, err) 63 err = store.Subscriptions().Delete(id2, "") 64 assert.NoError(t, err) 65 66 subscriptions, err = store.Subscriptions().GetSubscriptions(0, 5, "") 67 assert.NoError(t, err) 68 assert.Equal(t, len(subscriptions), 0) 69 } 70 71 func subscriptionsBasic_shouldThrowWhenOpeningNoExistingSubscription(t *testing.T, driver *RavenTestDriver) { 72 store := driver.getDocumentStoreMust(t) 73 defer store.Close() 74 75 clazz := reflect.TypeOf(&map[string]interface{}{}) 76 opts := ravendb.NewSubscriptionWorkerOptions("1") 77 78 subscription, err := store.Subscriptions().GetSubscriptionWorker(clazz, opts, "") 79 assert.NoError(t, err) 80 81 results := make(chan *ravendb.SubscriptionBatch, 16) 82 cb := func(batch *ravendb.SubscriptionBatch) error { 83 results <- batch 84 return nil 85 } 86 err = subscription.Run(cb) 87 88 assert.NoError(t, err) 89 err = subscription.WaitUntilFinished(0) 90 assert.NotNil(t, err) 91 _, ok := err.(*ravendb.SubscriptionDoesNotExistError) 92 assert.True(t, ok) 93 assert.Equal(t, err, subscription.Err()) 94 95 err = subscription.Close() 96 assert.NoError(t, err) 97 } 98 99 func subscriptionsBasic_shouldThrowOnAttemptToOpenAlreadyOpenedSubscription(t *testing.T, driver *RavenTestDriver) { 100 store := driver.getDocumentStoreMust(t) 101 defer store.Close() 102 103 id, err := store.Subscriptions().CreateForType(reflect.TypeOf(&User{}), nil, "") 104 assert.NoError(t, err) 105 106 { 107 clazz := reflect.TypeOf(map[string]interface{}{}) 108 opts := ravendb.NewSubscriptionWorkerOptions(id) 109 subscription, err := store.Subscriptions().GetSubscriptionWorker(clazz, opts, "") 110 assert.NoError(t, err) 111 112 { 113 session, err := store.OpenSession("") 114 assert.NoError(t, err) 115 err = session.Store(&User{}) 116 assert.NoError(t, err) 117 err = session.SaveChanges() 118 assert.NoError(t, err) 119 120 session.Close() 121 } 122 123 results := make(chan *ravendb.SubscriptionBatch, 16) 124 cb := func(batch *ravendb.SubscriptionBatch) error { 125 results <- batch 126 return nil 127 } 128 err = subscription.Run(cb) 129 assert.NoError(t, err) 130 131 select { 132 case <-results: 133 // no-op, got the result 134 case <-time.After(_reasonableWaitTime): 135 // no-op, timeout waiting for the result 136 } 137 138 options2 := ravendb.NewSubscriptionWorkerOptions(id) 139 options2.Strategy = ravendb.SubscriptionOpeningStrategyOpenIfFree 140 141 { 142 secondSubscription, err := store.Subscriptions().GetSubscriptionWorker(clazz, options2, "") 143 assert.NoError(t, err) 144 cb := func(batch *ravendb.SubscriptionBatch) error { 145 return nil 146 } 147 err = secondSubscription.Run(cb) 148 assert.NoError(t, err) 149 err = secondSubscription.WaitUntilFinished(0) 150 _, ok := err.(*ravendb.SubscriptionInUseError) 151 assert.True(t, ok) 152 153 err = secondSubscription.Close() 154 assert.NoError(t, err) 155 } 156 157 err = subscription.Close() 158 assert.NoError(t, err) 159 } 160 161 } 162 163 func subscriptionsBasic_shouldStreamAllDocumentsAfterSubscriptionCreation(t *testing.T, driver *RavenTestDriver) { 164 var err error 165 store := driver.getDocumentStoreMust(t) 166 defer store.Close() 167 168 var users []*User 169 { 170 session := openSessionMust(t, store) 171 172 user1 := &User{ 173 Age: 31, 174 } 175 err = session.StoreWithID(user1, "users/1") 176 assert.NoError(t, err) 177 users = append(users, user1) 178 179 user2 := &User{ 180 Age: 27, 181 } 182 err = session.StoreWithID(user2, "users/12") 183 assert.NoError(t, err) 184 users = append(users, user2) 185 186 user3 := &User{ 187 Age: 25, 188 } 189 err = session.StoreWithID(user3, "users/3") 190 assert.NoError(t, err) 191 users = append(users, user3) 192 193 err = session.SaveChanges() 194 assert.NoError(t, err) 195 196 session.Close() 197 } 198 199 id, err := store.Subscriptions().CreateForType(reflect.TypeOf(&User{}), nil, "") 200 assert.NoError(t, err) 201 202 { 203 opts := ravendb.NewSubscriptionWorkerOptions(id) 204 clazz := reflect.TypeOf(&User{}) 205 subscription, err := store.Subscriptions().GetSubscriptionWorker(clazz, opts, "") 206 assert.NoError(t, err) 207 208 results := make(chan *ravendb.SubscriptionBatch, 16) 209 cb := func(batch *ravendb.SubscriptionBatch) error { 210 results <- batch 211 return nil 212 } 213 err = subscription.Run(cb) 214 assert.NoError(t, err) 215 216 chDone := make(chan bool, 1) 217 go func() { 218 for batch := range results { 219 for i, item := range batch.Items { 220 expUser := users[i] 221 assert.Equal(t, item.ID, expUser.ID) 222 var u *User 223 err := item.GetResult(&u) 224 assert.NoError(t, err) 225 assert.Equal(t, u.Age, expUser.Age) 226 } 227 chDone <- true 228 } 229 }() 230 select { 231 case <-chDone: 232 // no-op, got the first batch 233 case <-time.After(_reasonableWaitTime): 234 assert.Fail(t, "timed out waiting for batch") 235 } 236 237 err = subscription.Close() 238 assert.NoError(t, err) 239 } 240 } 241 242 func subscriptionsBasic_shouldSendAllNewAndModifiedDocs(t *testing.T, driver *RavenTestDriver) { 243 var err error 244 store := driver.getDocumentStoreMust(t) 245 defer store.Close() 246 247 id, err := store.Subscriptions().CreateForType(reflect.TypeOf(&User{}), nil, "") 248 assert.NoError(t, err) 249 250 { 251 opts := ravendb.NewSubscriptionWorkerOptions(id) 252 clazz := reflect.TypeOf(map[string]interface{}{}) 253 subscription, err := store.Subscriptions().GetSubscriptionWorker(clazz, opts, "") 254 assert.NoError(t, err) 255 256 { 257 session := openSessionMust(t, store) 258 259 user := &User{} 260 user.setName("James") 261 err = session.StoreWithID(user, "users/1") 262 assert.NoError(t, err) 263 264 err = session.SaveChanges() 265 assert.NoError(t, err) 266 267 session.Close() 268 } 269 270 results := make(chan *ravendb.SubscriptionBatch, 16) 271 cb := func(batch *ravendb.SubscriptionBatch) error { 272 results <- batch 273 return nil 274 } 275 err = subscription.Run(cb) 276 assert.NoError(t, err) 277 go func() { 278 expNames := []string{"James", "Adam", "David"} 279 var n int 280 for batch := range results { 281 for _, item := range batch.Items { 282 var m map[string]interface{} 283 err := item.GetResult(&m) 284 assert.NoError(t, err) 285 name := m["name"].(string) 286 assert.Equal(t, name, expNames[n]) 287 n++ 288 } 289 } 290 }() 291 292 { 293 session := openSessionMust(t, store) 294 295 user := &User{} 296 user.setName("Adam") 297 err = session.StoreWithID(user, "users/12") 298 assert.NoError(t, err) 299 300 err = session.SaveChanges() 301 assert.NoError(t, err) 302 303 session.Close() 304 } 305 306 //Thread.sleep(15000); // test with sleep - let few heartbeats come to us - commented out for CI 307 308 { 309 session := openSessionMust(t, store) 310 311 user := &User{} 312 user.setName("David") 313 err = session.StoreWithID(user, "users/1") 314 assert.NoError(t, err) 315 316 err = session.SaveChanges() 317 assert.NoError(t, err) 318 319 session.Close() 320 } 321 322 err = subscription.Close() 323 assert.NoError(t, err) 324 } 325 } 326 327 func subscriptionsBasic_shouldRespectMaxDocCountInBatch(t *testing.T, driver *RavenTestDriver) { 328 var err error 329 store := driver.getDocumentStoreMust(t) 330 defer store.Close() 331 332 { 333 session := openSessionMust(t, store) 334 335 for i := 0; i < 100; i++ { 336 err = session.Store(&Company{}) 337 assert.NoError(t, err) 338 } 339 340 err = session.SaveChanges() 341 assert.NoError(t, err) 342 343 session.Close() 344 } 345 346 clazz := reflect.TypeOf(&Company{}) 347 id, err := store.Subscriptions().CreateForType(clazz, nil, "") 348 assert.NoError(t, err) 349 350 options := ravendb.NewSubscriptionWorkerOptions(id) 351 options.MaxDocsPerBatch = 25 352 353 { 354 clazz = reflect.TypeOf(map[string]interface{}{}) 355 subscriptionWorker, err := store.Subscriptions().GetSubscriptionWorker(clazz, options, "") 356 assert.NoError(t, err) 357 358 results := make(chan *ravendb.SubscriptionBatch, 16) 359 cb := func(batch *ravendb.SubscriptionBatch) error { 360 results <- batch 361 return nil 362 } 363 err = subscriptionWorker.Run(cb) 364 assert.NoError(t, err) 365 366 var totalItems int 367 for totalItems < 100 { 368 select { 369 case batch := <-results: 370 n := len(batch.Items) 371 assert.True(t, n <= 25) 372 totalItems += n 373 case <-time.After(_reasonableWaitTime): 374 assert.Fail(t, "timed out waiting for a batch") 375 totalItems = 100 376 } 377 } 378 _ = subscriptionWorker.Close() 379 } 380 } 381 382 func subscriptionsBasic_shouldRespectCollectionCriteria(t *testing.T, driver *RavenTestDriver) { 383 var err error 384 store := driver.getDocumentStoreMust(t) 385 defer store.Close() 386 387 { 388 session := openSessionMust(t, store) 389 390 for i := 0; i < 100; i++ { 391 err = session.Store(&Company{}) 392 assert.NoError(t, err) 393 err = session.Store(&User{}) 394 assert.NoError(t, err) 395 } 396 397 err = session.SaveChanges() 398 assert.NoError(t, err) 399 400 session.Close() 401 } 402 403 clazz := reflect.TypeOf(&User{}) 404 id, err := store.Subscriptions().CreateForType(clazz, nil, "") 405 assert.NoError(t, err) 406 407 options := ravendb.NewSubscriptionWorkerOptions(id) 408 options.MaxDocsPerBatch = 31 409 410 { 411 clazz = reflect.TypeOf(map[string]interface{}{}) 412 subscriptionWorker, err := store.Subscriptions().GetSubscriptionWorker(clazz, options, "") 413 assert.NoError(t, err) 414 415 results := make(chan *ravendb.SubscriptionBatch, 16) 416 cb := func(batch *ravendb.SubscriptionBatch) error { 417 results <- batch 418 return nil 419 } 420 err = subscriptionWorker.Run(cb) 421 assert.NoError(t, err) 422 423 var totalItems int 424 for totalItems < 100 { 425 select { 426 case batch := <-results: 427 n := len(batch.Items) 428 assert.True(t, n <= 31) 429 totalItems += n 430 case <-time.After(_reasonableWaitTime): 431 assert.Fail(t, "timed out waiting for batch") 432 totalItems = 100 433 } 434 435 } 436 437 _ = subscriptionWorker.Close() 438 } 439 } 440 441 func subscriptionsBasic_willAcknowledgeEmptyBatches(t *testing.T, driver *RavenTestDriver) { 442 var err error 443 store := driver.getDocumentStoreMust(t) 444 defer store.Close() 445 446 subscriptionDocuments, err := store.Subscriptions().GetSubscriptions(0, 10, "") 447 assert.NoError(t, err) 448 assert.Equal(t, len(subscriptionDocuments), 0) 449 450 opts := &ravendb.SubscriptionCreationOptions{} 451 clazz := reflect.TypeOf(&User{}) 452 allId, err := store.Subscriptions().CreateForType(clazz, opts, "") 453 assert.NoError(t, err) 454 455 { 456 clazz = reflect.TypeOf(map[string]interface{}{}) 457 opts := ravendb.NewSubscriptionWorkerOptions(allId) 458 allSubscription, err := store.Subscriptions().GetSubscriptionWorker(clazz, opts, "") 459 assert.NoError(t, err) 460 461 var allCounter int32 462 allSemaphore := make(chan bool) 463 464 filteredOptions := &ravendb.SubscriptionCreationOptions{ 465 Query: "from Users where age < 0", 466 } 467 filteredUsersId, err := store.Subscriptions().Create(filteredOptions, "") 468 assert.NoError(t, err) 469 470 { 471 clazz = reflect.TypeOf(map[string]interface{}{}) 472 opts := ravendb.NewSubscriptionWorkerOptions(filteredUsersId) 473 filteredUsersSubscription, err := store.Subscriptions().GetSubscriptionWorker(clazz, opts, "") 474 assert.NoError(t, err) 475 476 usersDocsSemaphore := make(chan bool) 477 478 { 479 session := openSessionMust(t, store) 480 481 for i := 0; i < 500; i++ { 482 err = session.StoreWithID(&User{}, "another/") 483 assert.NoError(t, err) 484 } 485 486 err = session.SaveChanges() 487 assert.NoError(t, err) 488 489 session.Close() 490 } 491 492 results := make(chan *ravendb.SubscriptionBatch, 16) 493 cb := func(batch *ravendb.SubscriptionBatch) error { 494 results <- batch 495 return nil 496 } 497 err = allSubscription.Run(cb) 498 assert.NoError(t, err) 499 500 go func() { 501 for batch := range results { 502 n := len(batch.Items) 503 total := atomic.AddInt32(&allCounter, int32(n)) 504 if total >= 100 { 505 allSemaphore <- true 506 } 507 } 508 }() 509 510 results2 := make(chan *ravendb.SubscriptionBatch, 16) 511 cb2 := func(batch *ravendb.SubscriptionBatch) error { 512 results <- batch 513 return nil 514 } 515 err = filteredUsersSubscription.Run(cb2) 516 assert.NoError(t, err) 517 518 // TODO: more go-ish waiting using select on 2 channels 519 go func() { 520 for range results2 { 521 usersDocsSemaphore <- true 522 } 523 }() 524 525 timedOut := chanWaitTimedOut(allSemaphore, _reasonableWaitTime) 526 assert.False(t, timedOut) 527 timedOut = chanWaitTimedOut(usersDocsSemaphore, time.Millisecond*50) 528 assert.True(t, timedOut) 529 } 530 531 _ = allSubscription.Close() 532 } 533 } 534 535 func subscriptionsBasic_canReleaseSubscription(t *testing.T, driver *RavenTestDriver) { 536 var err error 537 store := driver.getDocumentStoreMust(t) 538 defer store.Close() 539 540 var subscriptionWorker *ravendb.SubscriptionWorker 541 var throwingSubscriptionWorker *ravendb.SubscriptionWorker 542 var notThrowingSubscriptionWorker *ravendb.SubscriptionWorker 543 544 defer func() { 545 if subscriptionWorker != nil { 546 _ = subscriptionWorker.Close() 547 } 548 if throwingSubscriptionWorker != nil { 549 _ = throwingSubscriptionWorker.Close() 550 } 551 if notThrowingSubscriptionWorker != nil { 552 _ = notThrowingSubscriptionWorker.Close() 553 } 554 }() 555 556 opts := &ravendb.SubscriptionCreationOptions{} 557 clazz := reflect.TypeOf(&User{}) 558 id, err := store.Subscriptions().CreateForType(clazz, opts, "") 559 assert.NoError(t, err) 560 561 options1 := ravendb.NewSubscriptionWorkerOptions(id) 562 options1.Strategy = ravendb.SubscriptionOpeningStrategyOpenIfFree 563 clazz = reflect.TypeOf(map[string]interface{}{}) 564 subscriptionWorker, err = store.Subscriptions().GetSubscriptionWorker(clazz, options1, "") 565 assert.NoError(t, err) 566 567 putUserDoc(t, store) 568 569 results := make(chan *ravendb.SubscriptionBatch, 16) 570 cb := func(batch *ravendb.SubscriptionBatch) error { 571 results <- batch 572 return nil 573 } 574 err = subscriptionWorker.Run(cb) 575 assert.NoError(t, err) 576 select { 577 case <-results: 578 // no-op, got a result 579 case <-time.After(_reasonableWaitTime): 580 assert.Fail(t, "timed out waiting for batch") 581 } 582 583 options2 := ravendb.NewSubscriptionWorkerOptions(id) 584 options2.Strategy = ravendb.SubscriptionOpeningStrategyOpenIfFree 585 throwingSubscriptionWorker, err = store.Subscriptions().GetSubscriptionWorker(clazz, options2, "") 586 assert.NoError(t, err) 587 588 cbNil := func(batch *ravendb.SubscriptionBatch) error { 589 return nil 590 } 591 err = throwingSubscriptionWorker.Run(cbNil) 592 err = throwingSubscriptionWorker.WaitUntilFinished(0) 593 _, ok := err.(*ravendb.SubscriptionInUseError) 594 assert.True(t, ok) 595 596 err = store.Subscriptions().DropConnection(id, "") 597 assert.NoError(t, err) 598 599 wopts := ravendb.NewSubscriptionWorkerOptions(id) 600 notThrowingSubscriptionWorker, err = store.Subscriptions().GetSubscriptionWorker(clazz, wopts, "") 601 602 results = make(chan *ravendb.SubscriptionBatch, 16) 603 err = notThrowingSubscriptionWorker.Run(cb) 604 assert.NoError(t, err) 605 putUserDoc(t, store) 606 607 select { 608 case <-results: 609 // no-op, got a result 610 case <-time.After(_reasonableWaitTime): 611 assert.Fail(t, "timed out waiting for batch") 612 } 613 } 614 615 func putUserDoc(t *testing.T, store *ravendb.DocumentStore) { 616 session, err := store.OpenSession("") 617 assert.NoError(t, err) 618 defer session.Close() 619 620 err = session.Store(&User{}) 621 assert.NoError(t, err) 622 err = session.SaveChanges() 623 assert.NoError(t, err) 624 } 625 626 func subscriptionsBasic_shouldPullDocumentsAfterBulkInsert(t *testing.T, driver *RavenTestDriver) { 627 var err error 628 store := driver.getDocumentStoreMust(t) 629 defer store.Close() 630 631 opts := &ravendb.SubscriptionCreationOptions{} 632 id, err := store.Subscriptions().CreateForType(reflect.TypeOf(&User{}), opts, "") 633 assert.NoError(t, err) 634 635 { 636 clazz := reflect.TypeOf(&User{}) 637 wopts := ravendb.NewSubscriptionWorkerOptions(id) 638 subscription, err := store.Subscriptions().GetSubscriptionWorker(clazz, wopts, "") 639 { 640 bulk := store.BulkInsert("") 641 _, err = bulk.Store(&User{}, nil) 642 assert.NoError(t, err) 643 _, err = bulk.Store(&User{}, nil) 644 assert.NoError(t, err) 645 _, err = bulk.Store(&User{}, nil) 646 assert.NoError(t, err) 647 err = bulk.Close() 648 assert.NoError(t, err) 649 } 650 651 results := make(chan *ravendb.SubscriptionBatch, 16) 652 cb := func(batch *ravendb.SubscriptionBatch) error { 653 results <- batch 654 return nil 655 } 656 err = subscription.Run(cb) 657 658 done := false 659 nUsers := 0 660 for !done { 661 select { 662 case batch := <-results: 663 for _, item := range batch.Items { 664 var u *User 665 err := item.GetResult(&u) 666 assert.NoError(t, err) 667 assert.NotNil(t, u) 668 nUsers++ 669 if nUsers >= 2 { 670 done = true 671 } 672 } 673 case <-time.After(_reasonableWaitTime): 674 done = true 675 assert.Fail(t, "timed out waiting for batch") 676 } 677 } 678 679 err = subscription.Close() 680 assert.NoError(t, err) 681 } 682 } 683 684 func subscriptionsBasic_shouldStopPullingDocsAndCloseSubscriptionOnSubscriberErrorByDefault(t *testing.T, driver *RavenTestDriver) { 685 var err error 686 store := driver.getDocumentStoreMust(t) 687 defer store.Close() 688 689 opts := &ravendb.SubscriptionCreationOptions{} 690 id, err := store.Subscriptions().CreateForType(reflect.TypeOf(&User{}), opts, "") 691 assert.NoError(t, err) 692 693 { 694 clazz := reflect.TypeOf(map[string]interface{}{}) 695 wopts := ravendb.NewSubscriptionWorkerOptions(id) 696 subscription, err := store.Subscriptions().GetSubscriptionWorker(clazz, wopts, "") 697 698 putUserDoc(t, store) 699 700 cb := func(batch *ravendb.SubscriptionBatch) error { 701 return errors.New("Fake error") 702 } 703 err = subscription.Run(cb) 704 assert.NoError(t, err) 705 706 err = subscription.WaitUntilFinished(_reasonableWaitTime) 707 _, ok := err.(*ravendb.SubscriberErrorError) 708 assert.True(t, ok) 709 assert.NotNil(t, subscription.Err()) 710 711 res, err := store.Subscriptions().GetSubscriptions(0, 1, "") 712 assert.NoError(t, err) 713 subscriptionConfig := res[0] 714 assert.Nil(t, subscriptionConfig.ChangeVectorForNextBatchStartingPoint) 715 716 err = subscription.Close() 717 assert.NoError(t, err) 718 } 719 } 720 721 func subscriptionsBasic_canSetToIgnoreSubscriberErrors(t *testing.T, driver *RavenTestDriver) { 722 var err error 723 store := driver.getDocumentStoreMust(t) 724 defer store.Close() 725 726 opts := &ravendb.SubscriptionCreationOptions{} 727 id, err := store.Subscriptions().CreateForType(reflect.TypeOf(&User{}), opts, "") 728 assert.NoError(t, err) 729 730 options1 := ravendb.NewSubscriptionWorkerOptions(id) 731 options1.IgnoreSubscriberErrors = true 732 733 { 734 clazz := reflect.TypeOf(&User{}) 735 subscription, err := store.Subscriptions().GetSubscriptionWorker(clazz, options1, "") 736 assert.NoError(t, err) 737 738 putUserDoc(t, store) 739 putUserDoc(t, store) 740 741 results := make(chan *ravendb.SubscriptionBatch, 16) 742 cb := func(batch *ravendb.SubscriptionBatch) error { 743 results <- batch 744 return errors.New("Fake error") 745 } 746 err = subscription.Run(cb) 747 assert.NoError(t, err) 748 749 done := false 750 nUsers := 0 751 for !done { 752 select { 753 case batch := <-results: 754 for _, item := range batch.Items { 755 var u *User 756 err := item.GetResult(&u) 757 assert.NoError(t, err) 758 assert.NotNil(t, u) 759 nUsers++ 760 if nUsers >= 2 { 761 done = true 762 } 763 } 764 case <-time.After(_reasonableWaitTime): 765 assert.Fail(t, "timed out waiting for batch") 766 done = true 767 } 768 } 769 _ = subscription.Close() 770 err = subscription.WaitUntilFinished(0) 771 assert.NoError(t, err) 772 773 // nno error because we asked to ignore errors 774 assert.NoError(t, subscription.Err()) 775 776 err = subscription.Close() 777 assert.NoError(t, err) 778 } 779 } 780 781 func subscriptionsBasic_ravenDB_3452_ShouldStopPullingDocsIfReleased(t *testing.T, driver *RavenTestDriver) { 782 var err error 783 store := driver.getDocumentStoreMust(t) 784 defer store.Close() 785 786 opts := &ravendb.SubscriptionCreationOptions{} 787 id, err := store.Subscriptions().CreateForType(reflect.TypeOf(&User{}), opts, "") 788 assert.NoError(t, err) 789 790 { 791 options1 := ravendb.NewSubscriptionWorkerOptions(id) 792 options1.TimeToWaitBeforeConnectionRetry = ravendb.Duration(time.Second) 793 794 clazz := reflect.TypeOf(&User{}) 795 subscription, err := store.Subscriptions().GetSubscriptionWorker(clazz, options1, "") 796 assert.NoError(t, err) 797 798 { 799 session, err := store.OpenSession("") 800 assert.NoError(t, err) 801 err = session.StoreWithID(&User{}, "users/1") 802 assert.NoError(t, err) 803 err = session.StoreWithID(&User{}, "users/2") 804 assert.NoError(t, err) 805 err = session.SaveChanges() 806 assert.NoError(t, err) 807 808 session.Close() 809 } 810 811 results := make(chan *ravendb.SubscriptionBatch, 16) 812 cb := func(batch *ravendb.SubscriptionBatch) error { 813 results <- batch 814 return nil 815 } 816 err = subscription.Run(cb) 817 assert.NoError(t, err) 818 819 done := false 820 nUsers := 0 821 for !done { 822 select { 823 case batch := <-results: 824 for _, item := range batch.Items { 825 var u *User 826 err := item.GetResult(&u) 827 assert.NoError(t, err) 828 assert.NotNil(t, u) 829 nUsers++ 830 if nUsers >= 2 { 831 done = true 832 } 833 } 834 case <-time.After(_reasonableWaitTime): 835 assert.Fail(t, "timed out waiting for batch") 836 done = true 837 } 838 } 839 840 err = store.Subscriptions().DropConnection(id, "") 841 assert.NoError(t, err) 842 843 // this can exit normally or throw on drop connection 844 // depending on exactly where the drop happens 845 err = subscription.WaitUntilFinished(_reasonableWaitTime) 846 if err != nil { 847 _, ok := err.(*ravendb.SubscriptionClosedError) 848 assert.True(t, ok) 849 } 850 851 { 852 session, err := store.OpenSession("") 853 assert.NoError(t, err) 854 err = session.StoreWithID(&User{}, "users/3") 855 assert.NoError(t, err) 856 err = session.StoreWithID(&User{}, "users/4") 857 assert.NoError(t, err) 858 err = session.SaveChanges() 859 assert.NoError(t, err) 860 861 session.Close() 862 } 863 864 // should get no results since we dropped the connection 865 866 select { 867 case batch := <-results: 868 // if we get it, it should be nil because we receive 869 // from closed channel 870 assert.Nil(t, batch) 871 case <-time.After(50 * time.Millisecond): 872 // no-op, timeing out is also valid 873 } 874 875 assert.True(t, subscription.IsDone()) 876 877 err = subscription.Close() 878 assert.NoError(t, err) 879 } 880 } 881 882 func subscriptionsBasic_ravenDB_3453_ShouldDeserializeTheWholeDocumentsAfterTypedSubscription(t *testing.T, driver *RavenTestDriver) { 883 var err error 884 store := driver.getDocumentStoreMust(t) 885 defer store.Close() 886 887 opts := &ravendb.SubscriptionCreationOptions{} 888 id, err := store.Subscriptions().CreateForType(reflect.TypeOf(&User{}), opts, "") 889 assert.NoError(t, err) 890 891 { 892 clazz := reflect.TypeOf(&User{}) 893 wopts := ravendb.NewSubscriptionWorkerOptions(id) 894 895 subscription, err := store.Subscriptions().GetSubscriptionWorker(clazz, wopts, "") 896 assert.NoError(t, err) 897 898 var users []*User 899 { 900 session, err := store.OpenSession("") 901 assert.NoError(t, err) 902 u := &User{Age: 31} 903 err = session.StoreWithID(u, "users/1") 904 users = append(users, u) 905 assert.NoError(t, err) 906 u = &User{Age: 27} 907 err = session.StoreWithID(u, "users/12") 908 users = append(users, u) 909 assert.NoError(t, err) 910 u = &User{Age: 25} 911 err = session.StoreWithID(u, "users/3") 912 users = append(users, u) 913 assert.NoError(t, err) 914 err = session.SaveChanges() 915 assert.NoError(t, err) 916 917 session.Close() 918 } 919 920 results := make(chan *ravendb.SubscriptionBatch, 16) 921 cb := func(batch *ravendb.SubscriptionBatch) error { 922 results <- batch 923 return nil 924 } 925 err = subscription.Run(cb) 926 assert.NoError(t, err) 927 928 n := 0 929 done := false 930 for !done { 931 select { 932 case batch := <-results: 933 for _, item := range batch.Items { 934 var u *User 935 err := item.GetResult(&u) 936 assert.NoError(t, err) 937 expU := users[n] 938 assert.Equal(t, u.ID, expU.ID) 939 assert.Equal(t, u.Age, expU.Age) 940 n++ 941 if n >= len(users) { 942 done = true 943 } 944 } 945 946 case <-time.After(_reasonableWaitTime): 947 done = true 948 assert.Fail(t, "timed out waiting for batch") 949 } 950 951 err = subscription.Close() 952 assert.NoError(t, err) 953 } 954 } 955 } 956 957 func subscriptionsBasic_disposingOneSubscriptionShouldNotAffectOnNotificationsOfOthers(t *testing.T, driver *RavenTestDriver) { 958 var err error 959 store := driver.getDocumentStoreMust(t) 960 defer store.Close() 961 962 var subscription1 *ravendb.SubscriptionWorker 963 var subscription2 *ravendb.SubscriptionWorker 964 defer func() { 965 if subscription1 != nil { 966 _ = subscription1.Close() 967 } 968 if subscription2 != nil { 969 _ = subscription2.Close() 970 } 971 }() 972 973 id1, err := store.Subscriptions().CreateForType(reflect.TypeOf(&User{}), nil, "") 974 assert.NoError(t, err) 975 id2, err := store.Subscriptions().CreateForType(reflect.TypeOf(&User{}), nil, "") 976 assert.NoError(t, err) 977 978 { 979 session, err := store.OpenSession("") 980 assert.NoError(t, err) 981 err = session.StoreWithID(&User{}, "users/1") 982 assert.NoError(t, err) 983 err = session.StoreWithID(&User{}, "users/2") 984 assert.NoError(t, err) 985 err = session.SaveChanges() 986 assert.NoError(t, err) 987 988 session.Close() 989 } 990 991 clazz := reflect.TypeOf(&User{}) 992 opts := ravendb.NewSubscriptionWorkerOptions(id1) 993 994 subscription1, err = store.Subscriptions().GetSubscriptionWorker(clazz, opts, "") 995 assert.NoError(t, err) 996 997 items1 := make(chan *User, 10) 998 999 results := make(chan *ravendb.SubscriptionBatch, 16) 1000 cb := func(batch *ravendb.SubscriptionBatch) error { 1001 results <- batch 1002 return nil 1003 } 1004 err = subscription1.Run(cb) 1005 assert.NoError(t, err) 1006 1007 // TODO: rewrite in a more go-ish way 1008 go func() { 1009 for batch := range results { 1010 for _, item := range batch.Items { 1011 var u *User 1012 err := item.GetResult(&u) 1013 assert.NoError(t, err) 1014 items1 <- u 1015 } 1016 } 1017 }() 1018 1019 opts = ravendb.NewSubscriptionWorkerOptions(id2) 1020 subscription2, err = store.Subscriptions().GetSubscriptionWorker(clazz, opts, "") 1021 assert.NoError(t, err) 1022 items2 := make(chan *User, 10) 1023 1024 results2 := make(chan *ravendb.SubscriptionBatch, 16) 1025 cb2 := func(batch *ravendb.SubscriptionBatch) error { 1026 results2 <- batch 1027 return nil 1028 } 1029 err = subscription2.Run(cb2) 1030 assert.NoError(t, err) 1031 go func() { 1032 for batch := range results2 { 1033 for _, item := range batch.Items { 1034 var u *User 1035 err := item.GetResult(&u) 1036 assert.NoError(t, err) 1037 items2 <- u 1038 } 1039 } 1040 }() 1041 1042 u, ok := getNextUser(items1, 0) 1043 assert.True(t, ok) 1044 assert.Equal(t, u.ID, "users/1") 1045 1046 u, ok = getNextUser(items1, 0) 1047 assert.True(t, ok) 1048 assert.Equal(t, u.ID, "users/2") 1049 1050 u, ok = getNextUser(items2, 0) 1051 assert.True(t, ok) 1052 assert.Equal(t, u.ID, "users/1") 1053 1054 u, ok = getNextUser(items2, 0) 1055 assert.True(t, ok) 1056 assert.Equal(t, u.ID, "users/2") 1057 1058 _ = subscription1.Close() 1059 subscription1 = nil 1060 1061 { 1062 session, err := store.OpenSession("") 1063 assert.NoError(t, err) 1064 err = session.StoreWithID(&User{}, "users/3") 1065 assert.NoError(t, err) 1066 err = session.StoreWithID(&User{}, "users/4") 1067 assert.NoError(t, err) 1068 err = session.SaveChanges() 1069 assert.NoError(t, err) 1070 1071 session.Close() 1072 } 1073 1074 u, ok = getNextUser(items2, 0) 1075 assert.True(t, ok) 1076 assert.Equal(t, u.ID, "users/3") 1077 1078 u, ok = getNextUser(items2, 0) 1079 assert.True(t, ok) 1080 assert.Equal(t, u.ID, "users/4") 1081 } 1082 1083 func TestSubscriptionsBasic(t *testing.T) { 1084 driver := createTestDriver(t) 1085 destroy := func() { destroyDriver(t, driver) } 1086 defer recoverTest(t, destroy) 1087 1088 // matches order of Java tests 1089 subscriptionsBasic_canReleaseSubscription(t, driver) 1090 subscriptionsBasic_shouldRespectMaxDocCountInBatch(t, driver) 1091 subscriptionsBasic_shouldStreamAllDocumentsAfterSubscriptionCreation(t, driver) 1092 subscriptionsBasic_shouldRespectCollectionCriteria(t, driver) 1093 subscriptionsBasic_willAcknowledgeEmptyBatches(t, driver) 1094 1095 // subscriptionsBasic_shouldStopPullingDocsAndCloseSubscriptionOnSubscriberErrorByDefault(t, driver) 1096 1097 subscriptionsBasic_disposingOneSubscriptionShouldNotAffectOnNotificationsOfOthers(t, driver) 1098 subscriptionsBasic_shouldPullDocumentsAfterBulkInsert(t, driver) 1099 //subscriptionsBasic_canSetToIgnoreSubscriberErrors(t, driver) 1100 subscriptionsBasic_ravenDB_3452_ShouldStopPullingDocsIfReleased(t, driver) 1101 subscriptionsBasic_canDeleteSubscription(t, driver) 1102 1103 subscriptionsBasic_shouldThrowOnAttemptToOpenAlreadyOpenedSubscription(t, driver) 1104 1105 subscriptionsBasic_shouldThrowWhenOpeningNoExistingSubscription(t, driver) 1106 subscriptionsBasic_shouldSendAllNewAndModifiedDocs(t, driver) 1107 subscriptionsBasic_ravenDB_3453_ShouldDeserializeTheWholeDocumentsAfterTypedSubscription(t, driver) 1108 }