<commit_before>/*
 * Copyright 2015 Red Hat, Inc. and/or its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * 
 *      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.jbpm.services.ejb.timer;

import java.io.Serializable;
import java.util.Date;
import java.util.concurrent.Callable;

import javax.annotation.Resource;
import javax.ejb.ConcurrencyManagement;
import javax.ejb.ConcurrencyManagementType;
import javax.ejb.Lock;
import javax.ejb.LockType;
import javax.ejb.NoSuchObjectLocalException;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.ejb.Timeout;
import javax.ejb.Timer;
import javax.ejb.TimerConfig;

import org.drools.core.time.JobHandle;
import org.drools.core.time.impl.TimerJobInstance;
import org.jbpm.process.core.timer.TimerServiceRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Singleton
@Startup
@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
@Lock(LockType.READ)
public class EJBTimerScheduler {
	
	private static final Logger logger = LoggerFactory.getLogger(EJBTimerScheduler.class);

	private static final Integer OVERDUE_WAIT_TIME = Integer.parseInt(System.getProperty("org.jbpm.overdue.timer.wait", "20000"));
	
	@Resource
	private javax.ejb.TimerService timerService;
	
	@SuppressWarnings("unchecked")
	@Timeout
	public void executeTimerJob(Timer timer) {
		
		EjbTimerJob timerJob = (EjbTimerJob) timer.getInfo();
		logger.debug("About to execute timer for job {}", timerJob);
		TimerJobInstance timerJobInstance = timerJob.getTimerJobInstance();
		String timerServiceId = ((EjbGlobalJobHandle)timerJobInstance.getJobHandle()).getDeploymentId();
		
		// handle overdue timers as ejb timer service might start before all deployments are ready		
		long time = 0;
        while (TimerServiceRegistry.getInstance().get(timerServiceId) == null) {
        	logger.debug("waiting for timer service to be available, elapsed time {} ms", time);
            try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
            time += 500;
            
            if (time > OVERDUE_WAIT_TIME) {
            	logger.debug("No timer service found after waiting {} ms", time);
            	break;
            }
        }
		try {
			((Callable<Void>) timerJobInstance).call();
		} catch (Exception e) {
			logger.warn("Execution of time failed due to {}", e.getMessage(), e);
		}
	}
	
	public void internalSchedule(TimerJobInstance timerJobInstance) {
		TimerConfig config = new TimerConfig(new EjbTimerJob(timerJobInstance), true);
		Date expirationTime = timerJobInstance.getTrigger().nextFireTime();
		
		if (expirationTime != null) {
			timerService.createSingleActionTimer(expirationTime, config);
			logger.debug("Timer scheduled {} on {} scheduler service", timerJobInstance);
		} else {
			logger.info("Timer that was to be scheduled has already expired");
		}
	}
	
	public boolean removeJob(JobHandle jobHandle) {
		EjbGlobalJobHandle ejbHandle = (EjbGlobalJobHandle) jobHandle;<commit_msg>JBPM-5551 - Timer start event triggered every second cycle (#739)<commit_after>/*
 * Copyright 2015 Red Hat, Inc. and/or its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * 
 *      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.jbpm.services.ejb.timer;

import java.io.Serializable;
import java.util.Date;
import java.util.concurrent.Callable;

import javax.annotation.Resource;
import javax.ejb.ConcurrencyManagement;
import javax.ejb.ConcurrencyManagementType;
import javax.ejb.Lock;
import javax.ejb.LockType;
import javax.ejb.NoSuchObjectLocalException;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.ejb.Timeout;
import javax.ejb.Timer;
import javax.ejb.TimerConfig;

import org.drools.core.time.JobHandle;
import org.drools.core.time.impl.TimerJobInstance;
import org.jbpm.process.core.timer.TimerServiceRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Singleton
@Startup
@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
@Lock(LockType.READ)
public class EJBTimerScheduler {
	
	private static final Logger logger = LoggerFactory.getLogger(EJBTimerScheduler.class);

	private static final Integer OVERDUE_WAIT_TIME = Integer.parseInt(System.getProperty("org.jbpm.overdue.timer.wait", "20000"));
	
	@Resource
	private javax.ejb.TimerService timerService;
	
	@SuppressWarnings("unchecked")
	@Timeout
	public void executeTimerJob(Timer timer) {
		
		EjbTimerJob timerJob = (EjbTimerJob) timer.getInfo();
		logger.debug("About to execute timer for job {}", timerJob);
		TimerJobInstance timerJobInstance = timerJob.getTimerJobInstance();
		String timerServiceId = ((EjbGlobalJobHandle)timerJobInstance.getJobHandle()).getDeploymentId();
		
		// handle overdue timers as ejb timer service might start before all deployments are ready		
		long time = 0;
        while (TimerServiceRegistry.getInstance().get(timerServiceId) == null) {
        	logger.debug("waiting for timer service to be available, elapsed time {} ms", time);
            try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
            time += 500;
            
            if (time > OVERDUE_WAIT_TIME) {
            	logger.debug("No timer service found after waiting {} ms", time);
            	break;
            }
        }
		try {
			((Callable<Void>) timerJobInstance).call();
		} catch (Exception e) {
			logger.warn("Execution of time failed due to {}", e.getMessage(), e);
		}
	}
	
	public void internalSchedule(TimerJobInstance timerJobInstance) {
		TimerConfig config = new TimerConfig(new EjbTimerJob(timerJobInstance), true);
		Date expirationTime = timerJobInstance.getTrigger().hasNextFireTime();
		logger.debug("Timer expiration date is {}", expirationTime);
		if (expirationTime != null) {
			timerService.createSingleActionTimer(expirationTime, config);
			logger.debug("Timer scheduled {} on {} scheduler service", timerJobInstance);
		} else {
			logger.info("Timer that was to be scheduled has already expired");
		}
	}
	
	public boolean removeJob(JobHandle jobHandle) {
		EjbGlobalJobHandle ejbHandle = (EjbGlobalJobHandle) jobHandle;
{'fraction_non_alphanumeric': 0.09955783768363999, 'fraction_numerical': 0.007274283269148481, 'mean_word_length': 4.288084464555053, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '540443', 'n_tokens_mistral': 2150, 'n_tokens_neox': 1987, 'n_words': 556}