Search in sources :

Example 1 with ImmutabilityControlLevel

use of ru.fix.completable.reactor.runtime.immutability.ImmutabilityControlLevel in project completable-reactor by ru-fix.

the class ReactorGraphExecutionBuilder method handle.

private <PayloadType> void handle(ProcessingVertex processingVertex, TransitionPayloadContext payloadContext, CompletableFuture<PayloadType> executionResultFuture) {
    CRReactorGraph.ProcessingItemInfo processorInfo = processingVertex.getProcessingItemInfo();
    Object payload = payloadContext.getPayload();
    /**
     * In case of detached merge point processor should not have incoming handling transition.
     */
    if (processorInfo.getProcessingItemType() == CRReactorGraph.ProcessingItemType.MERGE_POINT) {
        throw new IllegalStateException(String.format("Processor %s is of type %s and should not have any incoming handling transition", processingVertex.getProcessingItem().getDebugName(), processorInfo.getProcessingItemType()));
    }
    ProfiledCall handleCall = profiler.profiledCall(ProfilerNames.HANDLE + "." + (payload != null ? payload.getClass().getSimpleName() : "null") + "." + processingVertex.getProcessingItem().getProfilingName()).start();
    boolean isTraceablePayload = tracer.isTraceable(payload);
    Object handleTracingMarker = isTraceablePayload ? tracer.beforeHandle(processingVertex.getProcessingItem().getIdentity().toString(), payload) : null;
    ReactorGraphModel.Identity handleTracingIdentity = isTraceablePayload ? processingVertex.getProcessingItem().getIdentity() : null;
    CompletableFuture<?> handlingResult;
    /**
     * Immutability check ensures that there is no payload modification during handling.
     */
    final ImmutabilityControlLevel controlLevel = this.immutabilityControlLevel;
    ImmutabilityChecker.Snapshot payloadSnapshot;
    try {
        if (controlLevel != ImmutabilityControlLevel.NO_CONTROL) {
            /**
             * Invoke handling with immutability check.
             */
            payloadSnapshot = immutabilityChecker.takeSnapshot(payload);
            handlingResult = invokeHandlingMethod(processorInfo, processingVertex.getProcessingItem(), payload);
        } else {
            /**
             * Invoke handling without immutability check.
             */
            payloadSnapshot = null;
            handlingResult = invokeHandlingMethod(processorInfo, processingVertex.getProcessingItem(), payload);
        }
    } catch (Exception handlingException) {
        RuntimeException exc = new RuntimeException(String.format("Failed handling by processor %s for payload %s %s. Handling method raised exception: %s.", processingVertex.getProcessingItem().getDebugName(), payload.getClass(), debugSerializer.dumpObject(payload), handlingException), handlingException);
        log.error(exc.getMessage(), exc);
        executionResultFuture.completeExceptionally(exc);
        processingVertex.getProcessorFuture().complete(new HandlePayloadContext().setTerminal(true));
        return;
    }
    if (handlingResult == null) {
        RuntimeException exc = new RuntimeException(String.format("Failed handling by processor %s for payload %s %s. Handling method returned NULL." + " Instance of CompletableFuture expected.", processingVertex.getProcessingItem().getDebugName(), payload.getClass(), debugSerializer.dumpObject(payload)));
        log.error(exc.getMessage(), exc);
        executionResultFuture.completeExceptionally(exc);
        processingVertex.getProcessorFuture().complete(new HandlePayloadContext().setTerminal(true));
        return;
    }
    handlingResult.handleAsync((res, thr) -> {
        handleCall.stop();
        if (isTraceablePayload) {
            tracer.afterHandle(handleTracingMarker, handleTracingIdentity.toString(), res, thr);
        }
        if (controlLevel != ImmutabilityControlLevel.NO_CONTROL) {
            Optional<String> diff = immutabilityChecker.diff(payloadSnapshot, payload);
            if (diff.isPresent()) {
                String message = String.format("Concurrent modification of payload %s detected. Diff: %s.", debugSerializer.dumpObject(payload), diff.get());
                switch(controlLevel) {
                    case LOG_ERROR:
                        log.error(message);
                        break;
                    case LOG_WARN:
                        log.warn(message);
                        break;
                    case EXCEPTION:
                        RuntimeException immutabilityException = new RuntimeException(message);
                        log.error(message, immutabilityException);
                        if (thr == null) {
                            log.error("Overwriting execution exception {} by immutability check exception {}.", thr, immutabilityException, thr);
                        }
                        thr = immutabilityException;
                        break;
                }
            }
        }
        if (thr != null) {
            RuntimeException exc = new RuntimeException(String.format("Failed handling by processor %s for payload %s %s", processingVertex.getProcessingItem().getDebugName(), payload.getClass(), debugSerializer.dumpObject(payload)), thr);
            log.error(exc.getMessage(), exc);
            executionResultFuture.completeExceptionally(exc);
            processingVertex.getProcessorFuture().complete(new HandlePayloadContext().setTerminal(true));
        } else {
            processingVertex.getProcessorFuture().complete(new HandlePayloadContext().setPayload(payload).setProcessorResult(res));
        }
        return null;
    }).exceptionally(exc -> {
        log.error("Failed to execute afterHandle block for {}", Optional.of(processingVertex).map(ProcessingVertex::getProcessingItem).map(CRProcessingItem::getDebugName).orElse("?"), exc);
        return null;
    });
}
Also used : ReactorGraphModel(ru.fix.completable.reactor.api.ReactorGraphModel) java.util(java.util) Accessors(lombok.experimental.Accessors) ProfiledCall(ru.fix.commons.profiler.ProfiledCall) lombok.val(lombok.val) CompletableFuture(java.util.concurrent.CompletableFuture) CRProcessingItem(ru.fix.completable.reactor.runtime.internal.CRProcessingItem) ThreadsafeCopyMaker(ru.fix.completable.reactor.runtime.cloning.ThreadsafeCopyMaker) ImmutabilityChecker(ru.fix.completable.reactor.runtime.immutability.ImmutabilityChecker) Supplier(java.util.function.Supplier) Collectors(java.util.stream.Collectors) CRProcessorDescription(ru.fix.completable.reactor.runtime.internal.dsl.CRProcessorDescription) Slf4j(lombok.extern.slf4j.Slf4j) ReactorGraph(ru.fix.completable.reactor.runtime.ReactorGraph) ImmutabilityControlLevel(ru.fix.completable.reactor.runtime.immutability.ImmutabilityControlLevel) DebugSerializer(ru.fix.completable.reactor.runtime.debug.DebugSerializer) Tracer(ru.fix.completable.reactor.runtime.tracing.Tracer) CRReactorGraph(ru.fix.completable.reactor.runtime.internal.CRReactorGraph) ProfilerNames(ru.fix.completable.reactor.runtime.ProfilerNames) Data(lombok.Data) Profiler(ru.fix.commons.profiler.Profiler) CRReactorGraph(ru.fix.completable.reactor.runtime.internal.CRReactorGraph) ImmutabilityControlLevel(ru.fix.completable.reactor.runtime.immutability.ImmutabilityControlLevel) CRProcessingItem(ru.fix.completable.reactor.runtime.internal.CRProcessingItem) ProfiledCall(ru.fix.commons.profiler.ProfiledCall) ReactorGraphModel(ru.fix.completable.reactor.api.ReactorGraphModel) ImmutabilityChecker(ru.fix.completable.reactor.runtime.immutability.ImmutabilityChecker)

