use of org.opencastproject.workflow.api.WorkflowDatabaseException in project opencast by opencast.
the class WorkflowServiceImpl method cleanupWorkflowInstances.
@Override
public synchronized void cleanupWorkflowInstances(int buffer, WorkflowState state) throws UnauthorizedException, WorkflowDatabaseException {
logger.info("Start cleaning up workflow instances older than {} days with status '{}'", buffer, state);
int instancesCleaned = 0;
int cleaningFailed = 0;
WorkflowQuery query = new WorkflowQuery().withState(state).withDateBefore(DateUtils.addDays(new Date(), -buffer)).withCount(Integer.MAX_VALUE);
for (WorkflowInstance workflowInstance : getWorkflowInstances(query).getItems()) {
try {
remove(workflowInstance.getId());
instancesCleaned++;
} catch (WorkflowDatabaseException e) {
throw e;
} catch (UnauthorizedException e) {
throw e;
} catch (NotFoundException e) {
// Since we are in a cleanup operation, we don't have to care about NotFoundExceptions
logger.debug("Workflow instance '{}' could not be removed: {}", workflowInstance.getId(), ExceptionUtils.getStackTrace(e));
} catch (WorkflowParsingException e) {
logger.warn("Workflow instance '{}' could not be removed: {}", workflowInstance.getId(), ExceptionUtils.getStackTrace(e));
cleaningFailed++;
} catch (WorkflowStateException e) {
logger.warn("Workflow instance '{}' could not be removed: {}", workflowInstance.getId(), ExceptionUtils.getStackTrace(e));
cleaningFailed++;
}
}
if (instancesCleaned == 0 && cleaningFailed == 0) {
logger.info("No workflow instances found to clean up");
return;
}
if (instancesCleaned > 0)
logger.info("Cleaned up '%d' workflow instances", instancesCleaned);
if (cleaningFailed > 0) {
logger.warn("Cleaning failed for '%d' workflow instances", cleaningFailed);
throw new WorkflowDatabaseException("Unable to clean all workflow instances, see logs!");
}
}
use of org.opencastproject.workflow.api.WorkflowDatabaseException in project opencast by opencast.
the class WorkflowServiceImpl method remove.
/**
* {@inheritDoc}
*
* @see org.opencastproject.workflow.api.WorkflowService#remove(long)
*/
@Override
public void remove(long workflowInstanceId) throws WorkflowDatabaseException, NotFoundException, UnauthorizedException, WorkflowParsingException, WorkflowStateException {
final Lock lock = this.lock.get(workflowInstanceId);
lock.lock();
try {
WorkflowQuery query = new WorkflowQuery();
query.withId(Long.toString(workflowInstanceId));
WorkflowSet workflows = index.getWorkflowInstances(query, Permissions.Action.READ.toString(), false);
if (workflows.size() == 1) {
WorkflowInstance instance = workflows.getItems()[0];
WorkflowInstance.WorkflowState state = instance.getState();
if (state != WorkflowState.SUCCEEDED && state != WorkflowState.FAILED && state != WorkflowState.STOPPED)
throw new WorkflowStateException("Workflow instance with state '" + state + "' cannot be removed. Only states SUCCEEDED, FAILED & STOPPED are allowed");
try {
assertPermission(instance, Permissions.Action.WRITE.toString());
} catch (MediaPackageException e) {
throw new WorkflowParsingException(e);
}
// First, remove temporary files DO THIS BEFORE REMOVING FROM INDEX
try {
removeTempFiles(instance);
} catch (NotFoundException e) {
// If the files aren't their anymore, we don't have to cleanup up them :-)
logger.debug("Temporary files of workflow instance %d seem to be gone already...", workflowInstanceId);
}
// Second, remove jobs related to a operation which belongs to the workflow instance
List<WorkflowOperationInstance> operations = instance.getOperations();
List<Long> jobsToDelete = new ArrayList<>();
for (WorkflowOperationInstance op : operations) {
if (op.getId() != null) {
long workflowOpId = op.getId();
if (workflowOpId != workflowInstanceId) {
jobsToDelete.add(workflowOpId);
}
}
}
try {
serviceRegistry.removeJobs(jobsToDelete);
} catch (ServiceRegistryException e) {
logger.warn("Problems while removing jobs related to workflow operations '%s': %s", jobsToDelete, e.getMessage());
} catch (NotFoundException e) {
logger.debug("No jobs related to one of the workflow operations '%s' found in the service registry", jobsToDelete);
}
// Third, remove workflow instance job itself
try {
serviceRegistry.removeJobs(Collections.singletonList(workflowInstanceId));
messageSender.sendObjectMessage(WorkflowItem.WORKFLOW_QUEUE, MessageSender.DestinationType.Queue, WorkflowItem.deleteInstance(workflowInstanceId, instance));
} catch (ServiceRegistryException e) {
logger.warn("Problems while removing workflow instance job '%d': %s", workflowInstanceId, ExceptionUtils.getStackTrace(e));
} catch (NotFoundException e) {
logger.info("No workflow instance job '%d' found in the service registry", workflowInstanceId);
}
// At last, remove workflow instance from the index
try {
index.remove(workflowInstanceId);
} catch (NotFoundException e) {
// This should never happen, because we got workflow instance by querying the index...
logger.warn("Workflow instance could not be removed from index: %s", ExceptionUtils.getStackTrace(e));
}
} else if (workflows.size() == 0) {
throw new NotFoundException("Workflow instance with id '" + Long.toString(workflowInstanceId) + "' could not be found");
} else {
throw new WorkflowDatabaseException("More than one workflow found with id: " + Long.toString(workflowInstanceId));
}
} finally {
lock.unlock();
}
}
use of org.opencastproject.workflow.api.WorkflowDatabaseException in project opencast by opencast.
the class WorkflowServiceImpl method activate.
/**
* Activate this service implementation via the OSGI service component runtime.
*
* @param componentContext
* the component context
*/
public void activate(ComponentContext componentContext) {
this.componentContext = componentContext;
executorService = (ThreadPoolExecutor) Executors.newCachedThreadPool();
try {
logger.info("Generating JMX workflow statistics");
workflowsStatistics = new WorkflowsStatistics(getBeanStatistics(), getHoldWorkflows());
jmxBeans.add(JmxUtil.registerMXBean(workflowsStatistics, JMX_WORKFLOWS_STATISTICS_TYPE));
} catch (WorkflowDatabaseException e) {
logger.error("Error registarting JMX statistic beans", e);
}
super.activate();
logger.info("Activate Workflow service");
}
use of org.opencastproject.workflow.api.WorkflowDatabaseException in project opencast by opencast.
the class WorkflowServiceImpl method runWorkflowOperation.
/**
* Executes the workflow's current operation.
*
* @param workflow
* the workflow
* @param properties
* the properties that are passed in on resume
* @return the processed workflow operation
* @throws WorkflowException
* if there is a problem processing the workflow
*/
protected WorkflowOperationInstance runWorkflowOperation(WorkflowInstance workflow, Map<String, String> properties) throws WorkflowException, UnauthorizedException {
WorkflowOperationInstance processingOperation = workflow.getCurrentOperation();
if (processingOperation == null)
throw new IllegalStateException("Workflow '" + workflow + "' has no operation to run");
// Keep the current state for later reference, it might have been changed from the outside
WorkflowState initialState = workflow.getState();
// Execute the operation handler
WorkflowOperationHandler operationHandler = selectOperationHandler(processingOperation);
WorkflowOperationWorker worker = new WorkflowOperationWorker(operationHandler, workflow, properties, this);
workflow = worker.execute();
// The workflow has been serialized/deserialized in between, so we need to refresh the reference
int currentOperationPosition = processingOperation.getPosition();
processingOperation = workflow.getOperations().get(currentOperationPosition);
Long currentOperationJobId = processingOperation.getId();
try {
updateOperationJob(currentOperationJobId, processingOperation.getState());
} catch (NotFoundException e) {
throw new IllegalStateException("Unable to find a job that has already been running");
} catch (ServiceRegistryException e) {
throw new WorkflowDatabaseException(e);
}
// Move on to the next workflow operation
WorkflowOperationInstance currentOperation = workflow.getCurrentOperation();
// Is the workflow done?
if (currentOperation == null) {
// If we are in failing mode, we were simply working off an error handling workflow
if (FAILING.equals(workflow.getState())) {
workflow.setState(FAILED);
} else // switched to paused while processing the error handling workflow extension
if (!FAILED.equals(workflow.getState())) {
workflow.setState(SUCCEEDED);
for (WorkflowOperationInstance op : workflow.getOperations()) {
if (op.getState().equals(WorkflowOperationInstance.OperationState.FAILED)) {
if (op.isFailWorkflowOnException()) {
workflow.setState(FAILED);
break;
}
}
}
}
// Save the updated workflow to the database
logger.debug("%s has %s", workflow, workflow.getState());
update(workflow);
} else {
// Somebody might have set the workflow to "paused" from the outside, so take a look a the database first
WorkflowState dbWorkflowState = null;
try {
dbWorkflowState = getWorkflowById(workflow.getId()).getState();
} catch (WorkflowDatabaseException e) {
throw new IllegalStateException("The workflow with ID " + workflow.getId() + " can not be accessed in the database", e);
} catch (NotFoundException e) {
throw new IllegalStateException("The workflow with ID " + workflow.getId() + " can not be found in the database", e);
} catch (UnauthorizedException e) {
throw new IllegalStateException("The workflow with ID " + workflow.getId() + " can not be read", e);
}
// If somebody changed the workflow state from the outside, that state should take precedence
if (!dbWorkflowState.equals(initialState)) {
logger.info("Workflow state for %s was changed to '%s' from the outside", workflow, dbWorkflowState);
workflow.setState(dbWorkflowState);
}
// Save the updated workflow to the database
Job job = null;
switch(workflow.getState()) {
case FAILED:
update(workflow);
break;
case FAILING:
case RUNNING:
try {
job = serviceRegistry.createJob(JOB_TYPE, Operation.START_OPERATION.toString(), Arrays.asList(Long.toString(workflow.getId())), null, false, null, WORKFLOW_JOB_LOAD);
currentOperation.setId(job.getId());
update(workflow);
job.setStatus(Status.QUEUED);
job.setDispatchable(true);
job = serviceRegistry.updateJob(job);
} catch (ServiceRegistryException e) {
throw new WorkflowDatabaseException(e);
} catch (NotFoundException e) {
// this should be impossible
throw new IllegalStateException("Unable to find a job that was just created");
}
break;
case PAUSED:
case STOPPED:
case SUCCEEDED:
update(workflow);
break;
case INSTANTIATED:
update(workflow);
throw new IllegalStateException("Impossible workflow state found during processing");
default:
throw new IllegalStateException("Unkown workflow state found during processing");
}
}
return processingOperation;
}
use of org.opencastproject.workflow.api.WorkflowDatabaseException in project opencast by opencast.
the class WorkflowServiceImpl method resume.
/**
* {@inheritDoc}
*
* @see org.opencastproject.workflow.api.WorkflowService#resume(long, Map)
*/
@Override
public WorkflowInstance resume(long workflowInstanceId, Map<String, String> properties) throws WorkflowException, NotFoundException, IllegalStateException, UnauthorizedException {
WorkflowInstance workflowInstance = getWorkflowById(workflowInstanceId);
if (!WorkflowState.PAUSED.equals(workflowInstance.getState()))
throw new IllegalStateException("Can not resume a workflow where the current state is not in paused");
workflowInstance = updateConfiguration(workflowInstance, properties);
update(workflowInstance);
WorkflowOperationInstance currentOperation = workflowInstance.getCurrentOperation();
// Is the workflow done?
if (currentOperation == null) {
// Let's make sure we didn't miss any failed operation, since the workflow state could have been
// switched to paused while processing the error handling workflow extension
workflowInstance.setState(SUCCEEDED);
for (WorkflowOperationInstance op : workflowInstance.getOperations()) {
if (op.getState().equals(WorkflowOperationInstance.OperationState.FAILED)) {
if (op.isFailWorkflowOnException()) {
workflowInstance.setState(FAILED);
break;
}
}
}
// Save the resumed workflow to the database
logger.debug("%s has %s", workflowInstance, workflowInstance.getState());
update(workflowInstance);
return workflowInstance;
}
// certain operations. In the latter case, there is no current paused operation.
if (OperationState.INSTANTIATED.equals(currentOperation.getState())) {
try {
// the operation has its own job. Update that too.
Job operationJob = serviceRegistry.createJob(JOB_TYPE, Operation.START_OPERATION.toString(), Arrays.asList(Long.toString(workflowInstanceId)), null, false, null, WORKFLOW_JOB_LOAD);
// this method call is publicly visible, so it doesn't necessarily go through the accept method. Set the
// workflow state manually.
workflowInstance.setState(RUNNING);
currentOperation.setId(operationJob.getId());
// update the workflow and its associated job
update(workflowInstance);
// Now set this job to be queued so it can be dispatched
operationJob.setStatus(Status.QUEUED);
operationJob.setDispatchable(true);
operationJob = serviceRegistry.updateJob(operationJob);
return workflowInstance;
} catch (ServiceRegistryException e) {
throw new WorkflowDatabaseException(e);
}
}
Long operationJobId = workflowInstance.getCurrentOperation().getId();
if (operationJobId == null)
throw new IllegalStateException("Can not resume a workflow where the current operation has no associated id");
// Set the current operation's job to queued, so it gets picked up again
Job workflowJob;
try {
workflowJob = serviceRegistry.getJob(workflowInstanceId);
workflowJob.setStatus(Status.RUNNING);
workflowJob.setPayload(WorkflowParser.toXml(workflowInstance));
workflowJob = serviceRegistry.updateJob(workflowJob);
Job operationJob = serviceRegistry.getJob(operationJobId);
operationJob.setStatus(Status.QUEUED);
operationJob.setDispatchable(true);
if (properties != null) {
Properties props = new Properties();
props.putAll(properties);
ByteArrayOutputStream out = new ByteArrayOutputStream();
props.store(out, null);
List<String> newArguments = new ArrayList<String>(operationJob.getArguments());
newArguments.add(new String(out.toByteArray(), "UTF-8"));
operationJob.setArguments(newArguments);
}
operationJob = serviceRegistry.updateJob(operationJob);
} catch (ServiceRegistryException e) {
throw new WorkflowDatabaseException(e);
} catch (IOException e) {
throw new WorkflowParsingException("Unable to parse workflow and/or workflow properties");
}
return workflowInstance;
}
Aggregations