use of org.opencastproject.workflow.api.WorkflowQuery in project opencast by opencast.
the class AbstractEventEndpoint method getEventWorkflows.
@GET
@Path("{eventId}/workflows.json")
@Produces(MediaType.APPLICATION_JSON)
@RestQuery(name = "geteventworkflows", description = "Returns all the data related to the workflows tab in the event details modal as JSON", returnDescription = "All the data related to the event workflows tab as JSON", pathParameters = { @RestParameter(name = "eventId", description = "The event id", isRequired = true, type = RestParameter.Type.STRING) }, reponses = { @RestResponse(description = "Returns all the data related to the event workflows tab as JSON", responseCode = HttpServletResponse.SC_OK), @RestResponse(description = "No event with this identifier was found.", responseCode = HttpServletResponse.SC_NOT_FOUND) })
public Response getEventWorkflows(@PathParam("eventId") String id) throws UnauthorizedException, SearchIndexException, JobEndpointException {
Opt<Event> optEvent = getIndexService().getEvent(id, getIndex());
if (optEvent.isNone())
return notFound("Cannot find an event with id '%s'.", id);
try {
if (!optEvent.get().hasRecordingStarted()) {
List<Field> fields = new ArrayList<Field>();
Map<String, String> workflowConfig = getSchedulerService().getWorkflowConfig(id);
for (Entry<String, String> entry : workflowConfig.entrySet()) {
fields.add(f(entry.getKey(), v(entry.getValue(), Jsons.BLANK)));
}
Map<String, String> agentConfiguration = getSchedulerService().getCaptureAgentConfiguration(id);
return okJson(obj(f("workflowId", v(agentConfiguration.get(CaptureParameters.INGEST_WORKFLOW_DEFINITION), Jsons.BLANK)), f("configuration", obj(fields))));
} else {
return okJson(getJobService().getTasksAsJSON(new WorkflowQuery().withMediaPackage(id)));
}
} catch (NotFoundException e) {
return notFound("Cannot find workflows for event %s", id);
} catch (SchedulerException e) {
logger.error("Unable to get workflow data for event with id {}", id);
throw new WebApplicationException(e, SC_INTERNAL_SERVER_ERROR);
}
}
use of org.opencastproject.workflow.api.WorkflowQuery in project opencast by opencast.
the class JobEndpoint method getTasks.
@GET
@Path("tasks.json")
@Produces(MediaType.APPLICATION_JSON)
@RestQuery(description = "Returns the list of tasks", name = "tasks", restParameters = { @RestParameter(name = "limit", description = "The maximum number of items to return per page", isRequired = false, type = RestParameter.Type.INTEGER), @RestParameter(name = "offset", description = "The offset", isRequired = false, type = RestParameter.Type.INTEGER), @RestParameter(name = "status", isRequired = false, description = "Filter results by workflows' current state", type = STRING), @RestParameter(name = "q", isRequired = false, description = "Filter results by free text query", type = STRING), @RestParameter(name = "seriesId", isRequired = false, description = "Filter results by series identifier", type = STRING), @RestParameter(name = "seriesTitle", isRequired = false, description = "Filter results by series title", type = STRING), @RestParameter(name = "creator", isRequired = false, description = "Filter results by the mediapackage's creator", type = STRING), @RestParameter(name = "contributor", isRequired = false, description = "Filter results by the mediapackage's contributor", type = STRING), @RestParameter(name = "fromdate", isRequired = false, description = "Filter results by workflow start date.", type = STRING), @RestParameter(name = "todate", isRequired = false, description = "Filter results by workflow start date.", type = STRING), @RestParameter(name = "language", isRequired = false, description = "Filter results by mediapackage's language.", type = STRING), @RestParameter(name = "title", isRequired = false, description = "Filter results by mediapackage's title.", type = STRING), @RestParameter(name = "subject", isRequired = false, description = "Filter results by mediapackage's subject.", type = STRING), @RestParameter(name = "workflow", isRequired = false, description = "Filter results by workflow definition.", type = STRING), @RestParameter(name = "operation", isRequired = false, description = "Filter results by workflows' current operation.", type = STRING), @RestParameter(name = "sort", isRequired = false, description = "The sort order. May include any " + "of the following: DATE_CREATED, TITLE, SERIES_TITLE, SERIES_ID, MEDIA_PACKAGE_ID, WORKFLOW_DEFINITION_ID, CREATOR, " + "CONTRIBUTOR, LANGUAGE, LICENSE, SUBJECT. The suffix must be :ASC for ascending or :DESC for descending sort order (e.g. TITLE:DESC).", type = STRING) }, reponses = { @RestResponse(description = "Returns the list of tasks from Opencast", responseCode = HttpServletResponse.SC_OK) }, returnDescription = "The list of tasks as JSON")
public Response getTasks(@QueryParam("limit") final int limit, @QueryParam("offset") final int offset, @QueryParam("status") List<String> states, @QueryParam("q") String text, @QueryParam("seriesId") String seriesId, @QueryParam("seriesTitle") String seriesTitle, @QueryParam("creator") String creator, @QueryParam("contributor") String contributor, @QueryParam("fromdate") String fromDate, @QueryParam("todate") String toDate, @QueryParam("language") String language, @QueryParam("title") String title, @QueryParam("subject") String subject, @QueryParam("workflowdefinition") String workflowDefinitionId, @QueryParam("mp") String mediapackageId, @QueryParam("operation") List<String> currentOperations, @QueryParam("sort") String sort, @Context HttpHeaders headers) throws JobEndpointException {
WorkflowQuery query = new WorkflowQuery();
query.withStartPage(offset);
query.withCount(limit);
// Add filters
query.withText(text);
query.withSeriesId(seriesId);
query.withSeriesTitle(seriesTitle);
query.withSubject(subject);
query.withMediaPackage(mediapackageId);
query.withCreator(creator);
query.withContributor(contributor);
try {
query.withDateAfter(SolrUtils.parseDate(fromDate));
} catch (ParseException e) {
logger.error("Not able to parse the date {}: {}", fromDate, e.getMessage());
}
try {
query.withDateBefore(SolrUtils.parseDate(toDate));
} catch (ParseException e) {
logger.error("Not able to parse the date {}: {}", fromDate, e.getMessage());
}
query.withLanguage(language);
query.withTitle(title);
query.withWorkflowDefintion(workflowDefinitionId);
if (states != null && states.size() > 0) {
try {
for (String state : states) {
if (StringUtils.isBlank(state)) {
continue;
} else if (state.startsWith(NEGATE_PREFIX)) {
query.withoutState(WorkflowState.valueOf(state.substring(1).toUpperCase()));
} else {
query.withState(WorkflowState.valueOf(state.toUpperCase()));
}
}
} catch (IllegalArgumentException e) {
logger.debug("Unknown workflow state.", e);
}
}
if (currentOperations != null && currentOperations.size() > 0) {
for (String op : currentOperations) {
if (StringUtils.isBlank(op)) {
continue;
}
if (op.startsWith(NEGATE_PREFIX)) {
query.withoutCurrentOperation(op.substring(1));
} else {
query.withCurrentOperation(op);
}
}
}
// Sorting
if (StringUtils.isNotBlank(sort)) {
try {
SortCriterion sortCriterion = RestUtils.parseSortQueryParameter(sort).iterator().next();
Sort sortKey = Sort.valueOf(sortCriterion.getFieldName().toUpperCase());
boolean ascending = SearchQuery.Order.Ascending == sortCriterion.getOrder() || SearchQuery.Order.None == sortCriterion.getOrder();
query.withSort(sortKey, ascending);
} catch (WebApplicationException ex) {
logger.warn("Failed to parse sort criterion \"{}\", invalid format.", sort);
} catch (IllegalArgumentException ex) {
logger.warn("Can not apply sort criterion \"{}\", no field with this name.", sort);
}
}
JObject json;
try {
json = getTasksAsJSON(query);
} catch (NotFoundException e) {
return NOT_FOUND;
}
return Response.ok(stream(serializer.fn.toJson(json)), MediaType.APPLICATION_JSON_TYPE).build();
}
use of org.opencastproject.workflow.api.WorkflowQuery in project opencast by opencast.
the class IndexServiceImpl method getCurrentWorkflowInstance.
@Override
public Opt<WorkflowInstance> getCurrentWorkflowInstance(String mpId) throws IndexServiceException {
WorkflowQuery query = new WorkflowQuery().withMediaPackage(mpId);
WorkflowSet workflowInstances;
try {
workflowInstances = workflowService.getWorkflowInstances(query);
if (workflowInstances.size() == 0) {
logger.info("No workflow instance found for mediapackage {}.", mpId);
return Opt.none();
}
} catch (WorkflowDatabaseException e) {
logger.error("Unable to get workflows for event {} because {}", mpId, getStackTrace(e));
throw new IndexServiceException("Unable to get current workflow for event " + mpId);
}
// Get the newest workflow instance
// TODO This presuppose knowledge of the Database implementation and should be fixed sooner or later!
WorkflowInstance workflowInstance = workflowInstances.getItems()[0];
for (WorkflowInstance instance : workflowInstances.getItems()) {
if (instance.getId() > workflowInstance.getId())
workflowInstance = instance;
}
return Opt.some(workflowInstance);
}
use of org.opencastproject.workflow.api.WorkflowQuery in project opencast by opencast.
the class IndexServiceImpl method removeEvent.
@Override
public boolean removeEvent(String id) throws NotFoundException, UnauthorizedException {
boolean unauthorizedScheduler = false;
boolean notFoundScheduler = false;
boolean removedScheduler = true;
try {
schedulerService.removeEvent(id);
} catch (NotFoundException e) {
notFoundScheduler = true;
} catch (UnauthorizedException e) {
unauthorizedScheduler = true;
} catch (SchedulerException e) {
removedScheduler = false;
logger.error("Unable to remove the event '{}' from scheduler service: {}", id, getStackTrace(e));
}
boolean unauthorizedWorkflow = false;
boolean notFoundWorkflow = false;
boolean removedWorkflow = true;
try {
WorkflowQuery workflowQuery = new WorkflowQuery().withMediaPackage(id);
WorkflowSet workflowSet = workflowService.getWorkflowInstances(workflowQuery);
if (workflowSet.size() == 0)
notFoundWorkflow = true;
for (WorkflowInstance instance : workflowSet.getItems()) {
workflowService.stop(instance.getId());
workflowService.remove(instance.getId());
}
} catch (NotFoundException e) {
notFoundWorkflow = true;
} catch (UnauthorizedException e) {
unauthorizedWorkflow = true;
} catch (WorkflowDatabaseException e) {
removedWorkflow = false;
logger.error("Unable to remove the event '{}' because removing workflow failed: {}", id, getStackTrace(e));
} catch (WorkflowException e) {
removedWorkflow = false;
logger.error("Unable to remove the event '{}' because removing workflow failed: {}", id, getStackTrace(e));
}
boolean unauthorizedArchive = false;
boolean notFoundArchive = false;
boolean removedArchive = true;
try {
final AQueryBuilder q = assetManager.createQuery();
final Predicate p = q.organizationId().eq(securityService.getOrganization().getId()).and(q.mediaPackageId(id));
final AResult r = q.select(q.nothing()).where(p).run();
if (r.getSize() > 0)
q.delete(DEFAULT_OWNER, q.snapshot()).where(p).run();
} catch (AssetManagerException e) {
if (e.getCause() instanceof UnauthorizedException) {
unauthorizedArchive = true;
} else if (e.getCause() instanceof NotFoundException) {
notFoundArchive = true;
} else {
removedArchive = false;
logger.error("Unable to remove the event '{}' from the archive: {}", id, getStackTrace(e));
}
}
if (notFoundScheduler && notFoundWorkflow && notFoundArchive)
throw new NotFoundException("Event id " + id + " not found.");
if (unauthorizedScheduler || unauthorizedWorkflow || unauthorizedArchive)
throw new UnauthorizedException("Not authorized to remove event id " + id);
try {
eventCommentService.deleteComments(id);
} catch (EventCommentException e) {
logger.error("Unable to remove comments for event '{}': {}", id, getStackTrace(e));
}
return removedScheduler && removedWorkflow && removedArchive;
}
use of org.opencastproject.workflow.api.WorkflowQuery in project opencast by opencast.
the class IndexServiceImpl method startAddAssetWorkflow.
/**
* Parses the processing information, including the workflowDefinitionId, from the metadataJson and starts the
* workflow with the passed mediapackage.
*
* TODO NOTE: This checks for running workflows, then takes a snapshot prior to starting a new workflow. This causes a
* potential race condition:
*
* 1. An existing workflow is running, the add asset workflow cannot start.
*
* 2. The snapshot(4x) archive(3x) is saved and the new workflow is started.
*
* 3. Possible race condition: No running workflow, a snapshot is saved but the workflow cannot start because another
* workflow has started between the time of checking and starting running.
*
* 4. If race condition: the Admin UI shows error that the workflow could not start.
*
* 5. If race condition: The interim snapshot(4x) archive(3x) is updated(4x-3x) by the running workflow's snapshots
* and resolves the inconsistency, eventually.
*
* Example of processing json:
*
* ...., "processing": { "workflow": "full", "configuration": { "videoPreview": "false", "trimHold": "false",
* "captionHold": "false", "archiveOp": "true", "publishEngage": "true", "publishHarvesting": "true" } }, ....
*
* @param metadataJson
* @param mp
* @return the created workflow instance id
* @throws IndexServiceException
*/
private String startAddAssetWorkflow(JSONObject metadataJson, MediaPackage mediaPackage) throws IndexServiceException {
String wfId = null;
String mpId = mediaPackage.getIdentifier().toString();
JSONObject processing = (JSONObject) metadataJson.get("processing");
if (processing == null)
throw new IllegalArgumentException("No processing field in metadata");
String workflowDefId = (String) processing.get("workflow");
if (workflowDefId == null)
throw new IllegalArgumentException("No workflow definition field in processing metadata");
JSONObject configJson = (JSONObject) processing.get("configuration");
try {
// 1. Check if any active workflows are running for this mediapackage id
WorkflowSet workflowSet = workflowService.getWorkflowInstances(new WorkflowQuery().withMediaPackage(mpId));
for (WorkflowInstance wf : Arrays.asList(workflowSet.getItems())) {
if (wf.isActive()) {
logger.warn("Unable to start new workflow '{}' on archived media package '{}', existing workfow {} is running", workflowDefId, mediaPackage, wf.getId());
throw new IllegalArgumentException("A workflow is already active for mp " + mpId + ", cannot start this workflow.");
}
}
// 2. Save the snapshot
assetManager.takeSnapshot(DEFAULT_OWNER, mediaPackage);
// 3. start the new workflow on the snapshot
// Workflow params are assumed to be String (not mixed with Number)
Map<String, String> params = new HashMap<String, String>();
if (configJson != null) {
for (Object key : configJson.keySet()) {
params.put((String) key, (String) configJson.get(key));
}
}
Set<String> mpIds = new HashSet<String>();
mpIds.add(mpId);
final Workflows workflows = new Workflows(assetManager, workspace, workflowService);
List<WorkflowInstance> wfList = workflows.applyWorkflowToLatestVersion(mpIds, ConfiguredWorkflow.workflow(workflowService.getWorkflowDefinitionById(workflowDefId), params)).toList();
wfId = wfList.size() > 0 ? Long.toString(wfList.get(0).getId()) : "Unknown";
logger.info("Asset update and publish workflow {} scheduled for mp {}", wfId, mpId);
} catch (AssetManagerException e) {
logger.warn("Unable to start workflow '{}' on archived media package '{}': {}", workflowDefId, mediaPackage, getStackTrace(e));
throw new IndexServiceException("Unable to start workflow " + workflowDefId + " on " + mpId);
} catch (WorkflowDatabaseException e) {
logger.warn("Unable to load workflow '{}' from workflow service: {}", wfId, getStackTrace(e));
} catch (NotFoundException e) {
logger.warn("Workflow '{}' not found", wfId);
}
return wfId;
}
Aggregations