use of co.cask.cdap.api.ProgramStatus in project cdap by caskdata.
the class ProgramScheduleStoreDataset method modifySchedulesTriggeredByDeletedProgram.
/**
* Update all schedules that can be triggered by the given deleted program. A schedule will be removed if
* the only {@link ProgramStatusTrigger} in it is triggered by the deleted program. Schedules with composite triggers
* will be updated if the composite trigger can still be satisfied after the program is deleted, otherwise the
* schedules will be deleted.
*
* @param programId the program id for which to delete the schedules
* @return the IDs of the schedules that were deleted
*/
public List<ScheduleId> modifySchedulesTriggeredByDeletedProgram(ProgramId programId) {
List<ScheduleId> deleted = new ArrayList<>();
Set<ProgramScheduleRecord> scheduleRecords = new HashSet<>();
for (ProgramStatus status : ProgramStatus.values()) {
scheduleRecords.addAll(findSchedules(Schedulers.triggerKeyForProgramStatus(programId, status)));
}
for (ProgramScheduleRecord scheduleRecord : scheduleRecords) {
ProgramSchedule schedule = scheduleRecord.getSchedule();
try {
deleteSchedule(schedule.getScheduleId());
} catch (NotFoundException e) {
// this should never happen
LOG.warn("Failed to delete the schedule '{}' triggered by '{}', skip this schedule.", schedule.getScheduleId(), programId, e);
continue;
}
if (schedule.getTrigger() instanceof AbstractSatisfiableCompositeTrigger) {
// get the updated composite trigger by removing the program status trigger of the given program
Trigger updatedTrigger = ((AbstractSatisfiableCompositeTrigger) schedule.getTrigger()).getTriggerWithDeletedProgram(programId);
if (updatedTrigger == null) {
deleted.add(schedule.getScheduleId());
continue;
}
// if the updated composite trigger is not null, add the schedule back with updated composite trigger
try {
addScheduleWithStatus(new ProgramSchedule(schedule.getName(), schedule.getDescription(), schedule.getProgramId(), schedule.getProperties(), updatedTrigger, schedule.getConstraints(), schedule.getTimeoutMillis()), scheduleRecord.getMeta().getStatus(), System.currentTimeMillis());
} catch (AlreadyExistsException e) {
// this should never happen
LOG.warn("Failed to add the schedule '{}' triggered by '{}' with updated trigger '{}', " + "skip adding this schedule.", schedule.getScheduleId(), programId, updatedTrigger, e);
}
} else {
deleted.add(schedule.getScheduleId());
}
}
return deleted;
}
use of co.cask.cdap.api.ProgramStatus in project cdap by caskdata.
the class ProgramStatusTrigger method getTriggerSatisfiedResult.
/**
* Helper method to return a result from the given supplier if the trigger is satisfied with the given notifications,
* or return the default result if the trigger is not satisfied.
*
* @param notifications notifications used to determine whether the trigger is satisfied
* @param defaultResult the default result to return if the trigger is not satisfied
* @param function the function to get result from if the trigger is satisfied
* @param <T> type of the result to be returned
* @return a result of type T
*/
private <T> T getTriggerSatisfiedResult(List<Notification> notifications, T defaultResult, Function<ProgramRunInfo, T> function) {
for (Notification notification : notifications) {
if (!Notification.Type.PROGRAM_STATUS.equals(notification.getNotificationType())) {
continue;
}
String programRunIdString = notification.getProperties().get(ProgramOptionConstants.PROGRAM_RUN_ID);
String programRunStatusString = notification.getProperties().get(ProgramOptionConstants.PROGRAM_STATUS);
// Ignore notifications which specify an invalid programRunId or programStatus
if (programRunIdString == null || programRunStatusString == null) {
continue;
}
ProgramStatus programStatus;
try {
programStatus = ProgramRunStatus.toProgramStatus(ProgramRunStatus.valueOf(programRunStatusString));
} catch (IllegalArgumentException e) {
// Return silently, this happens for statuses that are not meant to be scheduled
continue;
}
ProgramRunId programRunId = GSON.fromJson(programRunIdString, ProgramRunId.class);
ProgramId triggeringProgramId = programRunId.getParent();
if (this.programId.equals(triggeringProgramId) && programStatuses.contains(programStatus)) {
return function.apply(new ProgramRunInfo(programStatus, programRunId));
}
}
return defaultResult;
}
use of co.cask.cdap.api.ProgramStatus in project cdap by caskdata.
the class SmartWorkflow method destroy.
@Override
public void destroy() {
WorkflowContext workflowContext = getContext();
PipelineRuntime pipelineRuntime = new PipelineRuntime(workflowContext, workflowMetrics);
// Execute the post actions only if pipeline is not running in preview mode.
if (!workflowContext.getDataTracer(PostAction.PLUGIN_TYPE).isEnabled()) {
for (Map.Entry<String, PostAction> endingActionEntry : postActions.entrySet()) {
String name = endingActionEntry.getKey();
PostAction action = endingActionEntry.getValue();
StageSpec stageSpec = stageSpecs.get(name);
BatchActionContext context = new WorkflowBackedActionContext(workflowContext, pipelineRuntime, stageSpec);
try {
action.run(context);
} catch (Throwable t) {
LOG.error("Error while running post action {}.", name, t);
}
}
}
// publish all alerts
for (Map.Entry<String, AlertPublisher> alertPublisherEntry : alertPublishers.entrySet()) {
String name = alertPublisherEntry.getKey();
AlertPublisher alertPublisher = alertPublisherEntry.getValue();
PartitionedFileSet alertConnector = workflowContext.getDataset(name);
try (CloseableIterator<Alert> alerts = new AlertReader(alertConnector.getPartitions(PartitionFilter.ALWAYS_MATCH))) {
if (!alerts.hasNext()) {
continue;
}
StageMetrics stageMetrics = new DefaultStageMetrics(workflowMetrics, name);
StageSpec stageSpec = stageSpecs.get(name);
AlertPublisherContext alertContext = new DefaultAlertPublisherContext(pipelineRuntime, stageSpec, workflowContext, workflowContext.getAdmin());
alertPublisher.initialize(alertContext);
TrackedIterator<Alert> trackedIterator = new TrackedIterator<>(alerts, stageMetrics, Constants.Metrics.RECORDS_IN);
alertPublisher.publish(trackedIterator);
} catch (Exception e) {
LOG.warn("Stage {} had errors publishing alerts. Alerts may not have been published.", name, e);
} finally {
try {
alertPublisher.destroy();
} catch (Exception e) {
LOG.warn("Error destroying alert publisher for stage {}", name, e);
}
}
}
ProgramStatus status = getContext().getState().getStatus();
if (status == ProgramStatus.FAILED) {
WRAPPERLOGGER.error("Pipeline '{}' failed.", getContext().getApplicationSpecification().getName());
} else {
WRAPPERLOGGER.info("Pipeline '{}' {}.", getContext().getApplicationSpecification().getName(), status == ProgramStatus.COMPLETED ? "succeeded" : status.name().toLowerCase());
}
MacroEvaluator macroEvaluator = new DefaultMacroEvaluator(pipelineRuntime.getArguments(), workflowContext.getLogicalStartTime(), workflowContext, workflowContext.getNamespace());
// Get resolved plugin properties
Map<String, Map<String, String>> resolvedProperties = new HashMap<>();
for (StageSpec spec : stageSpecs.values()) {
String stageName = spec.getName();
resolvedProperties.put(stageName, workflowContext.getPluginProperties(stageName, macroEvaluator).getProperties());
}
// Add resolved plugin properties to workflow token as a JSON String
workflowContext.getToken().put(RESOLVED_PLUGIN_PROPERTIES_MAP, GSON.toJson(resolvedProperties));
}
use of co.cask.cdap.api.ProgramStatus in project cdap by caskdata.
the class DataStreamsSparkLauncher method destroy.
@TransactionPolicy(TransactionControl.EXPLICIT)
@Override
public void destroy() {
super.destroy();
ProgramStatus status = getContext().getState().getStatus();
WRAPPERLOGGER.info("Pipeline '{}' {}", getContext().getApplicationSpecification().getName(), status == ProgramStatus.COMPLETED ? "succeeded" : status.name().toLowerCase());
}
Aggregations