package com.github.signed.sandboxes.spring.data.bg;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import static com.github.signed.sandboxes.spring.data.bg.JobState.Cancelled;
import static com.github.signed.sandboxes.spring.data.bg.JobState.Done;
import static com.github.signed.sandboxes.spring.data.bg.JobState.InProgress;
import static com.github.signed.sandboxes.spring.data.bg.JobType.CancelAction;
import static com.github.signed.sandboxes.spring.data.bg.JobType.ExecuteAction;
import static java.util.stream.Collectors.groupingBy;
public class JobScheduler {
private final JobsRepository jobsRepository;
public JobScheduler(JobsRepository jobsRepository) {
this.jobsRepository = jobsRepository;
}
public void schedule() {
List<Job> jobs = jobsRepository.letsSeeAllJobsForAReferenceKeyWhereAtLeastOneJobIsIn(JobState.Pending);
List<JobHistory> jobHistories = jobs.stream().collect(groupingBy(job -> job.referenceKey))
.values().stream().map(JobHistory::createFromUnsorted).collect(Collectors.toList());
jobHistories.parallelStream().forEach(this::update);
}
private void update(JobHistory jobHistory) {
JobInContext pendingJob = jobHistory.earliestPendingJob().get();
Optional<JobInContext> maybePrecedingJob = pendingJob.precedingJob();
switch (pendingJob.type()) {
case ExecuteAction:
if (!maybePrecedingJob.isPresent()) {
set(pendingJob, InProgress);
break;
}
maybePrecedingJob.ifPresent(precedingJob -> {
if (precedingJob.isOfType(ExecuteAction)) {
set(pendingJob, Done);
return;
}
if (precedingJob.isOfType(CancelAction)) {
if (precedingJob.isInTerminalState()) {
set(pendingJob, InProgress);
return;
}
}
});
break;
case CancelAction:
if (!maybePrecedingJob.isPresent()) {
set(pendingJob, Done);
break;
}
maybePrecedingJob.ifPresent(precedingJob -> {
if (precedingJob.isOfType(ExecuteAction)) {
set(precedingJob, Cancelled);
set(pendingJob, InProgress);
return;
}
if(precedingJob.isOfType(CancelAction)){
set(pendingJob, Done);
return;
}
});
break;
default:
throw new IllegalStateException("Should not happen");
}
}
private void set(JobInContext pendingJob, JobState newState) {
}
}