package com.hubspot.baragon.data;
import java.util.List;
import org.apache.curator.framework.CuratorFramework;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.codahale.metrics.annotation.Timed;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Optional;
import com.google.common.collect.Lists;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.hubspot.baragon.config.ZooKeeperConfiguration;
import com.hubspot.baragon.models.BaragonResponse;
@Singleton
public class BaragonResponseHistoryDatastore extends AbstractDataStore {
private static final Logger LOG = LoggerFactory.getLogger(BaragonResponseHistoryDatastore.class);
public static final String RESPONSE_HISTORIES_FORMAT = "/responseHistory";
public static final String RESPONSE_HISTORIES_FOR_SERVICE_FORMAT = RESPONSE_HISTORIES_FORMAT + "/%s";
public static final String RESPONSE_HISTORY_FORMAT = RESPONSE_HISTORIES_FOR_SERVICE_FORMAT + "/%s";
public static final String SERVICE_ID_FOR_REQUEST_FORMAT = RESPONSE_HISTORIES_FORMAT + "/requestIdMapping/%s";
@Inject
public BaragonResponseHistoryDatastore(CuratorFramework curatorFramework, ObjectMapper objectMapper, ZooKeeperConfiguration zooKeeperConfiguration) {
super(curatorFramework, objectMapper, zooKeeperConfiguration);
}
@Timed
public void addResponse(String serviceId, String requestId, BaragonResponse response) {
writeToZk(String.format(RESPONSE_HISTORY_FORMAT, serviceId, requestId), response);
writeToZk(String.format(SERVICE_ID_FOR_REQUEST_FORMAT, requestId), serviceId);
}
@Timed
public Optional<String> getServiceIdForRequestId(String requestId) {
return readFromZk(String.format(SERVICE_ID_FOR_REQUEST_FORMAT, requestId), String.class);
}
@Timed
public Optional<BaragonResponse> getResponse(String serviceId, String requestId) {
return readFromZk(String.format(RESPONSE_HISTORY_FORMAT, serviceId, requestId), BaragonResponse.class);
}
@Timed
public List<BaragonResponse> getResponsesForService(String serviceId, int limit) {
final List<String> nodes = getChildren(String.format(RESPONSE_HISTORIES_FOR_SERVICE_FORMAT, serviceId));
final List<BaragonResponse> responses = Lists.newArrayListWithCapacity(Math.min(nodes.size(), limit));
for (String requestId : nodes.subList(0, Math.min(nodes.size(), limit))) {
try {
responses.addAll(readFromZk(String.format(RESPONSE_HISTORY_FORMAT, serviceId, requestId), BaragonResponse.class).asSet());
} catch (Exception e) {
LOG.error(String.format("Could not fetch info for group %s due to error %s", requestId, e));
}
}
return responses;
}
@Timed
public Optional<Long> getRequestUpdatedAt(String serviceId, String requestId) {
return getUpdatedAt(String.format(RESPONSE_HISTORY_FORMAT, serviceId, requestId));
}
@Timed
public List<String> getServiceIds() {
return getChildren(RESPONSE_HISTORIES_FORMAT);
}
@Timed
public List<String> getRequestIdsForService(String serviceId) {
return getChildren(String.format(RESPONSE_HISTORIES_FOR_SERVICE_FORMAT, serviceId));
}
@Timed
public void deleteResponse(String serviceId, String requestId) {
deleteNode(String.format(RESPONSE_HISTORY_FORMAT, serviceId, requestId));
deleteNode(String.format(SERVICE_ID_FOR_REQUEST_FORMAT, requestId));
}
@Timed
public void deleteResponses(String serviceId) {
String path = String.format(RESPONSE_HISTORIES_FOR_SERVICE_FORMAT, serviceId);
List<String> requestIds = getChildren(path);
deleteNode(path, true);
for (String requestId : requestIds) {
deleteNode(String.format(SERVICE_ID_FOR_REQUEST_FORMAT, requestId));
}
}
}