/* * Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com * The software in this package is published under the terms of the CPAL v1.0 * license, a copy of which has been included with this distribution in the * LICENSE.txt file. */ package org.mule.runtime.core.processor.strategy; import static org.mule.runtime.core.api.lifecycle.LifecycleUtils.disposeIfNeeded; import static org.mule.runtime.core.api.processor.ReactiveProcessor.ProcessingType.BLOCKING; import static org.mule.runtime.core.api.processor.ReactiveProcessor.ProcessingType.CPU_INTENSIVE; import static org.mule.runtime.core.api.processor.ReactiveProcessor.ProcessingType.CPU_LITE; import static org.mule.runtime.core.processor.strategy.BlockingProcessingStrategyFactory.BLOCKING_PROCESSING_STRATEGY_INSTANCE; import static org.mule.runtime.core.transaction.TransactionCoordination.isTransactionActive; import static org.slf4j.helpers.NOPLogger.NOP_LOGGER; import org.mule.runtime.api.lifecycle.Disposable; import org.mule.runtime.api.scheduler.Scheduler; import org.mule.runtime.core.api.Event; import org.mule.runtime.core.api.MuleContext; import org.mule.runtime.core.api.construct.FlowConstruct; import org.mule.runtime.core.api.processor.ReactiveProcessor; import org.mule.runtime.core.api.processor.Sink; import org.mule.runtime.core.api.processor.strategy.ProcessingStrategy; import org.mule.runtime.core.internal.util.rx.ConditionalExecutorServiceDecorator; import java.util.concurrent.ExecutorService; import java.util.function.Consumer; import java.util.function.Supplier; /** * Creates default processing strategy with same behavior as {@link ProactorProcessingStrategyFactory} apart from the fact it will * process synchronously without error when a transaction is active. */ public class DefaultFlowProcessingStrategyFactory extends ProactorProcessingStrategyFactory { @Override public ProcessingStrategy create(MuleContext muleContext, String schedulersNamePrefix) { return new DefaultFlowProcessingStrategy(() -> muleContext.getSchedulerService() .cpuLightScheduler(muleContext.getSchedulerBaseConfig().withName(schedulersNamePrefix + "." + CPU_LITE.name()) .withMaxConcurrentTasks(getMaxConcurrency())), () -> muleContext.getSchedulerService() .ioScheduler(muleContext.getSchedulerBaseConfig() .withName(schedulersNamePrefix + "." + BLOCKING.name()) .withMaxConcurrentTasks(getMaxConcurrency())), () -> muleContext.getSchedulerService() .cpuIntensiveScheduler(muleContext.getSchedulerBaseConfig() .withName(schedulersNamePrefix + "." + CPU_INTENSIVE.name()) .withMaxConcurrentTasks(getMaxConcurrency()))); } static class DefaultFlowProcessingStrategy extends ProactorProcessingStrategy { protected DefaultFlowProcessingStrategy(Supplier<Scheduler> cpuLightSchedulerSupplier, Supplier<Scheduler> blockingSchedulerSupplier, Supplier<Scheduler> cpuIntensiveSchedulerSupplier) { super(cpuLightSchedulerSupplier, blockingSchedulerSupplier, cpuIntensiveSchedulerSupplier); } @Override public Sink createSink(FlowConstruct flowConstruct, ReactiveProcessor pipeline) { Sink proactorSink = super.createSink(flowConstruct, pipeline); Sink syncSink = BLOCKING_PROCESSING_STRATEGY_INSTANCE.createSink(flowConstruct, pipeline); return new DelegateSink(syncSink, proactorSink); } @Override protected Consumer<Event> createOnEventConsumer() { // Do nothing given event should still be processed when transaction is active return event -> { }; } @Override protected ExecutorService decorateScheduler(Scheduler scheduler) { return new ConditionalExecutorServiceDecorator(scheduler, cuurentScheduler -> isTransactionActive()); } final static class DelegateSink implements Sink, Disposable { private final Sink syncSink; private final Sink proactorSink; public DelegateSink(Sink syncSink, Sink proactorSink) { this.syncSink = syncSink; this.proactorSink = proactorSink; } @Override public void accept(Event event) { if (isTransactionActive()) { syncSink.accept(event); } else { proactorSink.accept(event); } } @Override public void dispose() { disposeIfNeeded(syncSink, NOP_LOGGER); disposeIfNeeded(proactorSink, NOP_LOGGER); } } } }