/* * 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.module.deployment.internal; import static org.mule.runtime.core.api.scheduler.SchedulerConfig.config; import org.mule.runtime.api.scheduler.Scheduler; import org.mule.runtime.core.api.scheduler.SchedulerService; import org.mule.runtime.deployment.model.api.application.Application; import org.mule.runtime.deployment.model.api.domain.Domain; import org.mule.runtime.module.deployment.internal.util.ObservableList; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.locks.ReentrantLock; import java.util.function.Supplier; /** * Provides parallel deployment of Mule applications. * * @since 3.8.2 */ public class ParallelDeploymentDirectoryWatcher extends DeploymentDirectoryWatcher { private Scheduler threadPoolExecutor; public ParallelDeploymentDirectoryWatcher(ArchiveDeployer<Domain> domainArchiveDeployer, ArchiveDeployer<Application> applicationArchiveDeployer, ObservableList<Domain> domains, ObservableList<Application> applications, Supplier<SchedulerService> schedulerServiceSupplier, ReentrantLock deploymentLock) { super(domainArchiveDeployer, applicationArchiveDeployer, domains, applications, schedulerServiceSupplier, deploymentLock); } @Override protected void deployPackedApps(String[] zips) { if (zips.length == 0) { return; } List<Callable<Object>> tasks = new ArrayList<>(zips.length); for (final String zip : zips) { tasks.add(() -> { try { applicationArchiveDeployer.deployPackagedArtifact(zip); } catch (Exception e) { // Ignore and continue } return null; }); } waitForTasksToFinish(tasks); } @Override protected void deployExplodedApps(String[] apps) { List<Callable<Object>> tasks = new ArrayList<>(apps.length); for (final String addedApp : apps) { if (applicationArchiveDeployer.isUpdatedZombieArtifact(addedApp)) { tasks.add(() -> { try { applicationArchiveDeployer.deployExplodedArtifact(addedApp); } catch (Exception e) { // Ignore and continue } return null; }); } } if (!tasks.isEmpty()) { waitForTasksToFinish(tasks); } } private void waitForTasksToFinish(List<Callable<Object>> tasks) { this.threadPoolExecutor = schedulerServiceSupplier.get().ioScheduler(config().withName("parallelDeployment").withMaxConcurrentTasks(20)); try { final List<Future<Object>> futures = threadPoolExecutor.invokeAll(tasks); for (Future<Object> future : futures) { try { future.get(); } catch (ExecutionException e) { // Ignore and continue with the next one } } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } finally { threadPoolExecutor.stop(); } } }