use of org.opencastproject.workflow.api.WorkflowOperationInstance in project opencast by opencast.
the class TagByDublinCoreTermWOHTest method setUp.
@Before
public void setUp() throws Exception {
MediaPackageBuilder builder = MediaPackageBuilderFactory.newInstance().newMediaPackageBuilder();
mp = builder.loadFromXml(this.getClass().getResourceAsStream("/archive_mediapackage.xml"));
mp.getCatalog("catalog-1").setURI(this.getClass().getResource("/dublincore.xml").toURI());
// set up the handler
operationHandler = new TagByDublinCoreTermWOH();
// Initialize the workflow
instance = new WorkflowInstanceImpl();
operation = new WorkflowOperationInstanceImpl("test", OperationState.INSTANTIATED);
List<WorkflowOperationInstance> ops = new ArrayList<WorkflowOperationInstance>();
ops.add(operation);
instance.setOperations(ops);
instance.setMediaPackage(mp);
workspace = EasyMock.createNiceMock(Workspace.class);
EasyMock.expect(workspace.read(EasyMock.anyObject())).andAnswer(() -> getClass().getResourceAsStream("/dublincore.xml"));
EasyMock.replay(workspace);
operationHandler.setWorkspace(workspace);
}
use of org.opencastproject.workflow.api.WorkflowOperationInstance in project opencast by opencast.
the class TagWorkflowOperationHandler 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 {
MediaPackage mediaPackage = workflowInstance.getMediaPackage();
WorkflowOperationInstance currentOperation = workflowInstance.getCurrentOperation();
String configuredSourceFlavors = StringUtils.trimToEmpty(currentOperation.getConfiguration(SOURCE_FLAVORS_PROPERTY));
String configuredSourceTags = StringUtils.trimToEmpty(currentOperation.getConfiguration(SOURCE_TAGS_PROPERTY));
String configuredTargetFlavor = StringUtils.trimToNull(currentOperation.getConfiguration(TARGET_FLAVOR_PROPERTY));
String configuredTargetTags = StringUtils.trimToEmpty(currentOperation.getConfiguration(TARGET_TAGS_PROPERTY));
boolean copy = BooleanUtils.toBoolean(currentOperation.getConfiguration(COPY_PROPERTY));
if (copy) {
logger.info("Retagging mediapackage elements as a copy");
} else {
logger.info("Retagging mediapackage elements");
}
String[] sourceTags = StringUtils.split(configuredSourceTags, ",");
String[] targetTags = StringUtils.split(configuredTargetTags, ",");
String[] sourceFlavors = StringUtils.split(configuredSourceFlavors, ",");
SimpleElementSelector elementSelector = new SimpleElementSelector();
for (String flavor : sourceFlavors) {
elementSelector.addFlavor(MediaPackageElementFlavor.parseFlavor(flavor));
}
List<String> removeTags = new ArrayList<String>();
List<String> addTags = new ArrayList<String>();
List<String> overrideTags = new ArrayList<String>();
for (String tag : targetTags) {
if (tag.startsWith(MINUS)) {
removeTags.add(tag);
} else if (tag.startsWith(PLUS)) {
addTags.add(tag);
} else {
overrideTags.add(tag);
}
}
for (String tag : sourceTags) {
elementSelector.addTag(tag);
}
Collection<MediaPackageElement> elements = elementSelector.select(mediaPackage, false);
for (MediaPackageElement e : elements) {
MediaPackageElement element = e;
if (copy) {
element = (MediaPackageElement) e.clone();
element.setIdentifier(null);
// use the same URI as the original
element.setURI(e.getURI());
}
if (configuredTargetFlavor != null)
element.setFlavor(MediaPackageElementFlavor.parseFlavor(configuredTargetFlavor));
if (overrideTags.size() > 0) {
element.clearTags();
for (String tag : overrideTags) {
element.addTag(tag);
}
} else {
for (String tag : removeTags) {
element.removeTag(tag.substring(MINUS.length()));
}
for (String tag : addTags) {
element.addTag(tag.substring(PLUS.length()));
}
}
if (copy)
mediaPackage.addDerived(element, e);
}
return createResult(mediaPackage, Action.CONTINUE);
}
use of org.opencastproject.workflow.api.WorkflowOperationInstance 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.WorkflowOperationInstance in project opencast by opencast.
the class WorkflowServiceImpl method handleFailedOperation.
/**
* Handles the workflow for a failing operation.
*
* @param workflow
* the workflow
* @param currentOperation
* the failing workflow operation instance
* @throws WorkflowDatabaseException
* If the exception handler workflow is not found
*/
private void handleFailedOperation(WorkflowInstance workflow, WorkflowOperationInstance currentOperation) throws WorkflowDatabaseException {
String errorDefId = currentOperation.getExceptionHandlingWorkflow();
// Adjust the workflow state according to the setting on the operation
if (currentOperation.isFailWorkflowOnException()) {
if (StringUtils.isBlank(errorDefId)) {
workflow.setState(FAILED);
} else {
workflow.setState(FAILING);
// Remove the rest of the original workflow
int currentOperationPosition = workflow.getOperations().indexOf(currentOperation);
List<WorkflowOperationInstance> operations = new ArrayList<WorkflowOperationInstance>();
operations.addAll(workflow.getOperations().subList(0, currentOperationPosition + 1));
workflow.setOperations(operations);
// Determine the current workflow configuration
Map<String, String> configuration = new HashMap<String, String>();
for (String configKey : workflow.getConfigurationKeys()) {
configuration.put(configKey, workflow.getConfiguration(configKey));
}
// Append the operations
WorkflowDefinition errorDef = null;
try {
errorDef = getWorkflowDefinitionById(errorDefId);
workflow.extend(errorDef);
workflow.setOperations(updateConfiguration(workflow, configuration).getOperations());
} catch (NotFoundException notFoundException) {
throw new IllegalStateException("Unable to find the error workflow definition '" + errorDefId + "'");
}
}
}
// Fail the current operation
currentOperation.setState(OperationState.FAILED);
}
use of org.opencastproject.workflow.api.WorkflowOperationInstance 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;
}
Aggregations