package net.johnewart.gearman.server.cluster.queue;
import com.google.common.collect.ImmutableMap;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.core.IAtomicLong;
import net.johnewart.gearman.common.Job;
import net.johnewart.gearman.constants.JobPriority;
import net.johnewart.gearman.engine.core.QueuedJob;
import net.johnewart.gearman.engine.queue.JobQueue;
import net.johnewart.gearman.server.cluster.core.HazelcastJob;
import java.util.Collection;
import java.util.HashSet;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import static java.lang.String.format;
public class HazelcastJobQueue implements JobQueue {
private final HazelcastInstance hazelcast;
private final Queue<HazelcastJob> highQueue;
private final Queue<HazelcastJob> midQueue;
private final Queue<HazelcastJob> lowQueue;
private final Set<String> uniqueIds;
private final String queueName;
private final IAtomicLong maxQueueSize;
private final ConcurrentHashMap<String, Job> localJobs;
public HazelcastJobQueue(String name, HazelcastInstance hazelcast) {
this.hazelcast = hazelcast;
this.queueName = name;
this.highQueue = hazelcast.getQueue(format("jobs-%s-high", name));
this.midQueue = hazelcast.getQueue(format("jobs-%s-mid", name));
this.lowQueue = hazelcast.getQueue(format("jobs-%s-low", name));
this.uniqueIds = hazelcast.getSet(format("uniqueids-%s", name));
this.maxQueueSize = hazelcast.getAtomicLong(format("maxsize-%s", name));
this.localJobs = new ConcurrentHashMap<>();
}
@Override
public void enqueue(Job job) {
localJobs.put(job.getUniqueID(), job);
uniqueIds.add(job.getUniqueID());
switch(job.getPriority()) {
case HIGH:
highQueue.add(new HazelcastJob(job));
case NORMAL:
midQueue.add(new HazelcastJob(job));
case LOW:
lowQueue.add(new HazelcastJob(job));
default:
break;
}
}
@Override
public long size(JobPriority priority)
{
switch(priority) {
case HIGH:
return highQueue.size();
case NORMAL:
return midQueue.size();
case LOW:
return lowQueue.size();
default:
return -1;
}
}
@Override
public Job poll() {
HazelcastJob dequeued = highQueue.poll();
if(dequeued == null) {
dequeued = midQueue.poll();
}
if (dequeued == null) {
dequeued = lowQueue.poll();
}
if (dequeued != null) {
Job job = dequeued.toJob();
localJobs.put(job.getUniqueID(), job);
return job;
} else {
return null;
}
}
@Override
public long size() {
return highQueue.size() + midQueue.size() + lowQueue.size();
}
@Override
public boolean uniqueIdInUse(String uniqueID) {
return uniqueIds.contains(uniqueID);
}
@Override
public boolean isEmpty() {
return highQueue.isEmpty() && midQueue.isEmpty() && lowQueue.isEmpty();
}
@Override
public void setCapacity(int size) {
maxQueueSize.set(size);
}
@Override
public String getName() {
return queueName;
}
@Override
public boolean remove(Job job) {
localJobs.remove(job.getUniqueID());
uniqueIds.remove(job.getUniqueID());
switch(job.getPriority()) {
case HIGH:
return highQueue.remove(new HazelcastJob(job));
case NORMAL:
return midQueue.remove(new HazelcastJob(job));
case LOW:
return lowQueue.remove(new HazelcastJob(job));
default:
return false;
}
}
@Override
public Collection<QueuedJob> getAllJobs() {
return new HashSet<>();
}
@Override
public Job findJobByUniqueId(String uniqueID) {
return localJobs.get(uniqueID);
}
@Override
public ImmutableMap<Integer, Long> futureCounts() {
return ImmutableMap.of();
}
}