use of reactor.core.Disposable in project spring-data-mongodb by spring-projects.
the class ReactiveMongoTemplateTests method changeStreamEventsShouldBeFilteredCorrectly.
// DATAMONGO-1803
@Test
@Disabled("Heavily relying on timing assumptions. Cannot test message resumption properly. Too much race for too little time in between.")
@EnableIfReplicaSetAvailable
void changeStreamEventsShouldBeFilteredCorrectly() throws InterruptedException {
template.createCollection(Person.class).as(StepVerifier::create).expectNextCount(1).verifyComplete();
BlockingQueue<ChangeStreamEvent<Person>> documents = new LinkedBlockingQueue<>(100);
Disposable disposable = template.changeStream("person", ChangeStreamOptions.builder().filter(newAggregation(Person.class, match(where("age").gte(38)))).build(), Person.class).doOnNext(documents::add).subscribe();
// just give it some time to link to the collection.
Thread.sleep(500);
Person person1 = new Person("Spring", 38);
Person person2 = new Person("Data", 37);
Person person3 = new Person("MongoDB", 39);
//
Flux.merge(template.save(person1), template.save(person2), template.save(person3)).as(//
StepVerifier::create).expectNextCount(//
3).verifyComplete();
// just give it some time to link receive all events
Thread.sleep(500);
try {
assertThat(documents.stream().map(ChangeStreamEvent::getBody).collect(Collectors.toList())).containsExactly(person1, person3);
} finally {
disposable.dispose();
}
}
use of reactor.core.Disposable in project spring-data-mongodb by spring-projects.
the class ReactiveMongoTemplateTests method resumesAtTimestampCorrectly.
// DATAMONGO-2012, DATAMONGO-2113
@Test
@EnableIfMongoServerVersion(isGreaterThanEqual = "4.0")
@EnableIfReplicaSetAvailable
void resumesAtTimestampCorrectly() throws InterruptedException {
template.dropCollection(Person.class).onErrorResume(it -> Mono.empty()).as(StepVerifier::create).verifyComplete();
template.createCollection(Person.class).as(StepVerifier::create).expectNextCount(1).verifyComplete();
BlockingQueue<ChangeStreamEvent<Person>> documents = new LinkedBlockingQueue<>(100);
Disposable disposable = template.changeStream("person", ChangeStreamOptions.empty(), Person.class).doOnNext(documents::add).subscribe();
// just give it some time to link to the collection.
Thread.sleep(500);
Person person1 = new Person("Spring", 38);
Person person2 = new Person("Data", 37);
Person person3 = new Person("MongoDB", 39);
//
template.save(person1).delayElement(Duration.ofSeconds(1)).as(//
StepVerifier::create).expectNextCount(//
1).verifyComplete();
//
template.save(person2).as(//
StepVerifier::create).expectNextCount(//
1).verifyComplete();
// just give it some time to link receive all events
Thread.sleep(500);
disposable.dispose();
// skip first
documents.take();
// take 2nd
Instant resumeAt = documents.take().getTimestamp();
template.save(person3).as(StepVerifier::create).expectNextCount(1).verifyComplete();
BlockingQueue<ChangeStreamEvent<Person>> resumeDocuments = new LinkedBlockingQueue<>(100);
template.changeStream("person", ChangeStreamOptions.builder().resumeAt(resumeAt).build(), Person.class).doOnNext(resumeDocuments::add).subscribe();
// just give it some time to link receive all events
Thread.sleep(500);
try {
assertThat(resumeDocuments.stream().map(ChangeStreamEvent::getBody).collect(Collectors.toList())).containsExactly(person2, person3);
} finally {
disposable.dispose();
}
}
use of reactor.core.Disposable in project spring-data-mongodb by spring-projects.
the class ReactiveChangeStreamOperationSupportTests method changeStreamEventsShouldBeConvertedCorrectly.
// DATAMONGO-1803
@Test
@EnableIfMongoServerVersion(isGreaterThanEqual = "4.0")
public void changeStreamEventsShouldBeConvertedCorrectly() throws InterruptedException {
BlockingQueue<ChangeStreamEvent<Person>> documents = new LinkedBlockingQueue<>(100);
Disposable disposable = //
template.changeStream(Person.class).listen().doOnNext(documents::add).subscribe();
// just give it some time to link to the collection.
Thread.sleep(500);
Person person1 = new Person("Spring", 38);
Person person2 = new Person("Data", 39);
Person person3 = new Person("MongoDB", 37);
Flux.merge(template.insert(person1).delayElement(Duration.ofMillis(2)), template.insert(person2).delayElement(Duration.ofMillis(2)), //
template.insert(person3).delayElement(Duration.ofMillis(2))).as(//
StepVerifier::create).expectNextCount(//
3).verifyComplete();
// just give it some time to link receive all events
Thread.sleep(500);
try {
assertThat(documents.stream().map(ChangeStreamEvent::getBody).collect(Collectors.toList())).containsOnly(person1, person2, person3);
} finally {
disposable.dispose();
}
}
use of reactor.core.Disposable in project spring-data-mongodb by spring-projects.
the class ReactiveMongoRepositoryTests method shouldUseTailableCursor.
// DATAMONGO-1444
@Test
void shouldUseTailableCursor() throws Exception {
//
template.dropCollection(Capped.class).then(//
template.createCollection(//
Capped.class, CollectionOptions.empty().size(1000).maxDocuments(100).capped())).as(//
StepVerifier::create).expectNextCount(//
1).verifyComplete();
template.insert(new Capped("value", Math.random())).as(StepVerifier::create).expectNextCount(1).verifyComplete();
BlockingQueue<Capped> documents = new LinkedBlockingDeque<>(100);
Disposable disposable = cappedRepository.findByKey("value").doOnNext(documents::add).subscribe();
assertThat(documents.poll(5, TimeUnit.SECONDS)).isNotNull();
template.insert(new Capped("value", Math.random())).as(StepVerifier::create).expectNextCount(1).verifyComplete();
assertThat(documents.poll(5, TimeUnit.SECONDS)).isNotNull();
assertThat(documents).isEmpty();
disposable.dispose();
}
use of reactor.core.Disposable in project reactor-core by reactor.
the class FluxPublishOnTest method mapNotifiesOnce.
/**
* See #294 the consumer received more or less calls than expected Better reproducible
* with big thread pools, e.g. 128 threads
*
* @throws InterruptedException on interrupt
*/
@Test
public void mapNotifiesOnce() throws InterruptedException {
final int COUNT = 10000;
final Object internalLock = new Object();
final Object consumerLock = new Object();
final CountDownLatch internalLatch = new CountDownLatch(COUNT);
final CountDownLatch consumerLatch = new CountDownLatch(COUNT);
final AtomicInteger internalCounter = new AtomicInteger(0);
final AtomicInteger consumerCounter = new AtomicInteger(0);
final ConcurrentHashMap<Object, Long> seenInternal = new ConcurrentHashMap<>();
final ConcurrentHashMap<Object, Long> seenConsumer = new ConcurrentHashMap<>();
Sinks.Many<Integer> s = Sinks.many().multicast().onBackpressureBuffer();
Flux<Integer> d = s.asFlux();
/*Disposable c = */
d.publishOn(Schedulers.parallel()).parallel(8).groups().subscribe(stream -> stream.publishOn(Schedulers.parallel()).map(o -> {
synchronized (internalLock) {
internalCounter.incrementAndGet();
long curThreadId = Thread.currentThread().getId();
Long prevThreadId = seenInternal.put(o, curThreadId);
if (prevThreadId != null) {
fail(String.format("The object %d has already been seen internally on the thread %d, current thread %d", o, prevThreadId, curThreadId));
}
internalLatch.countDown();
}
return -o;
}).subscribe(o -> {
synchronized (consumerLock) {
consumerCounter.incrementAndGet();
long curThreadId = Thread.currentThread().getId();
Long prevThreadId = seenConsumer.put(o, curThreadId);
if (prevThreadId != null) {
fail(String.format("The object %d has already been seen by the consumer on the thread %d, current thread %d", o, prevThreadId, curThreadId));
}
consumerLatch.countDown();
}
}));
final long start = System.currentTimeMillis();
for (int i = 0; i < COUNT; i++) {
long busyLoops = 0;
while (s.tryEmitNext(i).isFailure()) {
busyLoops++;
if (busyLoops % 5000 == 0 && System.currentTimeMillis() - start >= 10_0000) {
throw new RuntimeException("Busy loop timed out");
}
}
}
internalLatch.await(5, TimeUnit.SECONDS);
assertThat(internalCounter).as("after 5s").hasValue(COUNT);
consumerLatch.await(5, TimeUnit.SECONDS);
assertThat(internalCounter).as("after 10s").hasValue(COUNT);
}
Aggregations