use of org.opencastproject.workflow.api.WorkflowParsingException in project opencast by opencast.
the class WorkflowServiceImpl method update.
/**
* {@inheritDoc}
*
* @see org.opencastproject.workflow.api.WorkflowService#update(org.opencastproject.workflow.api.WorkflowInstance)
*/
@Override
public void update(final WorkflowInstance workflowInstance) throws WorkflowException, UnauthorizedException {
final Lock lock = updateLock.get(workflowInstance.getId());
lock.lock();
try {
WorkflowInstance originalWorkflowInstance = null;
try {
originalWorkflowInstance = getWorkflowById(workflowInstance.getId());
} catch (NotFoundException e) {
// That's fine, it's a new workflow instance
}
if (originalWorkflowInstance != null) {
try {
assertPermission(originalWorkflowInstance, Permissions.Action.WRITE.toString());
} catch (MediaPackageException e) {
throw new WorkflowParsingException(e);
}
}
MediaPackage updatedMediaPackage = null;
try {
// Before we persist this, extract the metadata
updatedMediaPackage = workflowInstance.getMediaPackage();
populateMediaPackageMetadata(updatedMediaPackage);
String seriesId = updatedMediaPackage.getSeries();
if (seriesId != null && workflowInstance.getCurrentOperation() != null) {
// If the mediapackage contains a series, find the series ACLs and add the security information to the
// mediapackage
AccessControlList acl = seriesService.getSeriesAccessControl(seriesId);
Option<AccessControlList> activeSeriesAcl = authorizationService.getAcl(updatedMediaPackage, AclScope.Series);
if (activeSeriesAcl.isNone() || !AccessControlUtil.equals(activeSeriesAcl.get(), acl))
authorizationService.setAcl(updatedMediaPackage, AclScope.Series, acl);
}
} catch (SeriesException e) {
throw new WorkflowDatabaseException(e);
} catch (NotFoundException e) {
logger.warn("Metadata for mediapackage {} could not be updated because it wasn't found", updatedMediaPackage, e);
} catch (Exception e) {
logger.error("Metadata for mediapackage {} could not be updated", updatedMediaPackage, e);
}
// Synchronize the job status with the workflow
WorkflowState workflowState = workflowInstance.getState();
String xml;
try {
xml = WorkflowParser.toXml(workflowInstance);
} catch (Exception e) {
// Can't happen, since we are converting from an in-memory object
throw new IllegalStateException("In-memory workflow instance could not be serialized", e);
}
Job job = null;
try {
job = serviceRegistry.getJob(workflowInstance.getId());
job.setPayload(xml);
// Synchronize workflow and job state
switch(workflowState) {
case FAILED:
job.setStatus(Status.FAILED);
break;
case FAILING:
break;
case INSTANTIATED:
job.setDispatchable(true);
job.setStatus(Status.QUEUED);
break;
case PAUSED:
job.setStatus(Status.PAUSED);
break;
case RUNNING:
job.setStatus(Status.RUNNING);
break;
case STOPPED:
job.setStatus(Status.CANCELED);
break;
case SUCCEEDED:
job.setStatus(Status.FINISHED);
break;
default:
throw new IllegalStateException("Found a workflow state that is not handled");
}
} catch (ServiceRegistryException e) {
logger.error(e, "Unable to read workflow job %s from service registry", workflowInstance.getId());
throw new WorkflowDatabaseException(e);
} catch (NotFoundException e) {
logger.error("Job for workflow %s not found in service registry", workflowInstance.getId());
throw new WorkflowDatabaseException(e);
}
// Update both workflow and workflow job
try {
job = serviceRegistry.updateJob(job);
messageSender.sendObjectMessage(WorkflowItem.WORKFLOW_QUEUE, MessageSender.DestinationType.Queue, WorkflowItem.updateInstance(workflowInstance));
index(workflowInstance);
} catch (ServiceRegistryException e) {
logger.error("Update of workflow job %s in the service registry failed, service registry and workflow index may be out of sync", workflowInstance.getId());
throw new WorkflowDatabaseException(e);
} catch (NotFoundException e) {
logger.error("Job for workflow %s not found in service registry", workflowInstance.getId());
throw new WorkflowDatabaseException(e);
} catch (Exception e) {
logger.error("Update of workflow job %s in the service registry failed, service registry and workflow index may be out of sync", job.getId());
throw new WorkflowException(e);
}
if (workflowStatsCollect) {
workflowsStatistics.updateWorkflow(getBeanStatistics(), getHoldWorkflows());
}
try {
WorkflowInstance clone = WorkflowParser.parseWorkflowInstance(WorkflowParser.toXml(workflowInstance));
fireListeners(originalWorkflowInstance, clone);
} catch (Exception e) {
// Can't happen, since we are converting from an in-memory object
throw new IllegalStateException("In-memory workflow instance could not be serialized", e);
}
} finally {
lock.unlock();
}
}
use of org.opencastproject.workflow.api.WorkflowParsingException in project opencast by opencast.
the class LoggingWorkflowOperationHandler method start.
/**
* {@inheritDoc}
*
* @see org.opencastproject.workflow.api.WorkflowOperationHandler#start(org.opencastproject.workflow.api.WorkflowInstance,
* JobContext)
*/
@Override
public WorkflowOperationResult start(WorkflowInstance workflowInstance, JobContext context) throws WorkflowOperationException {
WorkflowOperationInstance operation = workflowInstance.getCurrentOperation();
String directoryPath = StringUtils.trimToNull(operation.getConfiguration("directory"));
File directory = null;
if (directoryPath != null) {
directory = new File(directoryPath);
try {
FileUtils.forceMkdir(directory);
} catch (IOException e) {
throw new WorkflowOperationException(String.format("Failed to create output directory '%s'", directoryPath), e);
}
}
boolean logMediaPackageJSON = BooleanUtils.toBoolean(operation.getConfiguration("mediapackage-json"));
boolean logMediaPackageXML = BooleanUtils.toBoolean(operation.getConfiguration("mediapackage-xml"));
boolean logWorkflowInstance = BooleanUtils.toBoolean(operation.getConfiguration("workflowinstance-xml"));
if (!(logMediaPackageJSON || logMediaPackageXML || logWorkflowInstance)) {
logMediaPackageJSON = true;
}
MediaPackage mediaPackage = workflowInstance.getMediaPackage();
// Log media package as JSON
if (logMediaPackageJSON) {
String filename = String.format("workflow-%d-%d-mediapackage-%s.json", workflowInstance.getId(), operation.getId(), mediaPackage.getIdentifier());
saveOrLog(MediaPackageParser.getAsJSON(mediaPackage), directory, filename);
}
// Log media package as XML
if (logMediaPackageXML) {
String filename = String.format("workflow-%d-%d-mediapackage-%s.xml", workflowInstance.getId(), operation.getId(), mediaPackage.getIdentifier());
saveOrLog(MediaPackageParser.getAsXml(mediaPackage), directory, filename);
}
// Log workflow instance as XML
if (logWorkflowInstance) {
String filename = String.format("workflow-%d-%d.xml", workflowInstance.getId(), operation.getId());
try {
saveOrLog(WorkflowParser.toXml(workflowInstance), directory, filename);
} catch (WorkflowParsingException e) {
throw new WorkflowOperationException(e);
}
}
// Continue with unmodified media package
return createResult(mediaPackage, Action.CONTINUE);
}
use of org.opencastproject.workflow.api.WorkflowParsingException 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.WorkflowParsingException 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.WorkflowParsingException in project opencast by opencast.
the class WorkflowServiceImpl method getWorkflowById.
/**
* {@inheritDoc}
*
* @see org.opencastproject.workflow.api.WorkflowService#getWorkflowById(long)
*/
@Override
public WorkflowInstanceImpl getWorkflowById(long id) throws WorkflowDatabaseException, NotFoundException, UnauthorizedException {
try {
Job job = serviceRegistry.getJob(id);
if (Status.DELETED.equals(job.getStatus())) {
throw new NotFoundException("Workflow '" + id + "' has been deleted");
}
if (JOB_TYPE.equals(job.getJobType()) && Operation.START_WORKFLOW.toString().equals(job.getOperation())) {
WorkflowInstanceImpl workflow = WorkflowParser.parseWorkflowInstance(job.getPayload());
assertPermission(workflow, Permissions.Action.READ.toString());
return workflow;
} else {
throw new NotFoundException("'" + id + "' is a job identifier, but it is not a workflow identifier");
}
} catch (WorkflowParsingException e) {
throw new IllegalStateException("The workflow job payload is malformed");
} catch (ServiceRegistryException e) {
throw new IllegalStateException("Error loading workflow job from the service registry");
} catch (MediaPackageException e) {
throw new IllegalStateException("Unable to read mediapackage from workflow " + id, e);
}
}
Aggregations