use of io.cdap.cdap.internal.app.runtime.schedule.ProgramScheduleRecord in project cdap by caskdata.
the class CoreSchedulerService method enableScheduleInternal.
private void enableScheduleInternal(ProgramScheduleStoreDataset store, ScheduleId scheduleId) throws IOException, NotFoundException, ConflictException, SchedulerException {
ProgramScheduleRecord record = store.getScheduleRecord(scheduleId);
if (ProgramScheduleStatus.SUSPENDED != record.getMeta().getStatus()) {
throw new ConflictException("Schedule '" + scheduleId + "' is already enabled");
}
timeSchedulerService.resumeProgramSchedule(record.getSchedule());
store.updateScheduleStatus(scheduleId, ProgramScheduleStatus.SCHEDULED);
}
use of io.cdap.cdap.internal.app.runtime.schedule.ProgramScheduleRecord in project cdap by caskdata.
the class ProgramScheduleService method getRecord.
/**
* Get the schedule record for the given schedule ID
*
* @return the schedule
* @throws NotFoundException if the schedule could not be found
* @throws UnauthorizedException if the principal is not authorized to access the schedule program
* @throws Exception if any other errors occurred while performing the authorization enforcement check
*/
public ProgramScheduleRecord getRecord(ScheduleId scheduleId) throws Exception {
ProgramScheduleRecord record = scheduler.getScheduleRecord(scheduleId);
accessEnforcer.enforce(record.getSchedule().getProgramId(), authenticationContext.getPrincipal(), StandardPermission.GET);
return record;
}
use of io.cdap.cdap.internal.app.runtime.schedule.ProgramScheduleRecord in project cdap by caskdata.
the class ProgramScheduleStoreDataset method listSchedulesRecordsWithPrefix.
/**
* List schedule records with the given key prefix and only returns the schedules that can pass the filter.
*
* @param prefixKeys the prefix of the schedule records to be listed
* @param filter a filter that only returns true if the schedule record will be returned in the result
* @return the schedule records with the given key prefix that can pass the filter
*/
private List<ProgramScheduleRecord> listSchedulesRecordsWithPrefix(Collection<Field<?>> prefixKeys, Predicate<ProgramSchedule> filter) throws IOException {
List<ProgramScheduleRecord> result = new ArrayList<>();
try (CloseableIterator<StructuredRow> iterator = scheduleStore.scan(Range.singleton(prefixKeys), Integer.MAX_VALUE)) {
while (iterator.hasNext()) {
StructuredRow row = iterator.next();
String serializedSchedule = row.getString(StoreDefinition.ProgramScheduleStore.SCHEDULE);
if (serializedSchedule != null) {
ProgramSchedule schedule = GSON.fromJson(serializedSchedule, ProgramSchedule.class);
if (schedule != null && filter.test(schedule)) {
result.add(new ProgramScheduleRecord(schedule, extractMetaFromRow(schedule.getScheduleId(), row)));
}
}
}
}
return result;
}
use of io.cdap.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<ProgramSchedule> modifySchedulesTriggeredByDeletedProgram(ProgramId programId) throws IOException {
long deleteTime = System.currentTimeMillis();
List<ProgramSchedule> 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();
markScheduleAsDeleted(schedule.getScheduleId(), deleteTime);
triggerStore.deleteAll(Range.singleton(getScheduleKeys(schedule.getScheduleId())));
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);
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);
}
}
return deleted;
}
use of io.cdap.cdap.internal.app.runtime.schedule.ProgramScheduleRecord in project cdap by caskdata.
the class ProgramLifecycleHttpHandler method doGetSchedules.
private void doGetSchedules(HttpResponder responder, ApplicationId applicationId, @Nullable ProgramId programId, @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 (programId != null) {
if (!appSpec.getProgramsByType(programId.getType().getApiProgramType()).contains(programId.getProgram())) {
throw new NotFoundException(programId);
}
schedules = programScheduleService.list(programId, 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));
}
Aggregations