net.nemerosa.ontrack.job.support.DefaultJobScheduler Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ontrack-job Show documentation
Show all versions of ontrack-job Show documentation
Abstract management of identified jobs.
package net.nemerosa.ontrack.job.support;
import net.nemerosa.ontrack.common.Time;
import net.nemerosa.ontrack.job.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
public class DefaultJobScheduler implements JobScheduler {
private final Logger logger = LoggerFactory.getLogger(JobScheduler.class);
private final JobDecorator jobDecorator;
private final ScheduledExecutorService scheduledExecutorService;
private final JobListener jobListener;
private final Map services = new ConcurrentHashMap<>(new TreeMap<>());
private final AtomicBoolean schedulerPaused = new AtomicBoolean(false);
private final AtomicLong idGenerator = new AtomicLong();
public DefaultJobScheduler(JobDecorator jobDecorator, ScheduledExecutorService scheduledExecutorService, JobListener jobListener) {
this.jobDecorator = jobDecorator;
this.scheduledExecutorService = scheduledExecutorService;
this.jobListener = jobListener;
}
@Override
public void schedule(Job job, Schedule schedule) {
logger.info("[job]{} Scheduling with {}", job.getKey(), schedule);
// Manages existing schedule
JobScheduledService existingService = services.remove(job.getKey());
if (existingService != null) {
logger.info("[job]{} Stopping existing schedule", job.getKey());
existingService.cancel(false);
}
// Creates and starts the scheduled service
logger.info("[job]{} Starting service", job.getKey());
// Copy stats from old schedule
JobScheduledService jobScheduledService = new JobScheduledService(
job,
schedule,
scheduledExecutorService,
existingService,
jobListener.isPausedAtStartup(job.getKey())
);
// Registration
services.put(job.getKey(), jobScheduledService);
}
@Override
public boolean unschedule(JobKey key) {
return unschedule(key, true);
}
protected boolean unschedule(JobKey key, boolean forceStop) {
JobScheduledService existingService = services.remove(key);
if (existingService != null) {
existingService.cancel(forceStop);
return true;
} else {
return false;
}
}
@Override
public void pause() {
schedulerPaused.set(true);
}
@Override
public void resume() {
schedulerPaused.set(false);
}
@Override
public boolean pause(JobKey key) {
JobScheduledService existingService = services.get(key);
if (existingService != null) {
existingService.pause();
return true;
} else {
throw new JobNotScheduledException(key);
}
}
@Override
public boolean resume(JobKey key) {
JobScheduledService existingService = services.get(key);
if (existingService != null) {
existingService.resume();
return true;
} else {
throw new JobNotScheduledException(key);
}
}
@Override
public Optional getJobStatus(JobKey key) {
JobScheduledService existingService = services.get(key);
if (existingService != null) {
return Optional.of(existingService.getJobStatus());
} else {
return Optional.empty();
}
}
@Override
public Optional getJobKey(long id) {
return services.values().stream()
.filter(service -> service.getId() == id)
.map(JobScheduledService::getJobKey)
.findFirst();
}
@Override
public Collection getAllJobKeys() {
return services.keySet();
}
@Override
public Collection getJobKeysOfType(JobType type) {
return getAllJobKeys().stream()
.filter(key -> key.sameType(type))
.collect(Collectors.toSet());
}
@Override
public Collection getJobKeysOfCategory(JobCategory category) {
return getAllJobKeys().stream()
.filter(key -> key.sameCategory(category))
.collect(Collectors.toSet());
}
@Override
public Collection getJobStatuses() {
return services.values().stream()
.map(JobScheduledService::getJobStatus)
.collect(Collectors.toList());
}
@Override
public Future> fireImmediately(JobKey jobKey) {
return fireImmediately(jobKey, Collections.emptyMap());
}
@Override
public Future> fireImmediately(JobKey jobKey, Map parameters) {
// Gets the existing scheduled service
JobScheduledService jobScheduledService = services.get(jobKey);
if (jobScheduledService == null) {
throw new JobNotScheduledException(jobKey);
}
// Fires the job immediately
return jobScheduledService.fireImmediately(true, parameters);
}
private class JobScheduledService implements Runnable {
private final long id;
private final Job job;
private final Schedule schedule;
private final ScheduledFuture> scheduledFuture;
private final AtomicBoolean paused;
private final AtomicReference
© 2015 - 2025 Weber Informatics LLC | Privacy Policy