Java Code Examples for reactor.core.publisher.Flux#concatMap()

The following examples show how to use reactor.core.publisher.Flux#concatMap() . These examples are extracted from open source projects. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source Project: reactor-core   File: RetrySpec.java    License: Apache License 2.0 6 votes vote down vote up
@Override
public Flux<Long> generateCompanion(Flux<RetrySignal> flux) {
	return flux.concatMap(retryWhenState -> {
		//capture the state immediately
		RetrySignal copy = retryWhenState.copy();
		Throwable currentFailure = copy.failure();
		long iteration = isTransientErrors ? copy.totalRetriesInARow() : copy.totalRetries();

		if (currentFailure == null) {
			return Mono.error(new IllegalStateException("RetryWhenState#failure() not expected to be null"));
		}
		else if (!errorFilter.test(currentFailure)) {
			return Mono.error(currentFailure);
		}
		else if (iteration >= maxAttempts) {
			return Mono.error(retryExhaustedGenerator.apply(this, copy));
		}
		else {
			return applyHooks(copy, Mono.just(iteration), doPreRetry, doPostRetry, asyncPreRetry, asyncPostRetry);
		}
	});
}
 
Example 2
Source Project: reactor-core   File: FluxSpecTests.java    License: Apache License 2.0 6 votes vote down vote up
@Test
	public void mappedConcat() {
//		"A mapped concat"
//		given: "source composables to concatMap, buffer and tap"
		Flux<Integer> firsts = Flux.just(1, 2, 3);

//		when: "the sources are concatMap"
		Flux<Integer> mergedFlux = firsts.concatMap(it -> Flux.range(it, 2));
		List<String> res = new ArrayList<>();
		mergedFlux.subscribe(
				it -> {
					res.add("" + it);
					System.out.println(it);
				}, Throwable::printStackTrace,
				() -> {
					res.add("done");
					System.out.println("completed!");
				});

//		then: "the values are all collected from source1 and source2 flux"
		assertThat(res).containsExactly("1", "2", "2", "3", "3", "4", "done");
	}
 
Example 3
/**
 * Finds the fist occurrence of the boundary in the given stream of data buffers, and skips
 * all data until then. Note that the first boundary of a multipart message does not contain
 * the initial \r\n, hence the need for a special boundary matcher.
 */
private static Flux<DataBuffer> skipUntilFirstBoundary(Flux<DataBuffer> dataBuffers, byte[] boundary) {
	byte[] needle = concat(FIRST_BOUNDARY_PREFIX, boundary);
	DataBufferUtils.Matcher matcher = DataBufferUtils.matcher(needle);
	AtomicBoolean found = new AtomicBoolean();

	return dataBuffers.concatMap(dataBuffer -> {
		if (found.get()) {
			return Mono.just(dataBuffer);
		}
		else {
			int endIdx = matcher.match(dataBuffer);
			if (endIdx != -1) {
				found.set(true);
				int length = dataBuffer.writePosition() - 1 - endIdx;
				DataBuffer slice = dataBuffer.retainedSlice(endIdx + 1, length);
				DataBufferUtils.release(dataBuffer);
				if (logger.isTraceEnabled()) {
					logger.trace("Found first boundary at " + endIdx + " in " + toString(dataBuffer));
				}
				return Mono.just(slice);
			}
			else {
				DataBufferUtils.release(dataBuffer);
				return Mono.empty();
			}
		}
	});
}
 
Example 4
@Override
public Flux<NumericResponse<KeyCommand, Long>> del(Publisher<KeyCommand> keys) {
    Flux<KeyCommand> s = Flux.from(keys);
    return s.concatMap(command -> {

        Assert.notNull(command.getKey(), "Key must not be null!");

        byte[] keyBuf = toByteArray(command.getKey());
        Mono<Long> m = write(keyBuf, StringCodec.INSTANCE, RedisCommands.DEL, keyBuf);
        return m.map(v -> new NumericResponse<>(command, v));
    });
}
 
Example 5
@Override
public Flux<NumericResponse<KeyCommand, Long>> del(Publisher<KeyCommand> keys) {
    Flux<KeyCommand> s = Flux.from(keys);
    return s.concatMap(command -> {

        Assert.notNull(command.getKey(), "Key must not be null!");

        byte[] keyBuf = toByteArray(command.getKey());
        Mono<Long> m = write(keyBuf, StringCodec.INSTANCE, RedisCommands.DEL, keyBuf);
        return m.map(v -> new NumericResponse<>(command, v));
    });
}
 
Example 6
@Override
public Flux<NumericResponse<KeyCommand, Long>> del(Publisher<KeyCommand> keys) {
    Flux<KeyCommand> s = Flux.from(keys);
    return s.concatMap(command -> {

        Assert.notNull(command.getKey(), "Key must not be null!");

        byte[] keyBuf = toByteArray(command.getKey());
        Mono<Long> m = write(keyBuf, StringCodec.INSTANCE, RedisCommands.DEL, keyBuf);
        return m.map(v -> new NumericResponse<>(command, v));
    });
}
 