Aggregations

java.util (java.util)1 CompletableFuture (java.util.concurrent.CompletableFuture)1 Supplier (java.util.function.Supplier)1 Collectors (java.util.stream.Collectors)1 Data (lombok.Data)1 Accessors (lombok.experimental.Accessors)1 Slf4j (lombok.extern.slf4j.Slf4j)1 lombok.val (lombok.val)1 ProfiledCall (ru.fix.commons.profiler.ProfiledCall)1 Profiler (ru.fix.commons.profiler.Profiler)1 ReactorGraphModel (ru.fix.completable.reactor.api.ReactorGraphModel)1 ProfilerNames (ru.fix.completable.reactor.runtime.ProfilerNames)1 ReactorGraph (ru.fix.completable.reactor.runtime.ReactorGraph)1 ThreadsafeCopyMaker (ru.fix.completable.reactor.runtime.cloning.ThreadsafeCopyMaker)1 DebugSerializer (ru.fix.completable.reactor.runtime.debug.DebugSerializer)1 ImmutabilityChecker (ru.fix.completable.reactor.runtime.immutability.ImmutabilityChecker)1 ImmutabilityControlLevel (ru.fix.completable.reactor.runtime.immutability.ImmutabilityControlLevel)1 CRProcessingItem (ru.fix.completable.reactor.runtime.internal.CRProcessingItem)1 CRReactorGraph (ru.fix.completable.reactor.runtime.internal.CRReactorGraph)1 CRProcessorDescription (ru.fix.completable.reactor.runtime.internal.dsl.CRProcessorDescription)1