All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.azure.messaging.eventhubs.implementation.ReactorShim Maven / Gradle / Ivy

There is a newer version: 5.19.2
Show newest version
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.azure.messaging.eventhubs.implementation;

import com.azure.core.util.logging.ClientLogger;
import reactor.core.publisher.Flux;
import reactor.core.scheduler.Schedulers;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.time.Duration;

/**
 * A shim that proxies Reactor operator calls, for example, if the loaded Reactor has an optimized variant
 * of a standard operator, then shim uses it else fallback to the standard variant, if there are breaking
 * changes in operators among Reactor versions that SDK supports, then shim may expose a unified API for
 * those operators.
 */
public final class ReactorShim {
    private static final ClientLogger LOGGER = new ClientLogger(ReactorShim.class);

    /* Reactor Operator names */
    private static final String  WINDOW_TIMEOUT_OPERATOR = "windowTimeout";
    /* Reactor Operator handles */
    private static final MethodHandle BACKPRESSURE_WINDOW_TIMEOUT_OPERATOR_HANDLE;

    static {
        BACKPRESSURE_WINDOW_TIMEOUT_OPERATOR_HANDLE = lookupBackpressureWindowTimeoutOperator();
    }

    /**
     * Split the {@code source} {@link Flux} sequence into multiple {@link Flux} windows containing
     * {@code maxSize} elements (or less for the final window) and starting from the first item.
     * Each {@link Flux} window will onComplete once it contains {@code maxSize} elements
     * OR it has been open for the given {@link Duration} (as measured on the {@link Schedulers#parallel() parallel}
     * Scheduler).
     *
     * 

* If the loaded Reactor library has a backpressure-aware window-timeout operator then it will be used, * which caps requests to the source by {@code maxSize} (i.e. prefetch), otherwise, the regular variant * of window-timeout operator requesting unbounded demand will be used. * * @param maxSize the maximum number of items to emit in the window before closing it * @param maxTime the maximum {@link Duration} since the window was opened before closing it * * @param the element type of the source {@link Flux}. * @return a {@link Flux} of {@link Flux} windows based on element count and duration. */ public static Flux> windowTimeout(Flux source, int maxSize, Duration maxTime) { if (BACKPRESSURE_WINDOW_TIMEOUT_OPERATOR_HANDLE == null) { // optimized (backpressure) aware windowTimeout operator not available use standard variant. return source.windowTimeout(maxSize, maxTime); } try { return ((Flux>) (BACKPRESSURE_WINDOW_TIMEOUT_OPERATOR_HANDLE.invoke(source, maxSize, maxTime, true))); } catch (Throwable err) { // 'java.lang.invoke' throws Throwable. Given 'Error' category represents a serious // abnormal thread state throw it immediately else throw via standard azure-core Logger. if (err instanceof Error) { throw (Error) err; } else if (err instanceof RuntimeException) { throw LOGGER.logExceptionAsError((RuntimeException) err); } else { throw LOGGER.logExceptionAsError(new RuntimeException(err)); } } } /** * Try to obtain {@link MethodHandle} for backpressure aware windowTimeout Reactor operator. * * @return if the backpressure aware windowTimeout Reactor operator is available then return * operator {@link MethodHandle} else null. */ private static MethodHandle lookupBackpressureWindowTimeoutOperator() { try { return MethodHandles.publicLookup().findVirtual(Flux.class, WINDOW_TIMEOUT_OPERATOR, MethodType.methodType(Flux.class, int.class, Duration.class, boolean.class)); } catch (IllegalAccessException | NoSuchMethodException err) { LOGGER.verbose("Failed to retrieve MethodHandle for backpressure aware windowTimeout Reactor operator.", err); } return null; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy