package eu.europeana.cloud.service.dps.service.zoo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import eu.europeana.cloud.service.coordination.ZookeeperService;
import eu.europeana.cloud.service.coordination.configuration.DynamicPropertyManager;
import eu.europeana.cloud.service.coordination.configuration.ZookeeperDynamicPropertyManager;
import eu.europeana.cloud.service.dps.TaskExecutionReportService;
import eu.europeana.cloud.service.dps.exception.AccessDeniedOrObjectDoesNotExistException;
/**
* Stores / retrieves dps tasks and task progress notifications from / to Kafka
* topics.
* <p/>
* Progress notifications are stored in Zookeeper directories as direct ZK child nodes of the root parent ZK node
* (which is specified in {@link #ZOOKEEPER_PATH}).
* <p/>
* Example:
* <p/>
* An example property node is "/eCloud/v2/ISTI/configuration/tasks/xslt-32427389328/progress".
* For the above example, an example-value for "progress", for task "xslt-32427389328" would be "50",
* that indicates that current progress is at 50%.
*
* @author manos
*/
public class ZookeeperReportService implements TaskExecutionReportService {
private static final Logger LOGGER = LoggerFactory.getLogger(ZookeeperReportService.class);
private final static int ZOOKEEPER_CONNECTION_TIME = 3000;
private final static int ZOOKEEPER_SESSION_TIMEOUT = 3000;
/**
* Key used to store TaskExecution progress in a Zookeeper node
*/
private final static String PROGRESS_KEY = "progress";
/**
* Base path where all metrics are stored.
*/
private final static String ZOOKEEPER_PATH = "/dps-tasks";
private ZookeeperService zS;
private DynamicPropertyManager pManager;
public ZookeeperReportService(ZookeeperService zS, DynamicPropertyManager pManager) {
this.pManager = pManager;
this.zS = zS;
}
public ZookeeperReportService(String zookeeperAddress) {
zS = new ZookeeperService(zookeeperAddress,
ZOOKEEPER_CONNECTION_TIME, ZOOKEEPER_SESSION_TIMEOUT, ZOOKEEPER_PATH);
pManager = new ZookeeperDynamicPropertyManager(zS, ZOOKEEPER_PATH);
}
@Override
public String getTaskProgress(String taskId) throws AccessDeniedOrObjectDoesNotExistException {
return getProgress(taskId);
}
@Override
public String getTaskNotificationChuncks(String taskId, int from, int to) {
throw new UnsupportedOperationException("Not implemented yet");
}
@Override
public void incrTaskProgress(String taskId) {
incr(taskId, PROGRESS_KEY);
}
/**
* @param taskId where progress refers to
* TaskId is also used to get the path where the progress is stored.
* @return Progress for the specified taskId
* @throws AccessDeniedOrObjectDoesNotExistException
*/
private String getProgress(String taskId) throws AccessDeniedOrObjectDoesNotExistException {
final String key = taskId + "/" + PROGRESS_KEY;
LOGGER.info("fetching progress for task with key {}", key);
String currentValue = pManager.getCurrentValue(key);
if (currentValue == null) {
throw new AccessDeniedOrObjectDoesNotExistException("Progress for taskId: [" + taskId + "] not found..");
}
return currentValue;
}
/**
* Increases the current value of the specified @param metric
* by 1.
*
* @param taskId Metric belongs to this taskId
* <p/>
* TaskId is used to generate the path where the metric will be stored.
*/
private void incr(String taskId, String metric) {
final String key = taskId + "/" + metric;
String currentValue = pManager.getCurrentValue(key);
if (currentValue == null) {
currentValue = "0";
}
int c = Integer.parseInt(currentValue);
c += 1;
pManager.updateValue(key, c + "");
}
}