package edu.unc.lib.dl.util; import static edu.unc.lib.dl.util.RedisWorkerConstants.DEPOSIT_TO_JOBS_PREFIX; import static edu.unc.lib.dl.util.RedisWorkerConstants.JOB_STATUS_PREFIX; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import edu.unc.lib.dl.util.RedisWorkerConstants.JobField; import edu.unc.lib.dl.util.RedisWorkerConstants.JobStatus; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; public class JobStatusFactory { private JedisPool jedisPool; public JedisPool getJedisPool() { return jedisPool; } public void setJedisPool(JedisPool jedisPool) { this.jedisPool = jedisPool; } public void started(String jobUUID, String depositUUID, Class<?> jobClass) { Map<String, String> status = new HashMap<String, String>(); status.put(JobField.uuid.name(), jobUUID); status.put(JobField.name.name(), jobClass.getName()); status.put(JobField.status.name(), JobStatus.working.name()); status.put(JobField.starttime.name(), String.valueOf(System.currentTimeMillis())); status.put(JobField.num.name(), "0"); try (Jedis jedis = getJedisPool().getResource()) { jedis.hmset(JOB_STATUS_PREFIX + jobUUID, status); jedis.rpush(DEPOSIT_TO_JOBS_PREFIX + depositUUID, jobUUID); } } public void interrupted(String jobUUID) { try (Jedis jedis = getJedisPool().getResource()) { jedis.hset(JOB_STATUS_PREFIX + jobUUID, JobField.status.name(), JobStatus.queued.name()); jedis.hset(JOB_STATUS_PREFIX + jobUUID, JobField.endtime.name(), String.valueOf(System.currentTimeMillis())); } } public void failed(String jobUUID, String message) { try (Jedis jedis = getJedisPool().getResource()) { jedis.hset(JOB_STATUS_PREFIX + jobUUID, JobField.status.name(), JobStatus.failed.name()); jedis.hset(JOB_STATUS_PREFIX + jobUUID, JobField.endtime.name(), String.valueOf(System.currentTimeMillis())); if (message != null) { jedis.hset(JOB_STATUS_PREFIX + jobUUID, JobField.message.name(), message); } } } public void failed(String jobUUID) { failed(jobUUID, null); } /** * Removes the all leftover partially completed jobs from the deposit * * @param depositUUID */ public void clearStale(String depositUUID) { List<String> failed = getJobsByStatus(depositUUID, JobStatus.failed); List<String> queued = getJobsByStatus(depositUUID, JobStatus.queued); List<String> working = getJobsByStatus(depositUUID, JobStatus.working); List<String> uuids = new ArrayList<String>(failed); uuids.addAll(queued); uuids.addAll(working); try (Jedis jedis = getJedisPool().getResource()) { for (String uuid : uuids) { jedis.del(JOB_STATUS_PREFIX + uuid); jedis.lrem(DEPOSIT_TO_JOBS_PREFIX + depositUUID, 0, uuid); } } } public void completed(String jobUUID) { try (Jedis jedis = getJedisPool().getResource()) { jedis.hset(JOB_STATUS_PREFIX + jobUUID, JobField.status.name(), JobStatus.completed.name()); jedis.hset(JOB_STATUS_PREFIX + jobUUID, JobField.endtime.name(), String.valueOf(System.currentTimeMillis())); } } public void killed(String jobUUID) { try (Jedis jedis = getJedisPool().getResource()) { jedis.hset(JOB_STATUS_PREFIX + jobUUID, JobField.status.name(), JobStatus.killed.name()); jedis.hset(JOB_STATUS_PREFIX + jobUUID, JobField.endtime.name(), String.valueOf(System.currentTimeMillis())); } } public void incrCompletion(String jobUUID, int amount) { try (Jedis jedis = getJedisPool().getResource()) { jedis.hincrBy(JOB_STATUS_PREFIX + jobUUID, JobField.num.name(), amount); } } public String getJobState(String uuid) { try (Jedis jedis = getJedisPool().getResource()) { return jedis.hget(JOB_STATUS_PREFIX + uuid, JobField.status.name()); } } public void setTotalCompletion(String jobUUID, int totalClicks) { try (Jedis jedis = getJedisPool().getResource()) { jedis.hset(JOB_STATUS_PREFIX + jobUUID, JobField.total.name(), String.valueOf(totalClicks)); } } public Map<String, String> get(String jobUUID) { try (Jedis jedis = getJedisPool().getResource()) { return jedis.hgetAll(JOB_STATUS_PREFIX + jobUUID); } } /** * Retrieves the names of the jobs that have already succeeded for the deposit. * @param depositUUID the id of the deposit * @return a set of job class names */ public List<String> getSuccessfulJobNames(String depositUUID) { List<String> result = new ArrayList<String>(); try (Jedis jedis = getJedisPool().getResource()) { List<String> jobUUIDs = jedis.lrange(DEPOSIT_TO_JOBS_PREFIX + depositUUID, 0, -1); for (String jobUUID : jobUUIDs) { List<String> info = jedis.hmget(JOB_STATUS_PREFIX + jobUUID, new String[] { JobField.status.name(), JobField.name.name() }); if (JobStatus.completed.name().equals(info.get(0))) { result.add(info.get(1)); } } } return result; } /** * Delete all job status related to the deposit. * @param depositUUID */ public void deleteAll(String depositUUID) { try (Jedis jedis = getJedisPool().getResource()) { List<String> jobUUIDs = jedis.lrange(DEPOSIT_TO_JOBS_PREFIX + depositUUID, 0, -1); for (String jobUUID : jobUUIDs) { jedis.del(JOB_STATUS_PREFIX + jobUUID); } jedis.del(DEPOSIT_TO_JOBS_PREFIX + depositUUID); } } public String getWorkingJob(String depositUUID) { return getJobByStatus(depositUUID, JobStatus.working); } public String getJobByStatus(String depositUUID, JobStatus status) { try (Jedis jedis = getJedisPool().getResource()) { List<String> jobUUIDs = jedis.lrange(DEPOSIT_TO_JOBS_PREFIX + depositUUID, 0, -1); for (String jobUUID : jobUUIDs) { String statusValue = jedis.hget(JOB_STATUS_PREFIX + jobUUID, JobField.status.name()); if (status.name().equals(statusValue)) { return jobUUID; } } } return null; } public List<String> getJobsByStatus(String depositUUID, JobStatus status) { List<String> result = new ArrayList<>(); try (Jedis jedis = getJedisPool().getResource()) { List<String> jobUUIDs = jedis.lrange(DEPOSIT_TO_JOBS_PREFIX + depositUUID, 0, -1); for (String jobUUID : jobUUIDs) { String statusValue = jedis.hget(JOB_STATUS_PREFIX + jobUUID, JobField.status.name()); if (status.name().equals(statusValue)) { result.add(jobUUID); } } } return result; } /** * Expire all the job keys associated with this deposit in X seconds. * @param depositUUID * @param statusKeysExpireSeconds time until expire */ public void expireKeys(String depositUUID, int seconds) { try (Jedis jedis = getJedisPool().getResource()) { List<String> jobUUIDs = jedis.lrange(DEPOSIT_TO_JOBS_PREFIX + depositUUID, 0, -1); for (String jobUUID : jobUUIDs) { jedis.expire(RedisWorkerConstants.JOB_STATUS_PREFIX+jobUUID, seconds); } jedis.expire(RedisWorkerConstants.DEPOSIT_TO_JOBS_PREFIX + depositUUID, seconds); } } public Map<String, Map<String, String>> getAllJobs(String depositUUID) { Map<String, Map<String, String>> results = new LinkedHashMap<>(); try (Jedis jedis = getJedisPool().getResource()) { List<String> jobUUIDs = jedis.lrange(DEPOSIT_TO_JOBS_PREFIX + depositUUID, 0, -1); for (String jobUUID : jobUUIDs) { Map<String, String> status = jedis.hgetAll(JOB_STATUS_PREFIX + jobUUID); results.put(jobUUID, status); } } return results; } }