JobManager implements ModeChangeListener { @Transactional public AsyncJobStatus cancelJob(String jobId) { if (jobId == null || jobId.isEmpty()) { throw new IllegalArgumentException("jobId is null or empty"); } AsyncJobStatus status = this.jobCurator.get(jobId); if (status != null) { if (status.getState().isTerminal()) { throw new IllegalStateException("job is already in a terminal state: " + status); } if (status.getState() != JobState.RUNNING) { this.setJobState(status, JobState.CANCELED); } else { log.warn("Attempting to cancel job that's already running: {}", status); if (status.getMaxAttempts() > 1) { log.warn("Setting max attempts to: 1"); status.setMaxAttempts(1); } } status = this.jobCurator.merge(status); } return status; } @Inject  JobManager(
        Configuration configuration,
        SchedulerFactory schedulerFactory,
        CandlepinModeManager modeManager,
        AsyncJobStatusCurator jobCurator,
        OwnerCurator ownerCurator,
        JobMessageDispatcher dispatcher,
        JobMessageReceiver receiver,
        PrincipalProvider principalProvider,
        CandlepinRequestScope scope,
        Injector injector); static Class<? extends AsyncJob> registerJob(String jobKey, Class<? extends AsyncJob> jobClass); static Class<? extends AsyncJob> unregisterJob(String jobKey); static Class<? extends AsyncJob> getJobClass(String jobKey); synchronized void initialize(); void start(); synchronized void start(Object key); void resume(); void resume(Object key); void suspend(); synchronized void suspend(Object key); synchronized void shutdown(); synchronized ManagerState getManagerState(); boolean isJobEnabled(String jobKey); boolean isSchedulerEnabled(); AsyncJobStatus findJob(String jobId); List<AsyncJobStatus> findJobs(AsyncJobStatusQueryBuilder queryBuilder); @Transactional AsyncJobStatus queueJob(JobConfig config); AsyncJobStatus executeJob(JobMessage message); @Transactional AsyncJobStatus cancelJob(String jobId); @Transactional int cleanupJobs(AsyncJobStatusQueryBuilder queryBuilder); @Transactional int abortNonTerminalJobs(AsyncJobStatusQueryBuilder queryBuilder); @Override void handleModeChange(CandlepinModeManager modeManager, Mode previousMode, Mode currentMode);  }
@Test public void testCancelJob() { String jobId = "job_id"; AsyncJobStatus expected = this.createJobStatus(jobId, null, JobState.QUEUED); this.injectMockedJobStatus(expected); JobManager manager = this.createJobManager(); AsyncJobStatus output = manager.cancelJob(expected.getId()); assertNotNull(output); assertEquals(expected.getId(), output.getId()); assertEquals(JobState.CANCELED, output.getState()); }
@Test public void testCancelJobDisablesRetryForRunningJobs() { String jobId = "job_id"; AsyncJobStatus expected = this.createJobStatus(jobId, null, JobState.RUNNING) .setMaxAttempts(5); this.injectMockedJobStatus(expected); JobManager manager = this.createJobManager(); AsyncJobStatus output = manager.cancelJob(expected.getId()); assertNotNull(output); assertEquals(expected.getId(), output.getId()); assertEquals(JobState.RUNNING, output.getState()); assertEquals(1, output.getMaxAttempts()); }