package net.johnewart.gearman.embedded;
import net.johnewart.gearman.common.Job;
import net.johnewart.gearman.common.events.WorkEvent;
import net.johnewart.gearman.common.interfaces.GearmanFunction;
import net.johnewart.gearman.common.interfaces.EngineWorker;
import net.johnewart.gearman.common.interfaces.GearmanWorker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class EmbeddedGearmanWorker implements EngineWorker, GearmanWorker, Runnable {
private final Logger LOG = LoggerFactory.getLogger(EmbeddedGearmanWorker.class);
private final EmbeddedGearmanServer server;
private final Map<String, GearmanFunction> abilityMap;
private volatile boolean running;
private final Object runLock;
public EmbeddedGearmanWorker(EmbeddedGearmanServer server) {
this.server = server;
this.abilityMap = new HashMap<>();
this.running = true;
this.runLock = new Object();
}
public void registerCallback(String callback, GearmanFunction function) {
abilityMap.put(callback, function);
server.registerWorkerAbility(this, callback);
}
@Override
public void doWork() {
Job nextJob;
do {
nextJob = server.getNextJobForWorker(this);
if(nextJob != null) {
LOG.debug("Received work to do: " + nextJob.getJobHandle());
GearmanFunction function = abilityMap.get(nextJob.getFunctionName());
WorkEvent workEvent = new WorkEvent(nextJob, this);
final byte[] results = function.process(workEvent);
server.completeWork(nextJob, results);
}
} while (nextJob != null);
server.markWorkerAsleep(this);
}
@Override
public void stopWork() {
this.running = false;
synchronized(runLock) {
runLock.notify();
}
}
@Override
public void sendData(Job job, byte[] data) throws IOException {
// NOOP
}
@Override
public void sendStatus(Job job, int numerator, int denominator) throws IOException {
// NOOP
}
@Override
public void sendWarning(Job job, byte[] warning) throws IOException {
// NOOP
}
@Override
public void run() {
while(running) {
LOG.debug("Doing work...");
doWork();
LOG.debug("Completed all available work, sleeping...");
synchronized (runLock) {
try {
LOG.debug("Waiting up to 30s for notification of work...");
runLock.wait(30000);
LOG.debug("Woke up!!");
} catch (InterruptedException e) {
LOG.error("Error waiting on lock: ", e);
}
}
}
LOG.info("Worker thread completed.");
}
@Override
public Set<String> getAbilities() {
return abilityMap.keySet();
}
@Override
public void wakeUp() {
synchronized (runLock) {
runLock.notify();
}
}
@Override
public void markAsleep() {
//NOOP
}
}