|
7 | 7 | import static de.bwaldvogel.mongo.backend.TestUtils.json; |
8 | 8 | import static de.bwaldvogel.mongo.backend.TestUtils.toArray; |
9 | 9 | import static java.util.Collections.singletonList; |
| 10 | +import static org.assertj.core.groups.Tuple.tuple; |
10 | 11 | import static org.junit.jupiter.api.Assertions.assertThrows; |
11 | 12 |
|
12 | 13 | import java.time.Duration; |
13 | 14 | import java.time.Instant; |
| 15 | +import java.util.AbstractMap; |
14 | 16 | import java.util.ArrayList; |
15 | 17 | import java.util.Arrays; |
16 | 18 | import java.util.Date; |
17 | 19 | import java.util.List; |
| 20 | +import java.util.Map; |
18 | 21 | import java.util.NoSuchElementException; |
19 | 22 | import java.util.UUID; |
| 23 | +import java.util.concurrent.TimeUnit; |
| 24 | +import java.util.stream.IntStream; |
20 | 25 |
|
| 26 | +import org.assertj.core.api.Assertions; |
21 | 27 | import org.bson.BsonDocument; |
22 | 28 | import org.bson.BsonInt32; |
23 | 29 | import org.bson.BsonTimestamp; |
|
39 | 45 | import com.mongodb.reactivestreams.client.Success; |
40 | 46 |
|
41 | 47 | import de.bwaldvogel.mongo.oplog.OperationType; |
| 48 | +import io.reactivex.Flowable; |
| 49 | +import io.reactivex.schedulers.Schedulers; |
42 | 50 | import io.reactivex.subscribers.TestSubscriber; |
43 | 51 |
|
44 | 52 | public abstract class AbstractOplogTest extends AbstractTest { |
@@ -425,4 +433,67 @@ public void testSimpleChangeStreamWithFilter() throws Exception { |
425 | 433 | assertThat(streamSubscriber.values().get(0).getFullDocument().get("bu")).isEqualTo("abc"); |
426 | 434 | } |
427 | 435 |
|
| 436 | + @Test |
| 437 | + @Disabled |
| 438 | + public void testMultipleChangeStreams() throws InterruptedException { |
| 439 | + Flowable.fromPublisher(asyncCollection.insertOne(json("_id: 1"))) |
| 440 | + .test().awaitDone(5, TimeUnit.SECONDS).assertComplete(); |
| 441 | + |
| 442 | + final int changeStreamCount = 32; |
| 443 | + |
| 444 | + List<Bson> pipeline = singletonList(match(Filters.eq("fullDocument.bu", "abc"))); |
| 445 | + |
| 446 | + final TestSubscriber<Map<Integer, List<ChangeStreamDocument<Document>>>> streamSubscriber |
| 447 | + = new TestSubscriber<>(); |
| 448 | + |
| 449 | + Flowable.range(1, changeStreamCount) |
| 450 | + .flatMapSingle(index -> { |
| 451 | + return Flowable.fromPublisher(asyncCollection.watch(pipeline)) |
| 452 | + .take(2) |
| 453 | + .toList() |
| 454 | + .map(changeStreamDocuments -> { |
| 455 | + return new AbstractMap.SimpleEntry<>(index, changeStreamDocuments); |
| 456 | + }) |
| 457 | + .subscribeOn(Schedulers.io()); // subscribe to change streams concurrently |
| 458 | + }) |
| 459 | + .toMap(Map.Entry::getKey, Map.Entry::getValue) |
| 460 | + .toFlowable() |
| 461 | + .subscribe(streamSubscriber); |
| 462 | + |
| 463 | + // give time for all ChangeStream Publishers to be subscribed to |
| 464 | + // todo: expose API to get cursors from Backend and wait until 'changeStreamCount' cursors |
| 465 | + TimeUnit.SECONDS.sleep(5); |
| 466 | + |
| 467 | + Flowable.concat( |
| 468 | + Flowable.fromPublisher(asyncCollection.insertOne(json("_id: 2, bu: 'abc"))), |
| 469 | + Flowable.fromPublisher(asyncCollection.insertOne(json("_id: 3, bu: 'xyz"))), |
| 470 | + Flowable.fromPublisher(asyncCollection.insertOne(json("_id: 4, bu: 'abc"))) |
| 471 | + ).test().awaitDone(5, TimeUnit.SECONDS).assertComplete(); |
| 472 | + |
| 473 | + final Map<Integer, List<ChangeStreamDocument<Document>>> results = streamSubscriber |
| 474 | + .awaitDone(15, TimeUnit.SECONDS) |
| 475 | + .assertComplete() |
| 476 | + .assertValueCount(1) |
| 477 | + .values().get(0); |
| 478 | + |
| 479 | + Assertions.assertThat(IntStream.rangeClosed(1, changeStreamCount)) |
| 480 | + .allSatisfy(index -> { |
| 481 | + Assertions.assertThat(results).containsKey(index); |
| 482 | + |
| 483 | + final List<ChangeStreamDocument<Document>> emits = results.get(index); |
| 484 | + Assertions.assertThat(emits).isNotNull() |
| 485 | + .extracting( |
| 486 | + document -> { |
| 487 | + return document.getDocumentKey().getInt32("_id").getValue(); |
| 488 | + }, |
| 489 | + document -> { |
| 490 | + return document.getFullDocument() != null |
| 491 | + ? document.getFullDocument().getString("bu") |
| 492 | + : null; |
| 493 | + } |
| 494 | + ) |
| 495 | + .containsExactly(tuple(2, "abc"), tuple(4, "abc")); |
| 496 | + }); |
| 497 | + } |
| 498 | + |
428 | 499 | } |
0 commit comments