use of co.cask.cdap.internal.app.runtime.schedule.trigger.AbstractSatisfiableCompositeTrigger 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.trigger.AbstractSatisfiableCompositeTrigger in project cdap by caskdata.
the class TimeScheduler method getCronTriggerKeyMap.
/**
* @return A Map with cron expression as keys and corresponding trigger key as values.
* Trigger keys are created from program name, programType and scheduleName (and cron expression if the trigger
* in the schedule is a composite trigger) and TimeScheuler#PAUSED_NEW_TRIGGERS_GROUP
* if it exists in this group else returns the {@link TriggerKey} prepared with null which gets it with
* {@link Key#DEFAULT_GROUP}
* @throws org.quartz.SchedulerException
*/
private Map<String, TriggerKey> getCronTriggerKeyMap(ProgramSchedule schedule) throws org.quartz.SchedulerException {
ProgramId program = schedule.getProgramId();
SchedulableProgramType programType = program.getType().getSchedulableType();
co.cask.cdap.api.schedule.Trigger trigger = schedule.getTrigger();
Map<String, TriggerKey> cronTriggerKeyMap = new HashMap<>();
// Get a set of TimeTrigger if the schedule's trigger is a composite trigger
if (trigger instanceof AbstractSatisfiableCompositeTrigger) {
Set<SatisfiableTrigger> triggerSet = ((AbstractSatisfiableCompositeTrigger) trigger).getUnitTriggers().get(ProtoTrigger.Type.TIME);
if (triggerSet == null) {
return ImmutableMap.of();
}
for (SatisfiableTrigger timeTrigger : triggerSet) {
String cron = ((TimeTrigger) timeTrigger).getCronExpression();
String triggerName = AbstractTimeSchedulerService.getTriggerName(program, programType, schedule.getName(), cron);
cronTriggerKeyMap.put(cron, triggerKeyForName(triggerName));
}
return cronTriggerKeyMap;
}
// No need to include cron expression in trigger key if the trigger is not composite trigger
String triggerName = AbstractTimeSchedulerService.scheduleIdFor(program, programType, schedule.getName());
cronTriggerKeyMap.put(((TimeTrigger) schedule.getTrigger()).getCronExpression(), triggerKeyForName(triggerName));
return cronTriggerKeyMap;
}
use of co.cask.cdap.internal.app.runtime.schedule.trigger.AbstractSatisfiableCompositeTrigger in project cdap by caskdata.
the class JobQueueDataset method addNotification.
@Override
public void addNotification(ProgramScheduleRecord record, Notification notification) {
boolean jobExists = false;
ProgramSchedule schedule = record.getSchedule();
// Only add notifications for enabled schedules
if (record.getMeta().getStatus() != ProgramScheduleStatus.SCHEDULED) {
return;
}
// for the same schedule.
if (schedule.getTrigger() instanceof AbstractSatisfiableCompositeTrigger) {
scheduleIds.add(getRowKeyPrefix(schedule.getScheduleId()));
}
try (CloseableIterator<Job> jobs = getJobsForSchedule(schedule.getScheduleId())) {
while (jobs.hasNext()) {
Job job = jobs.next();
if (job.getState() == Job.State.PENDING_TRIGGER) {
// ConstraintCheckerService
if (job.isToBeDeleted()) {
// ignore, it will be deleted by ConstraintCheckerService
continue;
}
long scheduleLastUpdated = record.getMeta().getLastUpdated();
if (job.getScheduleLastUpdatedTime() != scheduleLastUpdated) {
// schedule has changed: this job is obsolete
table.put(getRowKey(job.getJobKey().getScheduleId(), job.getJobKey().getCreationTime()), IS_OBSOLETE_COL, Bytes.toBytes(System.currentTimeMillis()));
} else if (System.currentTimeMillis() - job.getCreationTime() > job.getSchedule().getTimeoutMillis()) {
// job has timed out; mark it obsolete
table.put(getRowKey(job.getJobKey().getScheduleId(), job.getJobKey().getCreationTime()), IS_OBSOLETE_COL, Bytes.toBytes(System.currentTimeMillis()));
} else {
jobExists = true;
addNotification(job, notification);
break;
}
}
}
}
// if no job exists for the scheduleId, add a new job with the first notification
if (!jobExists) {
List<Notification> notifications = Collections.singletonList(notification);
Job.State jobState = isTriggerSatisfied(schedule, notifications) ? Job.State.PENDING_CONSTRAINT : Job.State.PENDING_TRIGGER;
put(new SimpleJob(schedule, System.currentTimeMillis(), notifications, jobState, record.getMeta().getLastUpdated()));
}
}
Aggregations