Search in sources :

Example 26 with WorkflowQuery

use of org.opencastproject.workflow.api.WorkflowQuery 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!");
    }
}
Also used : WorkflowDatabaseException(org.opencastproject.workflow.api.WorkflowDatabaseException) WorkflowQuery(org.opencastproject.workflow.api.WorkflowQuery) WorkflowStateException(org.opencastproject.workflow.api.WorkflowStateException) UnauthorizedException(org.opencastproject.security.api.UnauthorizedException) NotFoundException(org.opencastproject.util.NotFoundException) WorkflowInstance(org.opencastproject.workflow.api.WorkflowInstance) Date(java.util.Date) WorkflowParsingException(org.opencastproject.workflow.api.WorkflowParsingException)

Example 27 with WorkflowQuery

use of org.opencastproject.workflow.api.WorkflowQuery 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();
    }
}
Also used : WorkflowSet(org.opencastproject.workflow.api.WorkflowSet) MediaPackageException(org.opencastproject.mediapackage.MediaPackageException) WorkflowQuery(org.opencastproject.workflow.api.WorkflowQuery) WorkflowState(org.opencastproject.workflow.api.WorkflowInstance.WorkflowState) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) ArrayList(java.util.ArrayList) NotFoundException(org.opencastproject.util.NotFoundException) WorkflowInstance(org.opencastproject.workflow.api.WorkflowInstance) ServiceRegistryException(org.opencastproject.serviceregistry.api.ServiceRegistryException) Lock(java.util.concurrent.locks.Lock) WorkflowDatabaseException(org.opencastproject.workflow.api.WorkflowDatabaseException) WorkflowOperationInstance(org.opencastproject.workflow.api.WorkflowOperationInstance) WorkflowStateException(org.opencastproject.workflow.api.WorkflowStateException) WorkflowParsingException(org.opencastproject.workflow.api.WorkflowParsingException)

Example 28 with WorkflowQuery

use of org.opencastproject.workflow.api.WorkflowQuery 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();
    }
}
Also used : WorkflowSet(org.opencastproject.workflow.api.WorkflowSet) WorkflowQuery(org.opencastproject.workflow.api.WorkflowQuery) User(org.opencastproject.security.api.User) Organization(org.opencastproject.security.api.Organization) DefaultOrganization(org.opencastproject.security.api.DefaultOrganization) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) ArrayList(java.util.ArrayList) Collections.mkString(org.opencastproject.util.data.Collections.mkString) WorkflowInstance(org.opencastproject.workflow.api.WorkflowInstance) ServiceRegistryException(org.opencastproject.serviceregistry.api.ServiceRegistryException) UndispatchableJobException(org.opencastproject.serviceregistry.api.UndispatchableJobException) WorkflowOperationException(org.opencastproject.workflow.api.WorkflowOperationException) IOException(java.io.IOException) ConfigurationException(org.osgi.service.cm.ConfigurationException) SeriesException(org.opencastproject.series.api.SeriesException) InvalidSyntaxException(org.osgi.framework.InvalidSyntaxException) WorkflowException(org.opencastproject.workflow.api.WorkflowException) MediaPackageException(org.opencastproject.mediapackage.MediaPackageException) WorkflowParsingException(org.opencastproject.workflow.api.WorkflowParsingException) UnauthorizedException(org.opencastproject.security.api.UnauthorizedException) NotFoundException(org.opencastproject.util.NotFoundException) WorkflowDatabaseException(org.opencastproject.workflow.api.WorkflowDatabaseException) WorkflowStateException(org.opencastproject.workflow.api.WorkflowStateException) Lock(java.util.concurrent.locks.Lock) WorkflowDatabaseException(org.opencastproject.workflow.api.WorkflowDatabaseException) WorkflowInstanceImpl(org.opencastproject.workflow.api.WorkflowInstanceImpl) UnauthorizedException(org.opencastproject.security.api.UnauthorizedException) Job(org.opencastproject.job.api.Job)

Example 29 with WorkflowQuery

use of org.opencastproject.workflow.api.WorkflowQuery 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;
}
Also used : WorkflowSet(org.opencastproject.workflow.api.WorkflowSet) WorkflowQuery(org.opencastproject.workflow.api.WorkflowQuery) ResumableWorkflowOperationHandler(org.opencastproject.workflow.api.ResumableWorkflowOperationHandler) UndispatchableJobException(org.opencastproject.serviceregistry.api.UndispatchableJobException) WorkflowDefinition(org.opencastproject.workflow.api.WorkflowDefinition) NotFoundException(org.opencastproject.util.NotFoundException) Collections.mkString(org.opencastproject.util.data.Collections.mkString) WorkflowInstance(org.opencastproject.workflow.api.WorkflowInstance) WorkflowDatabaseException(org.opencastproject.workflow.api.WorkflowDatabaseException) ResumableWorkflowOperationHandler(org.opencastproject.workflow.api.ResumableWorkflowOperationHandler) WorkflowOperationHandler(org.opencastproject.workflow.api.WorkflowOperationHandler) UnauthorizedException(org.opencastproject.security.api.UnauthorizedException) WorkflowParsingException(org.opencastproject.workflow.api.WorkflowParsingException)

Example 30 with WorkflowQuery

use of org.opencastproject.workflow.api.WorkflowQuery in project opencast by opencast.

the class WorkflowServiceSolrIndexTest method testBuildNegativeStatesQuery.

/**
 * Tests whether the query is built using AND rather than OR when supplying multiple excluded states
 */
@Test
public void testBuildNegativeStatesQuery() throws Exception {
    WorkflowQuery q = new WorkflowQuery().withSeriesId("series1").withoutState(WorkflowState.RUNNING).withoutState(WorkflowState.PAUSED);
    String solrQuery = dao.createQuery(q, Permissions.Action.READ.toString(), true);
    String expected = "oc_org:mh_default_org AND seriesid:series1 AND (-state:running AND -state:paused AND *:*)";
    assertEquals(expected, solrQuery);
}
Also used : WorkflowQuery(org.opencastproject.workflow.api.WorkflowQuery) Test(org.junit.Test)

Aggregations

WorkflowQuery (org.opencastproject.workflow.api.WorkflowQuery)30 WorkflowSet (org.opencastproject.workflow.api.WorkflowSet)18 Test (org.junit.Test)17 WorkflowInstance (org.opencastproject.workflow.api.WorkflowInstance)16 NotFoundException (org.opencastproject.util.NotFoundException)9 WorkflowDatabaseException (org.opencastproject.workflow.api.WorkflowDatabaseException)8 ArrayList (java.util.ArrayList)5 UnauthorizedException (org.opencastproject.security.api.UnauthorizedException)5 WorkflowOperationInstance (org.opencastproject.workflow.api.WorkflowOperationInstance)4 WorkflowParsingException (org.opencastproject.workflow.api.WorkflowParsingException)4 CopyOnWriteArrayList (java.util.concurrent.CopyOnWriteArrayList)3 GET (javax.ws.rs.GET)3 Path (javax.ws.rs.Path)3 Produces (javax.ws.rs.Produces)3 Organization (org.opencastproject.security.api.Organization)3 User (org.opencastproject.security.api.User)3 RestQuery (org.opencastproject.util.doc.rest.RestQuery)3 WorkflowException (org.opencastproject.workflow.api.WorkflowException)3 WorkflowStateException (org.opencastproject.workflow.api.WorkflowStateException)3 IOException (java.io.IOException)2