Example 7
@Override
public Flux<NumericResponse<KeyCommand, Long>> del(Publisher<KeyCommand> keys) {
    Flux<KeyCommand> s = Flux.from(keys);
    return s.concatMap(command -> {

        Assert.notNull(command.getKey(), "Key must not be null!");

        byte[] keyBuf = toByteArray(command.getKey());
        Mono<Long> m = write(keyBuf, StringCodec.INSTANCE, RedisCommands.DEL, keyBuf);
        return m.map(v -> new NumericResponse<>(command, v));
    });
}
 
Example 8
@Override
public Flux<Long> generateCompanion(Flux<RetrySignal> t) {
    return t.concatMap(retryWhenState -> {
        RetrySignal copy = retryWhenState.copy();
        Throwable currentFailure = copy.failure();

        /*
         * Gateway exceptions come in many flavors, some can be recovered through RESUME while others
         * implicitly or explicitly invalidate a session and then only a RECONNECT is possible.
         */

        // First, if the current failure is not retryable, immediately forward the error

        if (currentFailure == null) {
            return Mono.error(new IllegalStateException("Retry.RetrySignal#failure() not expected to be null"));
        }

        if (!isRetryable(currentFailure)) {
            return Mono.error(currentFailure);
        }

        long iteration = reconnectContext.getAttempts();

        if (iteration >= reconnectOptions.getMaxRetries()) {
            return Mono.error(Exceptions.retryExhausted("Retries exhausted: " +
                    iteration + "/" + reconnectOptions.getMaxRetries(), copy.failure()));
        }

        // whenever we can recover with RESUME, we will use zero backoff for this attempt

        Duration nextBackoff;
        VoiceConnection.State nextState;

        Duration minBackoff = reconnectOptions.getFirstBackoff();
        Duration maxBackoff = reconnectOptions.getMaxBackoffInterval();

        if (canResume(currentFailure)) {
            // RESUME can happen immediately, but we still need backoff for iteration > 1 to avoid spam
            if (iteration == 1) {
                nextBackoff = Duration.ZERO;
            } else {
                nextBackoff = computeBackoff(iteration - 2, minBackoff, maxBackoff);
            }
            nextState = VoiceConnection.State.RESUMING;
        } else {
            nextBackoff = computeBackoff(iteration - 1, minBackoff, maxBackoff);
            nextState = VoiceConnection.State.RECONNECTING;
        }

        reconnectContext.next();

        if (nextBackoff.isZero()) {
            return applyHooks(new VoiceGatewayRetrySignal(copy.failure(), iteration, nextBackoff, nextState),
                    Mono.just(iteration),
                    doPreRetry);
        }

        Duration effectiveBackoff = nextBackoff.plusMillis(computeJitter(nextBackoff, minBackoff, maxBackoff,
                reconnectOptions.getJitterFactor()));

        return applyHooks(new VoiceGatewayRetrySignal(copy.failure(), iteration, effectiveBackoff, nextState),
                Mono.delay(effectiveBackoff, reconnectOptions.getBackoffScheduler()),
                doPreRetry);
    });
}
 
Example 9
@Override
public Flux<Long> generateCompanion(Flux<RetrySignal> t) {
    return t.concatMap(retryWhenState -> {
        RetrySignal copy = retryWhenState.copy();
        Throwable currentFailure = copy.failure();

        /*
         * Gateway exceptions come in many flavors, some can be recovered through RESUME while others
         * implicitly or explicitly invalidate a session and then only a RECONNECT is possible.
         */

        // First, if the current failure is not retryable, immediately forward the error

        if (currentFailure == null) {
            return Mono.error(new IllegalStateException("Retry.RetrySignal#failure() not expected to be null"));
        }

        if (!isRetryable(currentFailure)) {
            return Mono.error(currentFailure);
        }

        if (currentFailure instanceof InvalidSessionException) {
            reconnectContext.reset();
        }
        long iteration = reconnectContext.getAttempts();

        if (iteration >= reconnectOptions.getMaxRetries()) {
            return Mono.error(Exceptions.retryExhausted("Retries exhausted: " +
                    iteration + "/" + reconnectOptions.getMaxRetries(), copy.failure()));
        }

        // whenever we can recover with RESUME, we will use zero backoff for this attempt

        Duration nextBackoff;
        GatewayConnection.State nextState;

        Duration minBackoff = reconnectOptions.getFirstBackoff();
        Duration maxBackoff = reconnectOptions.getMaxBackoffInterval();

        if (canResume(currentFailure)) {
            // RESUME can happen immediately, but we still need backoff for iteration > 1 to avoid spam
            if (iteration == 1) {
                nextBackoff = Duration.ZERO;
            } else {
                nextBackoff = computeBackoff(iteration - 2, minBackoff, maxBackoff);
            }
            nextState = GatewayConnection.State.RESUMING;
        } else {
            nextBackoff = computeBackoff(iteration - 1, minBackoff, maxBackoff);
            nextState = GatewayConnection.State.RECONNECTING;
        }

        reconnectContext.next();

        if (nextBackoff.isZero()) {
            return applyHooks(new GatewayRetrySignal(copy.failure(), iteration, nextBackoff, nextState),
                    Mono.just(iteration),
                    doPreRetry);
        }

        Duration effectiveBackoff = nextBackoff.plusMillis(computeJitter(nextBackoff, minBackoff, maxBackoff,
                reconnectOptions.getJitterFactor()));

        return applyHooks(new GatewayRetrySignal(copy.failure(), iteration, effectiveBackoff, nextState),
                Mono.delay(effectiveBackoff, reconnectOptions.getBackoffScheduler()),
                doPreRetry);
    });
}
 
