/** * @param scheduleLastUpdatedTime the last modification time of the schedule, at the time this job is created. * This serves as a way to detect whether the schedule was changed later-on, and * hence, the job would be obsolete in that case. */ public SimpleJob(ProgramSchedule schedule, long creationTime, List<Notification> notifications, State state, long scheduleLastUpdatedTime) { this.schedule = schedule; this.jobKey = new JobKey(schedule.getScheduleId(), creationTime); this.notifications = ImmutableList.copyOf(notifications); this.state = state; this.scheduleLastUpdatedTime = scheduleLastUpdatedTime; }
/** * @param scheduleLastUpdatedTime the last modification time of the schedule, at the time this job is created. * This serves as a way to detect whether the schedule was changed later-on, and * hence, the job would be obsolete in that case. */ public SimpleJob(ProgramSchedule schedule, long creationTime, List<Notification> notifications, State state, long scheduleLastUpdatedTime) { this.schedule = schedule; this.jobKey = new JobKey(schedule.getScheduleId(), creationTime); this.notifications = ImmutableList.copyOf(notifications); this.state = state; this.scheduleLastUpdatedTime = scheduleLastUpdatedTime; }
/** * Update an existing schedule in the store. * * @param schedule the schedule to update * @return the updated schedule's last modified timestamp * @throws NotFoundException if one of the schedules already exists */ public long updateSchedule(ProgramSchedule schedule) throws NotFoundException { deleteSchedule(schedule.getScheduleId()); try { return addSchedule(schedule); } catch (AlreadyExistsException e) { // Should never reach here because we just deleted it throw new IllegalStateException( "Schedule '" + schedule.getScheduleId() + "' already exists despite just being deleted."); } }
/** * Update an existing schedule in the store. * * @param schedule the schedule to update * @return the updated schedule's last modified timestamp * @throws NotFoundException if one of the schedules already exists */ public long updateSchedule(ProgramSchedule schedule) throws NotFoundException { deleteSchedule(schedule.getScheduleId()); try { return addSchedule(schedule); } catch (AlreadyExistsException e) { // Should never reach here because we just deleted it throw new IllegalStateException( "Schedule '" + schedule.getScheduleId() + "' already exists despite just being deleted."); } }
private void collectScheduleProfileMetadata(ProgramSchedule schedule, ProfileId programProfile, Map<MetadataEntity, Map<String, String>> updates) { ScheduleId scheduleId = schedule.getScheduleId(); LOG.trace("Updating profile metadata for {}", scheduleId); // if we are able to get profile from preferences or schedule properties, use it // otherwise default profile will be used Optional<ProfileId> scheduleProfileId = SystemArguments.getProfileIdFromArgs(scheduleId.getNamespaceId(), schedule.getProperties()); programProfile = scheduleProfileId.orElse(programProfile); addProfileMetadataUpdate(scheduleId, programProfile, updates); }
private void updateScheduleProfileMetadata(ProgramSchedule schedule, ProfileId profileId) { ScheduleId scheduleId = schedule.getScheduleId(); Optional<ProfileId> scheduleProfileId = SystemArguments.getProfileIdFromArgs(scheduleId.getNamespaceId(), schedule.getProperties()); profileId = scheduleProfileId.orElse(profileId); setProfileMetadata(scheduleId, profileId); }
private Put toPut(Job job) { ScheduleId scheduleId = job.getSchedule().getScheduleId(); return new Put(getRowKey(scheduleId, job.getCreationTime()), COL, GSON.toJson(job)); }
private Put toPut(Job job) { ScheduleId scheduleId = job.getSchedule().getScheduleId(); return new Put(getRowKey(scheduleId, job.getCreationTime()), COL, GSON.toJson(job)); }
@Override public void deleteJob(Job job) { table.delete(getRowKey(job.getSchedule().getScheduleId(), job.getCreationTime())); }
@Override public void deleteJob(Job job) { table.delete(getRowKey(job.getSchedule().getScheduleId(), job.getCreationTime())); }
@Override public CloseableIterator<Job> getJobs(int partition, @Nullable Job lastJobProcessed) { byte[] jobRowPrefix = getJobRowPrefix(partition); byte[] startKey; if (lastJobProcessed == null) { startKey = jobRowPrefix; } else { // sanity check that the specified job is from the same partition Preconditions.checkArgument(partition == getPartition(lastJobProcessed.getSchedule().getScheduleId()), "Job is not from partition '%s': %s", partition, lastJobProcessed); byte[] jobRowKey = getRowKey(lastJobProcessed.getSchedule().getScheduleId(), lastJobProcessed.getCreationTime()); // we want to exclude the given Job from the scan startKey = Bytes.stopKeyForPrefix(jobRowKey); } byte[] stopKey = Bytes.stopKeyForPrefix(jobRowPrefix); return createCloseableIterator(table.scan(startKey, stopKey)); }
@Override public CloseableIterator<Job> getJobs(int partition, @Nullable Job lastJobProcessed) { byte[] jobRowPrefix = getJobRowPrefix(partition); byte[] startKey; if (lastJobProcessed == null) { startKey = jobRowPrefix; } else { // sanity check that the specified job is from the same partition Preconditions.checkArgument(partition == getPartition(lastJobProcessed.getSchedule().getScheduleId()), "Job is not from partition '%s': %s", partition, lastJobProcessed); byte[] jobRowKey = getRowKey(lastJobProcessed.getSchedule().getScheduleId(), lastJobProcessed.getCreationTime()); // we want to exclude the given Job from the scan startKey = Bytes.stopKeyForPrefix(jobRowKey); } byte[] stopKey = Bytes.stopKeyForPrefix(jobRowPrefix); return createCloseableIterator(table.scan(startKey, stopKey)); }
@Override public void apply() throws Exception { Assert.assertEquals(ImmutableSet.of(SCHED2_JOB), getAllJobs(jobQueue)); Assert.assertEquals(0, toSet(jobQueue.getJobsForSchedule(SCHED1.getScheduleId())).size()); Assert.assertEquals(ImmutableSet.of(SCHED2_JOB), toSet(jobQueue.getJobsForSchedule(SCHED2.getScheduleId()))); } });
@Override public void apply() throws Exception { Assert.assertEquals(ImmutableSet.of(SCHED2_JOB), getAllJobs(jobQueue, true)); Assert.assertEquals(0, toSet(jobQueue.getJobsForSchedule(SCHED1.getScheduleId())).size()); Assert.assertEquals(ImmutableSet.of(SCHED2_JOB), toSet(jobQueue.getJobsForSchedule(SCHED2.getScheduleId()))); } });
/** * Adds and enables time based schedules for the given workflow at the given frequency. * * @param scheduleMins the number of minutes to wait before launching the given workflow each time * @param workflowId the ID of the scheduled workflow */ private ProgramSchedule initializeSchedules(int scheduleMins, WorkflowId workflowId) throws ConflictException, BadRequestException, NotFoundException { ProgramSchedule schedule = new ProgramSchedule(String.format("%dMinSchedule", scheduleMins), "time schedule", workflowId, Collections.emptyMap(), new TimeTrigger(String.format("*/%d * * * *", scheduleMins)), Collections.emptyList()); scheduler.addSchedule(schedule); scheduler.enableSchedule(schedule.getScheduleId()); return schedule; }
@Override public void process(final ApplicationWithPrograms input) throws Exception { if (!input.canUpdateSchedules()) { // if we cant update schedules, emit and return emit(input); return; } ApplicationId appId = input.getApplicationId(); // Get a set of new schedules from the app spec Set<ProgramSchedule> newSchedules = getProgramScheduleSet(appId, input.getSpecification()); for (ProgramSchedule schedule : programScheduler.listSchedules(appId)) { if (newSchedules.contains(schedule)) { newSchedules.remove(schedule); // Remove the existing schedule from the newSchedules continue; } // Delete the existing schedule if it is not present in newSchedules programScheduler.deleteSchedule(schedule.getScheduleId()); } // Add new schedules programScheduler.addSchedules(newSchedules); // Emit the input to next stage. emit(input); }
/** * Removes all schedules for a specific program from the store. * * @param programId the program id for which to delete the schedules * @return the IDs of the schedules that were deleted */ // TODO: fix the bug that this method will return fake schedule id https://issues.cask.co/browse/CDAP-13626 public List<ScheduleId> deleteSchedules(ProgramId programId) { List<ScheduleId> deleted = new ArrayList<>(); // since all trigger row keys are prefixed by <scheduleRowKey>@, // a scan for that prefix finds exactly the schedules and all of its triggers byte[] prefix = keyPrefixForApplicationScan(programId.getParent()); 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.equals(schedule.getProgramId())) { store.delete(row.getRow()); deleted.add(schedule.getScheduleId()); } } } } return deleted; }
@Override public void apply() throws Exception { // should be 0 jobs in the JobQueue to begin with Assert.assertEquals(0, getAllJobs(jobQueue).size()); Assert.assertEquals(0, toSet(jobQueue.getJobsForSchedule(SCHED1.getScheduleId())).size()); Assert.assertEquals(0, toSet(jobQueue.getJobsForSchedule(SCHED2.getScheduleId())).size()); // put a job for SCHED1, and check that it is in 'getJobs' and 'getJobsForSchedule' jobQueue.put(SCHED1_JOB); // test get Assert.assertEquals(SCHED1_JOB, jobQueue.getJob(SCHED1_JOB.getJobKey())); Assert.assertEquals(ImmutableSet.of(SCHED1_JOB), getAllJobs(jobQueue)); Assert.assertEquals(ImmutableSet.of(SCHED1_JOB), toSet(jobQueue.getJobsForSchedule(SCHED1.getScheduleId()))); // the job for SCHED1 should not be in 'getJobsForSchedule' for SCHED2 Assert.assertEquals(0, toSet(jobQueue.getJobsForSchedule(SCHED2.getScheduleId())).size()); // put a job for SCHED2 and verify that it is also in the returned list jobQueue.put(SCHED2_JOB); Assert.assertEquals(ImmutableSet.of(SCHED1_JOB, SCHED2_JOB), getAllJobs(jobQueue)); Assert.assertEquals(ImmutableSet.of(SCHED2_JOB), toSet(jobQueue.getJobsForSchedule(SCHED2.getScheduleId()))); // mark job for SCHED1 for deletion and assert that it is no longer in 'getJobs' jobQueue.markJobsForDeletion(SCHED1.getScheduleId(), System.currentTimeMillis()); } });
public ScheduleDetail toScheduleDetail() { ScheduleProgramInfo programInfo = new ScheduleProgramInfo(schedule.getProgramId().getType().getSchedulableType(), schedule.getProgramId().getProgram()); ScheduleId scheduleId = schedule.getScheduleId(); return new ScheduleDetail(scheduleId.getNamespace(), scheduleId.getApplication(), scheduleId.getVersion(), scheduleId.getSchedule(), schedule.getDescription(), programInfo, schedule.getProperties(), schedule.getTrigger(), schedule.getConstraints(), schedule.getTimeoutMillis(), meta.getStatus().name()); } }
public ScheduleDetail toScheduleDetail() { ScheduleProgramInfo programInfo = new ScheduleProgramInfo(schedule.getProgramId().getType().getSchedulableType(), schedule.getProgramId().getProgram()); ScheduleId scheduleId = schedule.getScheduleId(); return new ScheduleDetail(scheduleId.getNamespace(), scheduleId.getApplication(), scheduleId.getVersion(), scheduleId.getSchedule(), schedule.getDescription(), programInfo, schedule.getProperties(), schedule.getTrigger(), schedule.getConstraints(), schedule.getTimeoutMillis(), meta.getStatus().name()); } }