use of org.opencastproject.workflow.api.WorkflowDatabaseException in project opencast by opencast.
the class WorkflowServiceImpl method start.
/**
* {@inheritDoc}
*
* @see org.opencastproject.workflow.api.WorkflowService#start(org.opencastproject.workflow.api.WorkflowDefinition,
* org.opencastproject.mediapackage.MediaPackage, Long, java.util.Map)
*/
@Override
public WorkflowInstance start(WorkflowDefinition workflowDefinition, MediaPackage sourceMediaPackage, Long parentWorkflowId, Map<String, String> properties) throws WorkflowDatabaseException, WorkflowParsingException, NotFoundException {
// We have to synchronize per media package to avoid starting multiple simultaneous workflows for one media package.
final Lock lock = mediaPackageLocks.get(sourceMediaPackage.getIdentifier().toString());
lock.lock();
try {
logger.startUnitOfWork();
if (workflowDefinition == null)
throw new IllegalArgumentException("workflow definition must not be null");
if (sourceMediaPackage == null)
throw new IllegalArgumentException("mediapackage must not be null");
for (List<String> errors : MediaPackageSupport.sanityCheck(sourceMediaPackage)) {
throw new IllegalArgumentException("Insane media package cannot be processed: " + mkString(errors, "; "));
}
if (parentWorkflowId != null) {
try {
// Let NotFoundException bubble up
getWorkflowById(parentWorkflowId);
} catch (UnauthorizedException e) {
throw new IllegalArgumentException("Parent workflow " + parentWorkflowId + " not visible to this user");
}
} else {
WorkflowQuery wfq = new WorkflowQuery().withMediaPackage(sourceMediaPackage.getIdentifier().compact());
WorkflowSet mpWorkflowInstances = getWorkflowInstances(wfq);
if (mpWorkflowInstances.size() > 0) {
for (WorkflowInstance wfInstance : mpWorkflowInstances.getItems()) {
if (wfInstance.isActive())
throw new IllegalStateException(String.format("Can't start workflow '%s' for media package '%s' because another workflow is currently active.", workflowDefinition.getTitle(), sourceMediaPackage.getIdentifier().compact()));
}
}
}
// Get the current user
User currentUser = securityService.getUser();
if (currentUser == null)
throw new SecurityException("Current user is unknown");
// Get the current organization
Organization organization = securityService.getOrganization();
if (organization == null)
throw new SecurityException("Current organization is unknown");
WorkflowInstance workflowInstance = new WorkflowInstanceImpl(workflowDefinition, sourceMediaPackage, parentWorkflowId, currentUser, organization, properties);
workflowInstance = updateConfiguration(workflowInstance, properties);
// Create and configure the workflow instance
try {
// Create a new job for this workflow instance
String workflowDefinitionXml = WorkflowParser.toXml(workflowDefinition);
String workflowInstanceXml = WorkflowParser.toXml(workflowInstance);
String mediaPackageXml = MediaPackageParser.getAsXml(sourceMediaPackage);
List<String> arguments = new ArrayList<String>();
arguments.add(workflowDefinitionXml);
arguments.add(mediaPackageXml);
if (parentWorkflowId != null || properties != null) {
String parentWorkflowIdString = (parentWorkflowId != null) ? parentWorkflowId.toString() : NULL_PARENT_ID;
arguments.add(parentWorkflowIdString);
}
if (properties != null) {
arguments.add(mapToString(properties));
}
Job job = serviceRegistry.createJob(JOB_TYPE, Operation.START_WORKFLOW.toString(), arguments, workflowInstanceXml, false, null, WORKFLOW_JOB_LOAD);
// Have the workflow take on the job's identity
workflowInstance.setId(job.getId());
// Add the workflow to the search index and have the job enqueued for dispatch.
// Update also sets ACL and mediapackage metadata
update(workflowInstance);
return workflowInstance;
} catch (Throwable t) {
try {
workflowInstance.setState(FAILED);
update(workflowInstance);
} catch (Exception failureToFail) {
logger.warn(failureToFail, "Unable to update workflow to failed state");
}
throw new WorkflowDatabaseException(t);
}
} finally {
logger.endUnitOfWork();
lock.unlock();
}
}
use of org.opencastproject.workflow.api.WorkflowDatabaseException in project opencast by opencast.
the class WorkflowServiceImpl method isReadyToAccept.
/**
* {@inheritDoc}
*
* If we are already running the maximum number of workflows, don't accept another START_WORKFLOW job
*
* @see org.opencastproject.job.api.AbstractJobProducer#isReadyToAccept(org.opencastproject.job.api.Job)
*/
@Override
public boolean isReadyToAccept(Job job) throws ServiceRegistryException, UndispatchableJobException {
String operation = job.getOperation();
// Only restrict execution of new jobs
if (!Operation.START_WORKFLOW.toString().equals(operation))
return true;
// If the first operation is guaranteed to pause, run the job.
if (job.getArguments().size() > 1 && job.getArguments().get(0) != null) {
try {
WorkflowDefinition workflowDef = WorkflowParser.parseWorkflowDefinition(job.getArguments().get(0));
if (workflowDef.getOperations().size() > 0) {
String firstOperationId = workflowDef.getOperations().get(0).getId();
WorkflowOperationHandler handler = getWorkflowOperationHandler(firstOperationId);
if (handler instanceof ResumableWorkflowOperationHandler) {
if (((ResumableWorkflowOperationHandler) handler).isAlwaysPause()) {
return true;
}
}
}
} catch (WorkflowParsingException e) {
throw new UndispatchableJobException(job + " is not a proper job to start a workflow", e);
}
}
WorkflowInstance workflow = null;
WorkflowSet workflowInstances = null;
String mediaPackageId = null;
// Fetch all workflows that are running with the current mediapackage
try {
workflow = getWorkflowById(job.getId());
mediaPackageId = workflow.getMediaPackage().getIdentifier().toString();
workflowInstances = getWorkflowInstances(new WorkflowQuery().withMediaPackage(workflow.getMediaPackage().getIdentifier().toString()).withState(RUNNING).withState(PAUSED).withState(FAILING));
} catch (NotFoundException e) {
logger.error("Trying to start workflow with id %s but no corresponding instance is available from the workflow service", job.getId());
throw new UndispatchableJobException(e);
} catch (UnauthorizedException e) {
logger.error("Authorization denied while requesting to loading workflow instance %s: %s", job.getId(), e.getMessage());
throw new UndispatchableJobException(e);
} catch (WorkflowDatabaseException e) {
logger.error("Error loading workflow instance %s: %s", job.getId(), e.getMessage());
return false;
}
// If more than one workflow is running working on this mediapackage, then we don't start this one
boolean toomany = workflowInstances.size() > 1;
// Make sure we are not excluding ourselves
toomany |= workflowInstances.size() == 1 && workflow.getId() != workflowInstances.getItems()[0].getId();
// Avoid running multiple workflows with same media package id at the same time
if (toomany) {
if (!delayedWorkflows.contains(workflow.getId())) {
logger.info("Delaying start of workflow %s, another workflow on media package %s is still running", workflow.getId(), mediaPackageId);
delayedWorkflows.add(workflow.getId());
}
return false;
}
return true;
}
use of org.opencastproject.workflow.api.WorkflowDatabaseException in project opencast by opencast.
the class WorkflowServiceSolrIndex method countWorkflowInstances.
/**
* {@inheritDoc}
*
* @see org.opencastproject.workflow.impl.WorkflowServiceIndex#countWorkflowInstances(org.opencastproject.workflow.api.WorkflowInstance.WorkflowState,
* java.lang.String)
*/
@Override
public long countWorkflowInstances(WorkflowState state, String operation) throws WorkflowDatabaseException {
StringBuilder query = new StringBuilder();
// Consider the workflow state
if (state != null) {
query.append(STATE_KEY).append(":").append(escapeQueryChars(state.toString()));
}
// Consider the current operation
if (StringUtils.isNotBlank(operation)) {
if (query.length() > 0)
query.append(" AND ");
query.append(OPERATION_KEY).append(":").append(escapeQueryChars(operation));
}
// We want all available workflows for this organization
String orgId = securityService.getOrganization().getId();
if (query.length() > 0)
query.append(" AND ");
query.append(ORG_KEY).append(":").append(escapeQueryChars(orgId));
appendSolrAuthFragment(query, Permissions.Action.READ.toString());
try {
QueryResponse response = solrServer.query(new SolrQuery(query.toString()));
return response.getResults().getNumFound();
} catch (SolrServerException e) {
throw new WorkflowDatabaseException(e);
}
}
use of org.opencastproject.workflow.api.WorkflowDatabaseException in project opencast by opencast.
the class WorkflowServiceSolrIndex method getWorkflowInstances.
/**
* {@inheritDoc}
*
* @see org.opencastproject.workflow.impl.WorkflowServiceIndex#getWorkflowInstances(org.opencastproject.workflow.api.WorkflowQuery,
* String, boolean)
*/
@Override
public WorkflowSet getWorkflowInstances(WorkflowQuery query, String action, boolean applyPermissions) throws WorkflowDatabaseException {
// default to 20 items if not specified
int count = query.getCount() > 0 ? (int) query.getCount() : 20;
int startIndex = query.getStartPage() > 0 ? (int) query.getStartPage() * count : (int) query.getStartIndex();
SolrQuery solrQuery = new SolrQuery();
solrQuery.setRows(count);
solrQuery.setStart(startIndex);
String solrQueryString = createQuery(query, action, applyPermissions);
solrQuery.setQuery(solrQueryString);
if (query.getSort() != null) {
ORDER order = query.isSortAscending() ? ORDER.asc : ORDER.desc;
solrQuery.addSortField(getSortField(query.getSort()) + "_sort", order);
}
if (!Sort.DATE_CREATED.equals(query.getSort())) {
solrQuery.addSortField(getSortField(Sort.DATE_CREATED) + "_sort", ORDER.desc);
}
long totalHits;
long time = System.currentTimeMillis();
WorkflowSetImpl set = null;
try {
QueryResponse response = solrServer.query(solrQuery);
SolrDocumentList items = response.getResults();
long searchTime = System.currentTimeMillis() - time;
totalHits = items.getNumFound();
set = new WorkflowSetImpl();
set.setPageSize(count);
set.setTotalCount(totalHits);
set.setStartPage(query.getStartPage());
set.setSearchTime(searchTime);
// Iterate through the results
for (SolrDocument doc : items) {
String xml = (String) doc.get(XML_KEY);
try {
set.addItem(WorkflowParser.parseWorkflowInstance(xml));
} catch (Exception e) {
throw new IllegalStateException("can not parse workflow xml", e);
}
}
} catch (Exception e) {
throw new WorkflowDatabaseException(e);
}
long totalTime = System.currentTimeMillis() - time;
logger.debug("Workflow query took {} ms", totalTime);
return set;
}
use of org.opencastproject.workflow.api.WorkflowDatabaseException in project opencast by opencast.
the class WorkflowServiceSolrIndex method activate.
/**
* Activates the index by configuring solr with the server url that must have been set previously.
*/
public void activate(String systemUserName) {
// Set up the solr server
if (solrServerUrl != null) {
solrServer = SolrServerFactory.newRemoteInstance(solrServerUrl);
} else {
try {
setupSolr(new File(solrRoot));
} catch (IOException e) {
throw new IllegalStateException("Unable to connect to solr at " + solrRoot, e);
} catch (SolrServerException e) {
throw new IllegalStateException("Unable to connect to solr at " + solrRoot, e);
}
}
// If the solr is empty, add all of the existing workflows
long instancesInSolr = 0;
try {
instancesInSolr = count();
} catch (WorkflowDatabaseException e) {
throw new IllegalStateException(e);
}
if (instancesInSolr == 0) {
logger.info("The workflow index is empty, looking for workflows to index");
// this may be a new index, so get all of the existing workflows and index them
List<String> workflowPayloads;
try {
workflowPayloads = serviceRegistry.getJobPayloads(WorkflowServiceImpl.Operation.START_WORKFLOW.toString());
} catch (ServiceRegistryException e) {
logger.error("Unable to load the workflows jobs: {}", e.getMessage());
throw new ServiceException(e.getMessage());
}
final int total = workflowPayloads.size();
if (total == 0) {
logger.info("No workflows found. Repopulating index finished.");
return;
}
logger.info("Populating the workflow index with {} workflows", total);
int current = 0;
for (String payload : workflowPayloads) {
current++;
WorkflowInstance instance = null;
try {
instance = WorkflowParser.parseWorkflowInstance(payload);
Organization organization = instance.getOrganization();
securityService.setOrganization(organization);
securityService.setUser(SecurityUtil.createSystemUser(systemUserName, organization));
index(instance);
} catch (WorkflowParsingException | WorkflowDatabaseException e) {
logger.warn("Skipping restoring of workflow {}", payload, e);
}
if (current % 100 == 0) {
logger.info("Indexing workflow {}/{} ({} percent done)", current, total, current * 100 / total);
}
}
logger.info("Finished populating the workflow search index");
}
}
Aggregations