Example 10
Source Project: reactor-core   File: RetryBackoffSpec.java    License: Apache License 2.0 4 votes vote down vote up
@Override
public Flux<Long> generateCompanion(Flux<RetrySignal> t) {
	validateArguments();
	return t.concatMap(retryWhenState -> {
		//capture the state immediately
		RetrySignal copy = retryWhenState.copy();
		Throwable currentFailure = copy.failure();
		long iteration = isTransientErrors ? copy.totalRetriesInARow() : copy.totalRetries();

		if (currentFailure == null) {
			return Mono.error(new IllegalStateException("Retry.RetrySignal#failure() not expected to be null"));
		}

		if (!errorFilter.test(currentFailure)) {
			return Mono.error(currentFailure);
		}

		if (iteration >= maxAttempts) {
			return Mono.error(retryExhaustedGenerator.apply(this, copy));
		}

		Duration nextBackoff;
		try {
			nextBackoff = minBackoff.multipliedBy((long) Math.pow(2, iteration));
			if (nextBackoff.compareTo(maxBackoff) > 0) {
				nextBackoff = maxBackoff;
			}
		}
		catch (ArithmeticException overflow) {
			nextBackoff = maxBackoff;
		}

		//short-circuit delay == 0 case
		if (nextBackoff.isZero()) {
			return RetrySpec.applyHooks(copy, Mono.just(iteration),
					syncPreRetry, syncPostRetry, asyncPreRetry, asyncPostRetry);
		}

		ThreadLocalRandom random = ThreadLocalRandom.current();

		long jitterOffset;
		try {
			jitterOffset = nextBackoff.multipliedBy((long) (100 * jitterFactor))
			                          .dividedBy(100)
			                          .toMillis();
		}
		catch (ArithmeticException ae) {
			jitterOffset = Math.round(Long.MAX_VALUE * jitterFactor);
		}
		long lowBound = Math.max(minBackoff.minus(nextBackoff)
		                                     .toMillis(), -jitterOffset);
		long highBound = Math.min(maxBackoff.minus(nextBackoff)
		                                    .toMillis(), jitterOffset);

		long jitter;
		if (highBound == lowBound) {
			if (highBound == 0) jitter = 0;
			else jitter = random.nextLong(highBound);
		}
		else {
			jitter = random.nextLong(lowBound, highBound);
		}
		Duration effectiveBackoff = nextBackoff.plusMillis(jitter);
		return RetrySpec.applyHooks(copy, Mono.delay(effectiveBackoff,
				backoffSchedulerSupplier.get()),
				syncPreRetry, syncPostRetry, asyncPreRetry, asyncPostRetry);
	});
}
 
Example 11
Source Project: redisson   File: RedissonBaseReactive.java    License: Apache License 2.0 4 votes vote down vote up
<V, T> Flux<T> execute(Publisher<V> commands, Function<V, Publisher<T>> mapper) {
    Flux<V> s = Flux.from(commands);
    return s.concatMap(mapper);
}
 
Example 12
Source Project: redisson   File: RedissonBaseReactive.java    License: Apache License 2.0 4 votes vote down vote up
<V, T> Flux<T> execute(Publisher<V> commands, Function<V, Publisher<T>> mapper) {
    Flux<V> s = Flux.from(commands);
    return s.concatMap(mapper);
}
 
Example 13
Source Project: redisson   File: RedissonBaseReactive.java    License: Apache License 2.0 4 votes vote down vote up
<V, T> Flux<T> execute(Publisher<V> commands, Function<V, Publisher<T>> mapper) {
    Flux<V> s = Flux.from(commands);
    return s.concatMap(mapper);
}
 
Example 14
Source Project: redisson   File: RedissonBaseReactive.java    License: Apache License 2.0 4 votes vote down vote up
<V, T> Flux<T> execute(Publisher<V> commands, Function<V, Publisher<T>> mapper) {
    Flux<V> s = Flux.from(commands);
    return s.concatMap(mapper);
}