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

org.camunda.bpm.engine.impl.jobexecutor.SequentialJobAcquisitionRunnable Maven / Gradle / Ivy

There is a newer version: 7.22.0-alpha1
Show newest version
/*
 * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH
 * under one or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership. Camunda licenses this file to you under the Apache License,
 * Version 2.0; you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.camunda.bpm.engine.impl.jobexecutor;

import java.util.Iterator;
import java.util.List;

import org.camunda.bpm.engine.ProcessEngine;
import org.camunda.bpm.engine.impl.ProcessEngineImpl;
import org.camunda.bpm.engine.impl.ProcessEngineLogger;
import org.camunda.bpm.engine.impl.interceptor.CommandExecutor;
import org.camunda.bpm.engine.impl.util.ClassLoaderUtil;


/**
 * 

{@link AcquireJobsRunnable} able to serve multiple process engines.

* *

* Continuously acquires jobs for all registered process engines until interruption. * For every such acquisition cycle, jobs are acquired and submitted for execution. *

* *

* For one cycle, all acquisition-related events (acquired jobs by engine, rejected jobs by engine, * exceptions during acquisition, etc.) are collected in an instance of {@link JobAcquisitionContext}. * The context is then handed to a {@link JobAcquisitionStrategy} that * determines the there is before the next acquisition cycles begins and how many jobs * are to be acquired next. *

* * @author Daniel Meyer */ public class SequentialJobAcquisitionRunnable extends AcquireJobsRunnable { protected final JobExecutorLogger LOG = ProcessEngineLogger.JOB_EXECUTOR_LOGGER; protected JobAcquisitionContext acquisitionContext; public SequentialJobAcquisitionRunnable(JobExecutor jobExecutor) { super(jobExecutor); acquisitionContext = initializeAcquisitionContext(); } public synchronized void run() { LOG.startingToAcquireJobs(jobExecutor.getName()); JobAcquisitionStrategy acquisitionStrategy = initializeAcquisitionStrategy(); while (!isInterrupted) { acquisitionContext.reset(); acquisitionContext.setAcquisitionTime(System.currentTimeMillis()); Iterator engineIterator = jobExecutor.engineIterator(); // See https://jira.camunda.com/browse/CAM-9913 ClassLoader classLoaderBeforeExecution = ClassLoaderUtil.switchToProcessEngineClassloader(); try { while (engineIterator.hasNext()) { ProcessEngineImpl currentProcessEngine = engineIterator.next(); if (!jobExecutor.hasRegisteredEngine(currentProcessEngine)) { // if engine has been unregistered meanwhile continue; } AcquiredJobs acquiredJobs = acquireJobs(acquisitionContext, acquisitionStrategy, currentProcessEngine); executeJobs(acquisitionContext, currentProcessEngine, acquiredJobs); } } catch (Exception e) { LOG.exceptionDuringJobAcquisition(e); acquisitionContext.setAcquisitionException(e); } finally { ClassLoaderUtil.setContextClassloader(classLoaderBeforeExecution); } acquisitionContext.setJobAdded(isJobAdded); configureNextAcquisitionCycle(acquisitionContext, acquisitionStrategy); //The clear had to be done after the configuration, since a hint can be //appear in the suspend and the flag shouldn't be cleaned in this case. //The loop will restart after suspend with the isJobAdded flag and //reconfigure with this flag clearJobAddedNotification(); long waitTime = acquisitionStrategy.getWaitTime(); // wait the requested wait time minus the time that acquisition itself took // this makes the intervals of job acquisition more constant and therefore predictable waitTime = Math.max(0, (acquisitionContext.getAcquisitionTime() + waitTime) - System.currentTimeMillis()); suspendAcquisition(waitTime); } LOG.stoppedJobAcquisition(jobExecutor.getName()); } protected JobAcquisitionContext initializeAcquisitionContext() { return new JobAcquisitionContext(); } /** * Reconfigure the acquisition strategy based on the current cycle's acquisition context. * A strategy implementation may update internal data structure to calculate a different wait time * before the next cycle of acquisition is performed. */ protected void configureNextAcquisitionCycle(JobAcquisitionContext acquisitionContext, JobAcquisitionStrategy acquisitionStrategy) { acquisitionStrategy.reconfigure(acquisitionContext); } protected JobAcquisitionStrategy initializeAcquisitionStrategy() { return new BackoffJobAcquisitionStrategy(jobExecutor); } public JobAcquisitionContext getAcquisitionContext() { return acquisitionContext; } protected void executeJobs(JobAcquisitionContext context, ProcessEngineImpl currentProcessEngine, AcquiredJobs acquiredJobs) { // submit those jobs that were acquired in previous cycles but could not be scheduled for execution List> additionalJobs = context.getAdditionalJobsByEngine().get(currentProcessEngine.getName()); if (additionalJobs != null) { for (List jobBatch : additionalJobs) { LOG.executeJobs(currentProcessEngine.getName(), jobBatch); jobExecutor.executeJobs(jobBatch, currentProcessEngine); } } // submit those jobs that were acquired in the current cycle for (List jobIds : acquiredJobs.getJobIdBatches()) { LOG.executeJobs(currentProcessEngine.getName(), jobIds); jobExecutor.executeJobs(jobIds, currentProcessEngine); } } protected AcquiredJobs acquireJobs( JobAcquisitionContext context, JobAcquisitionStrategy acquisitionStrategy, ProcessEngineImpl currentProcessEngine) { CommandExecutor commandExecutor = currentProcessEngine.getProcessEngineConfiguration() .getCommandExecutorTxRequired(); int numJobsToAcquire = acquisitionStrategy.getNumJobsToAcquire(currentProcessEngine.getName()); AcquiredJobs acquiredJobs = null; if (numJobsToAcquire > 0) { jobExecutor.logAcquisitionAttempt(currentProcessEngine); acquiredJobs = commandExecutor.execute(jobExecutor.getAcquireJobsCmd(numJobsToAcquire)); } else { acquiredJobs = new AcquiredJobs(numJobsToAcquire); } context.submitAcquiredJobs(currentProcessEngine.getName(), acquiredJobs); jobExecutor.logAcquiredJobs(currentProcessEngine, acquiredJobs.size()); jobExecutor.logAcquisitionFailureJobs(currentProcessEngine, acquiredJobs.getNumberOfJobsFailedToLock()); LOG.acquiredJobs(currentProcessEngine.getName(), acquiredJobs); return acquiredJobs; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy