Search in sources :

Example 1 with GlGraph

use of ru.fix.completable.reactor.graph.runtime.GlGraph in project completable-reactor by ru-fix.

the class CompletableReactor method registerGraphIfAbsent.

/**
 * @param graphConfig
 * @param <GraphConfigType>
 * @return true if graph is built and registered, false - if graph already registered
 */
public <GraphConfigType extends Graphable> boolean registerGraphIfAbsent(GraphConfigType graphConfig) {
    Objects.requireNonNull(graphConfig, "graphConfig");
    AtomicBoolean isComputed = new AtomicBoolean(false);
    glGraphConfigs.computeIfAbsent(graphConfig.getClass(), type -> {
        Class payloadType = getPayloadTypeForGraphConfigBasedClass(graphConfig.getClass());
        GlGraph graph = graphBuilder.buildGraph(graphConfig);
        Object prevGraph = glPayloadGraphs.putIfAbsent(payloadType, graph);
        if (prevGraph != null) {
            throw new IllegalArgumentException("" + "New graph config: " + graphConfig + " of type " + graphConfig.getClass() + " is registering graph for payload " + payloadType + "." + " But this payload was already registered by another graph config.");
        }
        isComputed.set(true);
        return true;
    });
    return isComputed.get();
}
Also used : GlGraph(ru.fix.completable.reactor.graph.runtime.GlGraph)

Example 2 with GlGraph

use of ru.fix.completable.reactor.graph.runtime.GlGraph in project completable-reactor by ru-fix.

the class CompletableReactor method internalSubmit.

/**
 * Submit request without checking whether reactor closed or not.
 * If maxPendingRequestCount limit is reached prints error message and accepts request.
 *
 * @param payload
 * @param timeoutMs
 * @param <PayloadType>
 * @return
 */
private <PayloadType> Execution<PayloadType> internalSubmit(PayloadType payload, long timeoutMs) {
    if (pendingRequestCount.get() > maxPendingRequestCount.get()) {
        log.error("Max pending request count is reached. Request will be accepted but there is a possibility of " + "OOM or something wrong with back pressure logic in client code.\n" + "Use trySubmit method that supports back pressure or correctly handle the load on " + "CompletableReactor on client side.");
    }
    ProfiledCall payloadCall = profiler.profiledCall("" + ProfilerNames.PAYLOAD + "." + payload.getClass().getSimpleName()).start();
    ProfiledCall executionCall = profiler.profiledCall("" + ProfilerNames.EXECUTION + "." + payload.getClass().getSimpleName()).start();
    /**
     * Inline graph execution scenario
     */
    Function inlineGraphFunction = inlinePayloadGraphs.get(payload.getClass());
    if (inlineGraphFunction != null) {
        CompletableFuture<PayloadType> inlineGraphResult = (CompletableFuture<PayloadType>) inlineGraphFunction.apply(payload);
        inlineGraphResult.thenAcceptAsync(any -> {
            payloadCall.stop();
            executionCall.stop();
        });
        return new Execution<>(inlineGraphResult, inlineGraphResult.thenAccept(any -> {
        /* do nothing */
        }), null);
    }
    /**
     * Standard graph execution scenario
     */
    ReactorGraphExecution<PayloadType> execution;
    ReactorGraph<PayloadType> graph = payloadGraphs.get(payload.getClass());
    if (graph != null) {
        execution = executionBuilder.build(graph);
    } else {
        GlGraph glGraph = glPayloadGraphs.get(payload.getClass());
        if (glGraph != null) {
            execution = glExecutionBuilder.build(glGraph);
        } else {
            throw new IllegalArgumentException(String.format("Rector graph not found for payload %s", payload.getClass()));
        }
    }
    /**
     * Handling pending request counts
     */
    pendingRequestCount.incrementAndGet();
    PayloadStatCounters statistics = payloadStatCounters.computeIfAbsent(payload.getClass(), key -> new PayloadStatCounters());
    statistics.runningTotal.increment();
    execution.getChainExecutionFuture().handleAsync((result, thr) -> {
        statistics.runningTotal.decrement();
        return null;
    });
    execution.getResultFuture().handleAsync((result, thr) -> {
        statistics.runningWithoutResult.decrement();
        return null;
    });
    /**
     * Launching chain execution
     */
    execution.getSubmitFuture().complete(payload);
    // TODO: add to exception details about vertex statuses, what vertix is currently does not completed on time
    /**
     * Add timeout protection to execution
     */
    ScheduledFuture<?> schedule = timeoutExecutorService.schedule(() -> {
        /**
         * Temporary solution.
         * Should be fixed by completing all futures in processor chain
         */
        if (!execution.getResultFuture().isDone()) {
            execution.getResultFuture().completeExceptionally(new TimeoutException(String.format("Response for payload %s took more than %d ms.", payload, timeoutMs)));
        }
        if (!execution.getChainExecutionFuture().isDone()) {
            execution.getChainExecutionFuture().completeExceptionally(new TimeoutException(String.format("Execution of payload %s took more than %d ms.", payload, timeoutMs)));
        }
    }, timeoutMs, TimeUnit.MILLISECONDS);
    execution.getChainExecutionFuture().handleAsync((result, throwable) -> {
        long count = pendingRequestCount.decrementAndGet();
        if (count == 0) {
            synchronized (pendingRequestCount) {
                pendingRequestCount.notifyAll();
            }
        }
        schedule.cancel(false);
        return null;
    });
    execution.getResultFuture().thenRunAsync(payloadCall::stop);
    execution.getChainExecutionFuture().thenRunAsync(executionCall::stop);
    return new Execution<>(execution.getResultFuture(), execution.getChainExecutionFuture(), execution.getDebugProcessingVertexGraphState());
}
Also used : java.util(java.util) CopierThreadsafeCopyMaker(ru.fix.completable.reactor.runtime.cloning.CopierThreadsafeCopyMaker) ProfiledCall(ru.fix.commons.profiler.ProfiledCall) LoggerFactory(org.slf4j.LoggerFactory) ThreadsafeCopyMaker(ru.fix.completable.reactor.runtime.cloning.ThreadsafeCopyMaker) Constructor(java.lang.reflect.Constructor) Function(java.util.function.Function) ReactorGraphExecutionBuilder(ru.fix.completable.reactor.runtime.execution.ReactorGraphExecutionBuilder) ReflectionImmutabilityChecker(ru.fix.completable.reactor.runtime.immutability.ReflectionImmutabilityChecker) ExecutionBuilder(ru.fix.completable.reactor.runtime.execution.ExecutionBuilder) GlGraph(ru.fix.completable.reactor.graph.runtime.GlGraph) ReactorGraphExecution(ru.fix.completable.reactor.runtime.execution.ReactorGraphExecution) ToStringDebugSerializer(ru.fix.completable.reactor.runtime.debug.ToStringDebugSerializer) Logger(org.slf4j.Logger) java.util.concurrent(java.util.concurrent) java.util.concurrent.atomic(java.util.concurrent.atomic) ImmutabilityChecker(ru.fix.completable.reactor.runtime.immutability.ImmutabilityChecker) PrefixedProfiler(ru.fix.commons.profiler.PrefixedProfiler) ImmutabilityControlLevel(ru.fix.completable.reactor.runtime.immutability.ImmutabilityControlLevel) DebugSerializer(ru.fix.completable.reactor.runtime.debug.DebugSerializer) Tracer(ru.fix.completable.reactor.runtime.tracing.Tracer) ParameterizedType(java.lang.reflect.ParameterizedType) CRReactorGraph(ru.fix.completable.reactor.runtime.internal.CRReactorGraph) Type(java.lang.reflect.Type) Graphable(ru.fix.completable.reactor.graph.Graphable) Profiler(ru.fix.commons.profiler.Profiler) GlGraph(ru.fix.completable.reactor.graph.runtime.GlGraph) Function(java.util.function.Function) ReactorGraphExecution(ru.fix.completable.reactor.runtime.execution.ReactorGraphExecution) ProfiledCall(ru.fix.commons.profiler.ProfiledCall)

