use of gov.cms.bfd.pipeline.sharedutils.PipelineJobSchedule in project beneficiary-fhir-data by CMSgov.
the class PipelineManagerIT method runUninterruptibleJobsThenStop.
/**
* Verifies that {@link PipelineManager#stop()} works, as expected.
*
* @throws Exception Any unhandled {@link Exception}s will cause this test case to fail.
*/
@Test
public void runUninterruptibleJobsThenStop() throws Exception {
// Create the pipeline and have it run a mock job.
PipelineJobRecordStore jobRecordStore = new PipelineJobRecordStore(PipelineTestUtils.get().getPipelineApplicationState().getMetrics());
try (PipelineManager pipelineManager = new PipelineManager(PipelineTestUtils.get().getPipelineApplicationState().getMetrics(), jobRecordStore)) {
MockJob mockJob = new MockJob(Optional.of(new PipelineJobSchedule(1, ChronoUnit.MILLIS)), false, () -> {
return PipelineJobOutcome.WORK_DONE;
});
pipelineManager.registerJob(mockJob);
jobRecordStore.submitPendingJob(MockJob.JOB_TYPE, null);
// Wait until the mock job has started.
Awaitility.await().atMost(1, TimeUnit.SECONDS).until(() -> jobRecordStore.getJobRecords().stream().filter(j -> MockJob.JOB_TYPE.equals(j.getJobType()) && j.isStarted()).findAny().isPresent());
// Stop the pipeline. If this doesn't hang, we're good.
pipelineManager.stop();
}
}
use of gov.cms.bfd.pipeline.sharedutils.PipelineJobSchedule in project beneficiary-fhir-data by CMSgov.
the class PipelineManagerIT method runInterruptibleJobsThenStop.
/**
* Verifies that {@link PipelineManager#stop()} works, as expected.
*
* @throws Exception Any unhandled {@link Exception}s will cause this test case to fail.
*/
@Test
public void runInterruptibleJobsThenStop() throws Exception {
// Create the pipeline and have it run a mock job.
PipelineJobRecordStore jobRecordStore = new PipelineJobRecordStore(PipelineTestUtils.get().getPipelineApplicationState().getMetrics());
try (PipelineManager pipelineManager = new PipelineManager(PipelineTestUtils.get().getPipelineApplicationState().getMetrics(), jobRecordStore)) {
MockJob mockJob = new MockJob(Optional.of(new PipelineJobSchedule(1, ChronoUnit.MILLIS)), () -> {
// Add an artificial delay that we'll be able to measure.
Thread.sleep(500);
return PipelineJobOutcome.WORK_DONE;
});
pipelineManager.registerJob(mockJob);
jobRecordStore.submitPendingJob(MockJob.JOB_TYPE, null);
// Wait until the mock job has started.
Awaitility.await().atMost(1, TimeUnit.SECONDS).until(() -> jobRecordStore.getJobRecords().stream().filter(j -> MockJob.JOB_TYPE.equals(j.getJobType()) && j.isStarted()).findAny().isPresent());
// Stop the pipeline and then make sure that the job was actually interrupted.
pipelineManager.stop();
PipelineJobRecord<NullPipelineJobArguments> mockJobRecord = jobRecordStore.findMostRecent(MockJob.JOB_TYPE).get();
assertTrue(mockJobRecord.getCanceledTime().isPresent());
assertTrue(mockJobRecord.getDuration().get().toMillis() < 500);
}
}
use of gov.cms.bfd.pipeline.sharedutils.PipelineJobSchedule in project beneficiary-fhir-data by CMSgov.
the class PipelineManagerIT method runSuccessfulScheduledJob.
/**
* Verifies that {@link PipelineManager} runs a successful mock scheduled job, as expected.
*
* @throws Exception Any unhandled {@link Exception}s will cause this test case to fail.
*/
@Test
public void runSuccessfulScheduledJob() throws Exception {
// Create the pipeline and have it run a mock job.
PipelineJobRecordStore jobRecordStore = new PipelineJobRecordStore(PipelineTestUtils.get().getPipelineApplicationState().getMetrics());
try (PipelineManager pipelineManager = new PipelineManager(PipelineTestUtils.get().getPipelineApplicationState().getMetrics(), jobRecordStore)) {
MockJob mockJob = new MockJob(Optional.of(new PipelineJobSchedule(1, ChronoUnit.MILLIS)), () -> PipelineJobOutcome.WORK_DONE);
pipelineManager.registerJob(mockJob);
jobRecordStore.submitPendingJob(MockJob.JOB_TYPE, null);
// Wait until a completed iteration of the mock job can be found.
Awaitility.await().atMost(1, TimeUnit.SECONDS).until(() -> jobRecordStore.getJobRecords().stream().filter(j -> MockJob.JOB_TYPE.equals(j.getJobType()) && j.isCompleted()).findAny().isPresent());
// Verify that one of the completed mock job iterations looks correct.
Optional<PipelineJobRecord<?>> mockJobRecord = jobRecordStore.getJobRecords().stream().filter(j -> MockJob.JOB_TYPE.equals(j.getJobType()) && j.isCompleted()).findAny();
assertEquals(Optional.of(PipelineJobOutcome.WORK_DONE), mockJobRecord.get().getOutcome());
}
}
use of gov.cms.bfd.pipeline.sharedutils.PipelineJobSchedule in project beneficiary-fhir-data by CMSgov.
the class SchedulerJob method call.
/**
* @see gov.cms.bfd.pipeline.sharedutils.PipelineJob#call()
*/
@Override
public PipelineJobOutcome call() throws Exception {
boolean scheduledAJob = false;
while (true) {
try (Timer.Context timer = appMetrics.timer(MetricRegistry.name(getClass().getSimpleName(), "call", "iteration")).time()) {
Instant now = Instant.now();
Set<PipelineJob<NullPipelineJobArguments>> scheduledJobs = pipelineManager.getScheduledJobs();
for (PipelineJob<NullPipelineJobArguments> scheduledJob : scheduledJobs) {
PipelineJobSchedule jobSchedule = scheduledJob.getSchedule().get();
Optional<PipelineJobRecord<NullPipelineJobArguments>> mostRecentExecution = jobRecordsStore.findMostRecent(scheduledJob.getType());
/* Calculate whether or not we should trigger an execution of the next job. */
boolean shouldTriggerJob;
if (!mostRecentExecution.isPresent()) {
// If the job has never run, we'll always trigger it now, regardless of schedule.
shouldTriggerJob = true;
} else {
if (!mostRecentExecution.get().isCompleted()) {
// If the job's still pending or running, don't double-trigger it.
shouldTriggerJob = false;
} else {
if (mostRecentExecution.get().isCompletedSuccessfully()) {
// If the job's not running, check to see if it's time to trigger it again.
// Note: This calculation is based on completion time, not submission or start time.
Instant nextExecution = mostRecentExecution.get().getStartedTime().get().plus(jobSchedule.getRepeatDelay(), jobSchedule.getRepeatDelayUnit());
shouldTriggerJob = now.equals(nextExecution) || now.isAfter(nextExecution);
} else {
// We don't re-run failed jobs.
shouldTriggerJob = false;
}
}
}
// If we shouldn't trigger this job, move on to the next.
if (!shouldTriggerJob) {
continue;
}
// Trigger the job (for future execution, when VolunteerJob picks it up)!
jobRecordsStore.submitPendingJob(scheduledJob.getType(), null);
}
}
try {
Thread.sleep(SCHEDULER_TICK_MILLIS);
} catch (InterruptedException e) {
/*
* Jobs are only interrupted/cancelled as part of application shutdown, so when encountered,
* we'll break out of our scheduling loop and close up shop here.
*/
break;
}
}
/*
* Did we schedule at least one job? If we ever move to an autoscaled version of this
* application, it will be important to ensure that we "collude" with the PipelineJobRecordStore
* to ignore this PipelineJobOutcome and ensure that the record doesn't get marked as completed,
* even when the application shuts down. (If that happened, then scheduled triggers would stop
* firing.)
*/
return scheduledAJob ? PipelineJobOutcome.WORK_DONE : PipelineJobOutcome.NOTHING_TO_DO;
}
use of gov.cms.bfd.pipeline.sharedutils.PipelineJobSchedule in project beneficiary-fhir-data by CMSgov.
the class PipelineManagerIT method runFailingScheduledJob.
/**
* Verifies that {@link PipelineManager} runs a failing mock scheduled job, as expected.
*
* @throws Exception Any unhandled {@link Exception}s will cause this test case to fail.
*/
@Test
public void runFailingScheduledJob() throws Exception {
// Create the pipeline and have it run a mock job.
PipelineJobRecordStore jobRecordStore = new PipelineJobRecordStore(PipelineTestUtils.get().getPipelineApplicationState().getMetrics());
try (PipelineManager pipelineManager = new PipelineManager(PipelineTestUtils.get().getPipelineApplicationState().getMetrics(), jobRecordStore)) {
MockJob mockJob = new MockJob(Optional.of(new PipelineJobSchedule(1, ChronoUnit.MILLIS)), () -> {
throw new RuntimeException("boom");
});
pipelineManager.registerJob(mockJob);
jobRecordStore.submitPendingJob(MockJob.JOB_TYPE, null);
// Wait until a completed job can be found.
Awaitility.await().atMost(1, TimeUnit.SECONDS).until(() -> jobRecordStore.getJobRecords().stream().filter(j -> MockJob.JOB_TYPE.equals(j.getJobType()) && j.isCompleted()).findAny().isPresent());
// Verify that one of the completed mock job iterations looks correct.
Optional<PipelineJobRecord<?>> mockJobRecord = jobRecordStore.getJobRecords().stream().filter(j -> MockJob.JOB_TYPE.equals(j.getJobType()) && j.isCompleted()).findAny();
assertEquals(RuntimeException.class, mockJobRecord.get().getFailure().get().getType());
assertEquals("boom", mockJobRecord.get().getFailure().get().getMessage());
// Make sure that the job stopped trying to execute after it failed.
assertEquals(1, jobRecordStore.getJobRecords().stream().filter(j -> MockJob.JOB_TYPE.equals(j.getJobType())).count());
}
}
Aggregations