use of co.cask.cdap.internal.app.runtime.schedule.ProgramScheduleRecord in project cdap by caskdata.
the class ProgramScheduleStoreDataset method getScheduleRecord.
/**
* Read all information about a schedule from the store.
*
* @param scheduleId the id of the schedule to read
* @return the schedule record from the store
* @throws NotFoundException if the schedule does not exist in the store
*/
public ProgramScheduleRecord getScheduleRecord(ScheduleId scheduleId) throws NotFoundException {
Row row = store.get(new Get(rowKeyForSchedule(scheduleId)));
byte[] serialized = row.get(SCHEDULE_COLUMN_BYTES);
if (serialized == null) {
throw new NotFoundException(scheduleId);
}
ProgramSchedule schedule = GSON.fromJson(Bytes.toString(serialized), ProgramSchedule.class);
ProgramScheduleMeta meta = extractMetaFromRow(scheduleId, row);
return new ProgramScheduleRecord(schedule, meta);
}
use of co.cask.cdap.internal.app.runtime.schedule.ProgramScheduleRecord 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.internal.app.runtime.schedule.ProgramScheduleRecord in project cdap by caskdata.
the class ProgramLifecycleHttpHandler method doGetSchedules.
protected void doGetSchedules(HttpResponder responder, ApplicationId applicationId, @Nullable String workflow, @Nullable String triggerTypeStr, @Nullable String statusStr) throws Exception {
ApplicationSpecification appSpec = store.getApplication(applicationId);
if (appSpec == null) {
throw new NotFoundException(applicationId);
}
ProgramScheduleStatus status;
try {
status = statusStr == null ? null : ProgramScheduleStatus.valueOf(statusStr);
} catch (IllegalArgumentException e) {
throw new BadRequestException(String.format("Invalid schedule status '%s'. Must be one of %s.", statusStr, Joiner.on(',').join(ProgramScheduleStatus.values())), e);
}
ProtoTrigger.Type triggerType;
try {
triggerType = triggerTypeStr == null ? null : ProtoTrigger.Type.valueOfCategoryName(triggerTypeStr);
} catch (IllegalArgumentException e) {
throw new BadRequestException(e.getMessage(), e);
}
Predicate<ProgramScheduleRecord> predicate = record -> true;
if (status != null) {
predicate = predicate.and(record -> record.getMeta().getStatus().equals(status));
}
if (triggerType != null) {
predicate = predicate.and(record -> record.getSchedule().getTrigger().getType().equals(triggerType));
}
Collection<ProgramScheduleRecord> schedules;
if (workflow != null) {
WorkflowId workflowId = applicationId.workflow(workflow);
if (appSpec.getWorkflows().get(workflow) == null) {
throw new NotFoundException(workflowId);
}
schedules = programScheduleService.list(workflowId, predicate);
} else {
schedules = programScheduleService.list(applicationId, predicate);
}
List<ScheduleDetail> details = schedules.stream().map(ProgramScheduleRecord::toScheduleDetail).collect(Collectors.toList());
responder.sendJson(HttpResponseStatus.OK, GSON.toJson(details, Schedulers.SCHEDULE_DETAILS_TYPE));
}
use of co.cask.cdap.internal.app.runtime.schedule.ProgramScheduleRecord in project cdap by caskdata.
the class ProgramScheduleStoreDataset method findSchedules.
/**
* Find all schedules that have a trigger with a given trigger key.
*
* @param triggerKey the trigger key to look up
* @return a list of all schedules that are triggered by this key; never null
*/
public Collection<ProgramScheduleRecord> findSchedules(String triggerKey) {
Map<ScheduleId, ProgramScheduleRecord> schedulesFound = new HashMap<>();
try (Scanner scanner = store.readByIndex(TRIGGER_KEY_COLUMN_BYTES, Bytes.toBytes(triggerKey))) {
Row triggerRow;
while ((triggerRow = scanner.next()) != null) {
String triggerRowKey = Bytes.toString(triggerRow.getRow());
try {
ScheduleId scheduleId = extractScheduleIdFromTriggerKey(triggerRowKey);
if (schedulesFound.containsKey(scheduleId)) {
continue;
}
Row row = store.get(new Get(rowKeyForSchedule(scheduleId)));
byte[] serialized = row.get(SCHEDULE_COLUMN_BYTES);
if (serialized == null) {
throw new NotFoundException(scheduleId);
}
ProgramSchedule schedule = GSON.fromJson(Bytes.toString(serialized), ProgramSchedule.class);
ProgramScheduleMeta meta = extractMetaFromRow(scheduleId, row);
ProgramScheduleRecord record = new ProgramScheduleRecord(schedule, meta);
schedulesFound.put(scheduleId, record);
} catch (IllegalArgumentException | NotFoundException e) {
// the only exceptions we know to be thrown here are IllegalArgumentException (ill-formed key) or
// NotFoundException (if the schedule does not exist). Both should never happen, so we warn and ignore.
// we will let any other exception propagate up, because it would be a DataSetException or similarly serious.
LOG.warn("Problem with trigger id '{}' found for trigger key '{}': {}. Skipping entry.", triggerRowKey, triggerKey, e.getMessage());
}
}
}
return schedulesFound.values();
}
use of co.cask.cdap.internal.app.runtime.schedule.ProgramScheduleRecord in project cdap by caskdata.
the class ProgramScheduleStoreDataset method listScheduleRecords.
/**
* List schedule records in a given application and if the programId is not null, only return the schedules
* which can launch the given program
*/
private List<ProgramScheduleRecord> listScheduleRecords(ApplicationId appId, @Nullable ProgramId programId) {
List<ProgramScheduleRecord> result = new ArrayList<>();
byte[] prefix = keyPrefixForApplicationScan(appId);
try (Scanner scanner = store.scan(new Scan(prefix, Bytes.stopKeyForPrefix(prefix)))) {
Row row;
while ((row = scanner.next()) != null) {
byte[] serialized = row.get(SCHEDULE_COLUMN_BYTES);
if (serialized != null) {
ProgramSchedule schedule = GSON.fromJson(Bytes.toString(serialized), ProgramSchedule.class);
if (programId == null || programId.equals(schedule.getProgramId())) {
result.add(new ProgramScheduleRecord(schedule, extractMetaFromRow(schedule.getScheduleId(), row)));
}
}
}
}
return result;
}
Aggregations