Example 3 with GlGraph

use of ru.fix.completable.reactor.graph.runtime.GlGraph in project completable-reactor by ru-fix.

the class CompletableReactor method registerGraphIfAbsent.

// TODO: execute validation during graph registration
/**
 * Test graph configuration.
 * Check all execution paths.
 * Validated that there is no conflicts between merging vertices and all required endpoints exist.
 */
public <GraphConfigType extends Graphable> boolean registerGraphIfAbsent(Class<GraphConfigType> graphConfigClass) {
    Objects.requireNonNull(graphConfigClass, "graphConfigClass");
    AtomicBoolean isComputed = new AtomicBoolean(false);
    glGraphConfigs.computeIfAbsent(graphConfigClass, type -> {
        try {
            Class payloadType = getPayloadTypeForGraphConfigBasedClass(graphConfigClass);
            Graphable graphConfig;
            try {
                Constructor<GraphConfigType> ctor = graphConfigClass.getDeclaredConstructor();
                if (!ctor.isAccessible()) {
                    ctor.setAccessible(true);
                }
                graphConfig = ctor.newInstance();
            } catch (Exception exc) {
                throw new IllegalArgumentException("" + "Failed to instantiate graph config instance of class: " + graphConfigClass + "." + " Graph config class should have default no arg constructor." + " If it is inner class then it sould be static.", exc);
            }
            GlGraph graph = graphBuilder.buildGraph(graphConfig);
            glPayloadGraphs.putIfAbsent(payloadType, graph);
            isComputed.set(true);
        } catch (Exception exc) {
            throw new RuntimeException("Failed to register graph config in ReactorGraph: " + graphConfigClass, exc);
        }
        return true;
    });
    return isComputed.get();
}
Also used : GlGraph(ru.fix.completable.reactor.graph.runtime.GlGraph) Graphable(ru.fix.completable.reactor.graph.Graphable)

Aggregations

GlGraph (ru.fix.completable.reactor.graph.runtime.GlGraph)3 Graphable (ru.fix.completable.reactor.graph.Graphable)2 Constructor (java.lang.reflect.Constructor)1 ParameterizedType (java.lang.reflect.ParameterizedType)1 Type (java.lang.reflect.Type)1 java.util (java.util)1 java.util.concurrent (java.util.concurrent)1 java.util.concurrent.atomic (java.util.concurrent.atomic)1 Function (java.util.function.Function)1 Logger (org.slf4j.Logger)1 LoggerFactory (org.slf4j.LoggerFactory)1 PrefixedProfiler (ru.fix.commons.profiler.PrefixedProfiler)1 ProfiledCall (ru.fix.commons.profiler.ProfiledCall)1 Profiler (ru.fix.commons.profiler.Profiler)1 CopierThreadsafeCopyMaker (ru.fix.completable.reactor.runtime.cloning.CopierThreadsafeCopyMaker)1 ThreadsafeCopyMaker (ru.fix.completable.reactor.runtime.cloning.ThreadsafeCopyMaker)1 DebugSerializer (ru.fix.completable.reactor.runtime.debug.DebugSerializer)1 ToStringDebugSerializer (ru.fix.completable.reactor.runtime.debug.ToStringDebugSerializer)1 ExecutionBuilder (ru.fix.completable.reactor.runtime.execution.ExecutionBuilder)1 ReactorGraphExecution (ru.fix.completable.reactor.runtime.execution.ReactorGraphExecution)1