@Override @Nullable public T get() { return this.processor.block(); }
@Override @Nullable public T get(long timeout, TimeUnit unit) { Assert.notNull(unit, "TimeUnit must not be null"); Duration duration = Duration.ofMillis(TimeUnit.MILLISECONDS.convert(timeout, unit)); return this.processor.block(duration); }
@Override @Nullable public T get() { return this.processor.block(); }
@Override @Nullable public T get(long timeout, TimeUnit unit) { Assert.notNull(unit, "TimeUnit must not be null"); Duration duration = Duration.ofMillis(TimeUnit.MILLISECONDS.convert(timeout, unit)); return this.processor.block(duration); }
/** * Block the calling thread indefinitely, waiting for the completion of this {@code MonoProcessor}. If the * {@link MonoProcessor} is completed with an error a RuntimeException that wraps the error is thrown. * * @return the value of this {@code MonoProcessor} */ @Override @Nullable public O block() { return block(WaitStrategy.NOOP_SPIN_OBSERVER); }
@SuppressWarnings("unchecked") @Override protected <T> T getValue(int index) { if (subscriptions.get(index) != null) { return (T) subscriptions.get(index).block(); } return super.getValue(index); }
@SuppressWarnings("unchecked") @Override protected <T> T getValue(int index) { if (subscriptions.get(index) != null) { return (T) subscriptions.get(index).block(); } return super.getValue(index); }
@Test(expected = IllegalStateException.class) public void MonoProcessorResultNotAvailable() { MonoProcessor<String> mp = MonoProcessor.create(); mp.block(Duration.ofMillis(1)); }
@Test public void monoProcessorBlockIsUnbounded() { long start = System.nanoTime(); String result = Mono.just("foo") .delayElement(Duration.ofMillis(500)) .toProcessor() .block(); assertThat(result).isEqualTo("foo"); assertThat(Duration.ofNanos(System.nanoTime() - start)) .isGreaterThanOrEqualTo(Duration.ofMillis(500)); }
@Test public void customHeader() throws Exception { HttpHeaders headers = new HttpHeaders(); headers.add("my-header", "my-value"); MonoProcessor<Object> output = MonoProcessor.create(); this.client.execute(getUrl("/custom-header"), headers, session -> session.receive() .map(WebSocketMessage::getPayloadAsText) .subscribeWith(output) .then()) .block(TIMEOUT); assertEquals("my-header:my-value", output.block(TIMEOUT)); }
@Test public void monoProcessorBlockNegativeIsImmediateTimeout() { long start = System.nanoTime(); assertThatExceptionOfType(IllegalStateException.class) .isThrownBy(() -> Mono.just("foo") .delayElement(Duration.ofMillis(500)) .toProcessor() .block(Duration.ofSeconds(-1))) .withMessage("Timeout on Mono blocking read"); assertThat(Duration.ofNanos(System.nanoTime() - start)) .isLessThan(Duration.ofMillis(500)); }
@Test public void fluxCanBeEnforcedToDispatchValuesWithKeysDistinctFromPredecessors() { // "A Flux can be enforced to dispatch values with keys distinct from their immediate predecessors keys" // given:"a composable with values 1 to 5 with duplicate keys" Flux<Integer> s = Flux.fromIterable(Arrays.asList(2, 4, 3, 5, 2, 5)); // when:"the values are filtered and result is collected" MonoProcessor<List<Integer>> tap = s.distinctUntilChanged(it -> it % 2 == 0) .collectList() .toProcessor(); // then:"collected must remove duplicates" assertThat(tap.block()).containsExactly(2, 3, 2, 5); }
@Test public void monoProcessorBlockZeroIsImmediateTimeout() { long start = System.nanoTime(); assertThatExceptionOfType(IllegalStateException.class) .isThrownBy(() -> Mono.just("foo") .delayElement(Duration.ofMillis(500)) .toProcessor() .block(Duration.ZERO)) .withMessage("Timeout on Mono blocking read"); assertThat(Duration.ofNanos(System.nanoTime() - start)) .isLessThan(Duration.ofMillis(500)); }
@Test public void fluxCanBeEnforcedToDispatchValuesDistinctFromPredecessors() { // "A Flux can be enforced to dispatch values distinct from their immediate predecessors" // given:"a composable with values 1 to 3 with duplicates" Flux<Integer> s = Flux.fromIterable(Arrays.asList(1, 1, 2, 2, 3)); // when:"the values are filtered and result is collected" MonoProcessor<List<Integer>> tap = s.distinctUntilChanged() .collectList() .toProcessor(); tap.subscribe(); // then:"collected must remove duplicates" assertThat(tap.block()).containsExactly(1, 2, 3); }
@Test public void fluxCanBeEnforcedToDispatchDistinctValues() { // "A Flux can be enforced to dispatch distinct values" // given:"a composable with values 1 to 4 with duplicates" Flux<Integer> s = Flux.fromIterable(Arrays.asList(1, 2, 3, 1, 2, 3, 4)); // when:"the values are filtered and result is collected" MonoProcessor<List<Integer>> tap = s.distinct() .collectList() .toProcessor(); tap.subscribe(); // then:"collected should be without duplicates" assertThat(tap.block()).containsExactly(1, 2, 3, 4); }
@Test public void fluxCanBeEnforcedToDispatchValuesHavingDistinctKeys() { // "A Flux can be enforced to dispatch values having distinct keys" // given: "a composable with values 1 to 4 with duplicate keys" Flux<Integer> s = Flux.fromIterable(Arrays.asList(1, 2, 3, 1, 2, 3, 4)); // when: "the values are filtered and result is collected" MonoProcessor<List<Integer>> tap = s.distinct(it -> it % 3) .collectList() .toProcessor(); tap.subscribe(); // then: "collected should be without duplicates" assertThat(tap.block()).containsExactly(1, 2, 3); }
@Test // SPR-16494 @Ignore // https://github.com/reactor/reactor-netty/issues/283 public void serverDetectsClientDisconnect() { assumeTrue(this.server instanceof ReactorHttpServer); Flux<String> result = this.webClient.get() .uri("/infinite") .accept(TEXT_EVENT_STREAM) .retrieve() .bodyToFlux(String.class); StepVerifier.create(result) .expectNext("foo 0") .expectNext("foo 1") .thenCancel() .verify(Duration.ofSeconds(5L)); SseController controller = this.wac.getBean(SseController.class); controller.cancellation.block(Duration.ofSeconds(5)); }
@Test public void reduceWillAccumulateListOfAcceptedValues() { // "Reduce will accumulate a list of accepted values" // given: "a composable" FluxProcessor<Integer, Integer> source = EmitterProcessor.create(); Mono<List<Integer>> reduced = source.collectList(); MonoProcessor<List<Integer>> value = reduced.toProcessor(); value.subscribe(); // when: "the first value is accepted" source.onNext(1); source.onComplete(); // then: "the list contains the first element" assertThat(value.block()).containsExactly(1); }
@Test public void subProtocol() throws Exception { String protocol = "echo-v1"; AtomicReference<HandshakeInfo> infoRef = new AtomicReference<>(); MonoProcessor<Object> output = MonoProcessor.create(); this.client.execute(getUrl("/sub-protocol"), new WebSocketHandler() { @Override public List<String> getSubProtocols() { return Collections.singletonList(protocol); } @Override public Mono<Void> handle(WebSocketSession session) { infoRef.set(session.getHandshakeInfo()); return session.receive() .map(WebSocketMessage::getPayloadAsText) .subscribeWith(output) .then(); } }) .block(TIMEOUT); HandshakeInfo info = infoRef.get(); assertThat(info.getHeaders().getFirst("Upgrade"), Matchers.equalToIgnoringCase("websocket")); assertEquals(protocol, info.getHeaders().getFirst("Sec-WebSocket-Protocol")); assertEquals("Wrong protocol accepted", protocol, info.getSubProtocol()); assertEquals("Wrong protocol detected on the server side", protocol, output.block(TIMEOUT)); }
@Test public void promiseAcceptCountCannotExceedOne() { MonoProcessor<Object> deferred = MonoProcessor.create(); deferred.onNext("alpha"); try { deferred.onNext("bravo"); } catch (Exception e) { if(!Exceptions.isCancel(e)) { throw e; } } assertEquals(deferred.block(), "alpha"); }