Search in sources :

Example 1 with AbstractSatisfiableCompositeTrigger

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;
}
Also used : SatisfiableTrigger(co.cask.cdap.internal.app.runtime.schedule.trigger.SatisfiableTrigger) Trigger(co.cask.cdap.api.schedule.Trigger) AbstractSatisfiableCompositeTrigger(co.cask.cdap.internal.app.runtime.schedule.trigger.AbstractSatisfiableCompositeTrigger) ProgramStatusTrigger(co.cask.cdap.internal.app.runtime.schedule.trigger.ProgramStatusTrigger) AlreadyExistsException(co.cask.cdap.common.AlreadyExistsException) ProgramSchedule(co.cask.cdap.internal.app.runtime.schedule.ProgramSchedule) ArrayList(java.util.ArrayList) AbstractSatisfiableCompositeTrigger(co.cask.cdap.internal.app.runtime.schedule.trigger.AbstractSatisfiableCompositeTrigger) NotFoundException(co.cask.cdap.common.NotFoundException) ProgramScheduleRecord(co.cask.cdap.internal.app.runtime.schedule.ProgramScheduleRecord) ScheduleId(co.cask.cdap.proto.id.ScheduleId) HashSet(java.util.HashSet) ProgramStatus(co.cask.cdap.api.ProgramStatus)

Example 2 with AbstractSatisfiableCompositeTrigger

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;
}
Also used : TimeTrigger(co.cask.cdap.internal.app.runtime.schedule.trigger.TimeTrigger) HashMap(java.util.HashMap) AbstractSatisfiableCompositeTrigger(co.cask.cdap.internal.app.runtime.schedule.trigger.AbstractSatisfiableCompositeTrigger) ProgramId(co.cask.cdap.proto.id.ProgramId) TriggerKey(org.quartz.TriggerKey) SatisfiableTrigger(co.cask.cdap.internal.app.runtime.schedule.trigger.SatisfiableTrigger) SchedulableProgramType(co.cask.cdap.api.schedule.SchedulableProgramType)

Example 3 with AbstractSatisfiableCompositeTrigger

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()));
    }
}
Also used : ProgramSchedule(co.cask.cdap.internal.app.runtime.schedule.ProgramSchedule) AbstractSatisfiableCompositeTrigger(co.cask.cdap.internal.app.runtime.schedule.trigger.AbstractSatisfiableCompositeTrigger) Notification(co.cask.cdap.proto.Notification)

Aggregations

AbstractSatisfiableCompositeTrigger (co.cask.cdap.internal.app.runtime.schedule.trigger.AbstractSatisfiableCompositeTrigger)3 ProgramSchedule (co.cask.cdap.internal.app.runtime.schedule.ProgramSchedule)2 SatisfiableTrigger (co.cask.cdap.internal.app.runtime.schedule.trigger.SatisfiableTrigger)2 ProgramStatus (co.cask.cdap.api.ProgramStatus)1 SchedulableProgramType (co.cask.cdap.api.schedule.SchedulableProgramType)1 Trigger (co.cask.cdap.api.schedule.Trigger)1 AlreadyExistsException (co.cask.cdap.common.AlreadyExistsException)1 NotFoundException (co.cask.cdap.common.NotFoundException)1 ProgramScheduleRecord (co.cask.cdap.internal.app.runtime.schedule.ProgramScheduleRecord)1 ProgramStatusTrigger (co.cask.cdap.internal.app.runtime.schedule.trigger.ProgramStatusTrigger)1 TimeTrigger (co.cask.cdap.internal.app.runtime.schedule.trigger.TimeTrigger)1 Notification (co.cask.cdap.proto.Notification)1 ProgramId (co.cask.cdap.proto.id.ProgramId)1 ScheduleId (co.cask.cdap.proto.id.ScheduleId)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 TriggerKey (org.quartz.TriggerKey)1