@Override public JobData createJob( String jobName, long fireTime, JobData jobData ) { Assert.notNull( jobName, "jobName is required" ); Assert.notNull( jobData, "jobData is required" ); try { jobData.setJobName( jobName ); JobData job = getEm().create( jobData ); JobStat stat = getEm().create( new JobStat( jobName, job.getUuid() ) ); scheduleJob( jobName, fireTime, job.getUuid(), stat.getUuid() ); return job; } catch ( Exception e ) { throw new JobRuntimeException( e ); } }
public void start( int maxFailures ) { Preconditions.checkState( this.status.equals( Status.NOT_STARTED ) || this.status.equals( Status.FAILED ), "Attempted to start job in progress" ); this.status = Status.IN_PROGRESS; stats.incrementRuns(); // use >= in case the threshold lowers after the job has passed the failure // mark if ( maxFailures != FOREVER && stats.getTotalAttempts() > maxFailures ) { status = Status.DEAD; } startTime = System.currentTimeMillis(); stats.setStartTime( startTime ); }
@Override public void delay( long delay ) { updateState( Status.IN_PROGRESS, "Attempted to delay a job not in progress", Status.DELAYED ); stats.incrementDelays(); this.delay = delay; runtime.delay( this ); }
assertEquals( 1, stat.getTotalAttempts() ); assertEquals( 1, stat.getRunCount() ); assertEquals( 0, stat.getDelayCount() );
@Test public void transitionsRetry() { JobData data = new JobData(); JobStat stat = new JobStat(); JobDescriptor jobDescriptor = new JobDescriptor( "", UUID.randomUUID(), UUID.randomUUID(), data, stat, null ); JobExecution bje = new JobExecutionImpl( jobDescriptor ); assertEquals( JobExecution.Status.NOT_STARTED, bje.getStatus() ); bje.start( JobExecution.FOREVER ); assertEquals( JobExecution.Status.IN_PROGRESS, bje.getStatus() ); bje.failed(); assertEquals( JobExecution.Status.FAILED, bje.getStatus() ); }
@Test public void failureTriggerCount() { JobData data = new JobData(); JobStat stat = new JobStat(); JobDescriptor jobDescriptor = new JobDescriptor( "", UUID.randomUUID(), UUID.randomUUID(), data, stat, null ); JobExecution bje = new JobExecutionImpl( jobDescriptor ); bje.start( 1 ); assertEquals( Status.IN_PROGRESS, bje.getStatus() ); assertEquals( 1, stat.getRunCount() ); bje.failed(); assertEquals( Status.FAILED, bje.getStatus() ); assertEquals( 1, stat.getRunCount() ); // now fail again, we should trigger a state change bje = new JobExecutionImpl( jobDescriptor ); bje.start( 1 ); assertEquals( Status.DEAD, bje.getStatus() ); assertEquals( 2, stat.getRunCount() ); }
public void completed() { updateState( Status.IN_PROGRESS, "Attempted to complete job not in progress", Status.COMPLETED ); stats.setDuration( duration ); }
@Override public void delayRetry( JobExecution execution, long delay ) { JobData data = execution.getJobData(); JobStat stat = execution.getJobStats(); try { // if it's a dead status, it's failed too many times, just kill the job if ( execution.getStatus() == Status.DEAD ) { getQm().deleteTransaction( jobQueueName, execution.getTransactionId(), null ); getEm().update( data ); getEm().update( stat ); return; } // re-schedule the job to run again in the future scheduleJob( execution.getJobName(), System.currentTimeMillis() + delay, data.getUuid(), stat.getUuid() ); // delete the pending transaction getQm().deleteTransaction( jobQueueName, execution.getTransactionId(), null ); // update the data for the next run getEm().update( data ); getEm().update( stat ); } catch ( Exception e ) { // should never happen throw new JobRuntimeException( String.format( "Unable to delete job data with id %s", data.getUuid() ), e ); } }
assertEquals( 1, stat.getTotalAttempts() ); assertEquals( runCount, stat.getRunCount() ); assertEquals( delayCount, stat.getDelayCount() );
@Test public void transitionsOk() { JobData data = new JobData(); JobStat stat = new JobStat(); JobDescriptor jobDescriptor = new JobDescriptor( "", UUID.randomUUID(), UUID.randomUUID(), data, stat, null ); JobExecution bje = new JobExecutionImpl( jobDescriptor ); assertEquals( JobExecution.Status.NOT_STARTED, bje.getStatus() ); bje.start( 1 ); assertEquals( JobExecution.Status.IN_PROGRESS, bje.getStatus() ); bje.completed(); assertEquals( JobExecution.Status.COMPLETED, bje.getStatus() ); }
@Test public void failureTriggerNoTrip() { JobData data = new JobData(); JobStat stat = new JobStat(); JobDescriptor jobDescriptor = new JobDescriptor( "", UUID.randomUUID(), UUID.randomUUID(), data, stat, null ); JobExecution bje = new JobExecutionImpl( jobDescriptor ); bje.start( JobExecution.FOREVER ); assertEquals( Status.IN_PROGRESS, bje.getStatus() ); assertEquals( 1, stat.getRunCount() ); bje.failed(); assertEquals( Status.FAILED, bje.getStatus() ); assertEquals( 1, stat.getRunCount() ); // now fail again, we should trigger a state change bje = new JobExecutionImpl( jobDescriptor ); bje.start( JobExecution.FOREVER ); assertEquals( Status.IN_PROGRESS, bje.getStatus() ); assertEquals( 2, stat.getRunCount() ); bje.failed(); assertEquals( Status.FAILED, bje.getStatus() ); assertEquals( 2, stat.getRunCount() ); }
assertEquals( numberOfRuns, stat.getTotalAttempts() ); assertEquals( numberOfRuns, stat.getRunCount() ); assertEquals( 0, stat.getDelayCount() );
@Test public void transitionsDead() { JobData data = new JobData(); JobStat stat = new JobStat(); JobDescriptor jobDescriptor = new JobDescriptor( "", UUID.randomUUID(), UUID.randomUUID(), data, stat, null ); JobExecution bje = new JobExecutionImpl( jobDescriptor ); assertEquals( JobExecution.Status.NOT_STARTED, bje.getStatus() ); bje.start( 1 ); assertEquals( JobExecution.Status.IN_PROGRESS, bje.getStatus() ); bje.killed(); assertEquals( JobExecution.Status.DEAD, bje.getStatus() ); }
assertEquals( totalAttempts, stat.getTotalAttempts() ); assertEquals( totalAttempts, stat.getRunCount() ); assertEquals( 0, stat.getDelayCount() );
@Test public void doubleInvokeFail() { JobData data = new JobData(); JobStat stat = new JobStat(); JobDescriptor jobDescriptor = new JobDescriptor( "", UUID.randomUUID(), UUID.randomUUID(), data, stat, null ); JobExecution bje = new JobExecutionImpl( jobDescriptor ); bje.start( 1 ); try { bje.start( 1 ); fail( "Should have failed on double start() call" ); } catch ( IllegalStateException ise ) { } bje.completed(); try { bje.completed(); fail( "Should have failed on double complete call" ); } catch ( IllegalStateException ise ) { } } }
assertEquals( numberOfRuns, stat.getTotalAttempts() ); assertEquals( numberOfRuns, stat.getRunCount() ); assertEquals( 0, stat.getDelayCount() ); assertEquals( numberOfRuns, stat.getTotalAttempts() ); assertEquals( numberOfRuns, stat.getRunCount() ); assertEquals( 0, stat.getDelayCount() );
@Test public void transitionFail() { JobData data = new JobData(); JobStat stat = new JobStat(); JobDescriptor jobDescriptor = new JobDescriptor( "", UUID.randomUUID(), UUID.randomUUID(), data, stat, null ); JobExecution bje = new JobExecutionImpl( jobDescriptor ); try { bje.completed(); fail( "Should have throw ISE on NOT_STARTED to IN_PROGRESS" ); } catch ( IllegalStateException ise ) { } try { bje.failed(); fail( "Should have thrown ISE on NOT_STARTED to FAILED" ); } catch ( IllegalStateException ise ) { } bje.start( 1 ); bje.completed(); try { bje.failed(); fail( "Should have failed failed after complete call" ); } catch ( IllegalStateException ise ) { } }
@Test public void transitionFailOnDeath() { JobData data = new JobData(); JobStat stat = new JobStat(); JobDescriptor jobDescriptor = new JobDescriptor( "", UUID.randomUUID(), UUID.randomUUID(), data, stat, null ); JobExecution bje = new JobExecutionImpl( jobDescriptor ); try { bje.completed(); fail( "Should have throw ISE on NOT_STARTED to IN_PROGRESS" ); } catch ( IllegalStateException ise ) { } try { bje.failed(); fail( "Should have thrown ISE on NOT_STARTED to FAILED" ); } catch ( IllegalStateException ise ) { } bje.start( 1 ); bje.killed(); try { bje.killed(); fail( "Should have failed failed after complete call" ); } catch ( IllegalStateException ise ) { } }