/*
* Copyright 2013 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.
* 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.jbpm.executor.impl.jpa;
import org.drools.core.command.impl.ExecutableCommand;
import org.jbpm.executor.RequeueAware;
import org.jbpm.executor.entities.ErrorInfo;
import org.jbpm.executor.entities.RequestInfo;
import org.kie.api.executor.ExecutorAdminService;
import org.kie.api.executor.STATUS;
import org.kie.api.runtime.CommandExecutor;
import org.kie.api.runtime.Context;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
import java.util.List;
/**
* Default implementation of <code>ExecutorAdminService</code> backed with JPA
* IMPORTANT: please keep all classes from package org.jbpm.shared.services.impl as FQCN
* inside method body to avoid exception logged by CDI when used with in memory mode
*/
public class ExecutorRequestAdminServiceImpl implements ExecutorAdminService, RequeueAware {
private CommandExecutor commandService;
public ExecutorRequestAdminServiceImpl() {
}
public void setCommandService(CommandExecutor commandService ) {
this.commandService = commandService;
}
/**
* {@inheritDoc}
*/
public int clearAllRequests() {
List<RequestInfo> requests =
commandService.execute(new org.jbpm.shared.services.impl.commands.QueryStringCommand<List<RequestInfo>>("select r from RequestInfo r"));
commandService.execute(new org.jbpm.shared.services.impl.commands.RemoveObjectCommand(requests.toArray()));
return requests.size();
}
/**
* {@inheritDoc}
*/
public int clearAllErrors() {
List<ErrorInfo> errors =
commandService.execute(new org.jbpm.shared.services.impl.commands.QueryStringCommand<List<ErrorInfo>>("select e from ErrorInfo e"));
commandService.execute(new org.jbpm.shared.services.impl.commands.RemoveObjectCommand(errors.toArray()));
return errors.size();
}
@Override
public void requeue(Long olderThan) {
commandService.execute(new RequeueRunningJobsCommand(olderThan));
}
@Override
public void requeueById(Long requestId) {
commandService.execute(new RequeueRunningJobCommand(requestId));
}
private class RequeueRunningJobsCommand implements ExecutableCommand<Void> {
private Logger logger = LoggerFactory.getLogger(RequeueRunningJobsCommand.class);
private static final long serialVersionUID = 8670412133363766161L;
private Long upperLimitTime;
public RequeueRunningJobsCommand(Long maxRunningTime) {
this.upperLimitTime = System.currentTimeMillis() - maxRunningTime;
}
@SuppressWarnings("unchecked")
@Override
public Void execute(Context context) {
List<RequestInfo> requests = null;
try {
org.jbpm.shared.services.impl.JpaPersistenceContext ctx = (org.jbpm.shared.services.impl.JpaPersistenceContext) context;
requests = ctx.queryInTransaction("RunningRequests", List.class);
for (RequestInfo request : requests) {
if (request != null && maxRunningTimeExceeded(request.getTime())) {
logger.info("Requeing request as the time exceeded for its running state id : {}, key : {}, start time : {}, max time {}",
request.getId(), request.getKey(), request.getTime(), new Date(upperLimitTime));
request.setStatus(STATUS.QUEUED);
ctx.merge(request);
}
}
} catch (Exception e) {
logger.warn("Error while trying to requeue jobs that runs for too long {}", e.getMessage());
}
return null;
}
private boolean maxRunningTimeExceeded(Date actualDate) {
if (actualDate.getTime() < upperLimitTime) {
return true;
}
return false;
}
}
private class RequeueRunningJobCommand implements ExecutableCommand<Void> {
private Logger logger = LoggerFactory.getLogger(RequeueRunningJobCommand.class);
private static final long serialVersionUID = 8670412133363766161L;
private Long requestId;
public RequeueRunningJobCommand(Long id) {
this.requestId = id;
}
@Override
public Void execute(Context context) {
try {
org.jbpm.shared.services.impl.JpaPersistenceContext ctx = (org.jbpm.shared.services.impl.JpaPersistenceContext) context;
RequestInfo request = ctx.find(RequestInfo.class, requestId);
if (request != null && request.getStatus() != STATUS.CANCELLED
&& request.getStatus() != STATUS.DONE) {
logger.info("Requeing request with id : {}, key : {}, start time : {}", request.getId(), request.getKey(), request.getTime());
request.setStatus(STATUS.QUEUED);
ctx.merge(request);
} else {
throw new IllegalArgumentException("Retrying completed or cancelled job is not allowed (job id " + requestId +")");
}
} catch (Exception e) {
logger.warn("Error while trying to requeue jobs that runs for too long {}", e.getMessage());
}
return null;
}
}
}