com.hubspot.singularity.data.RequestManager Maven / Gradle / Ivy
package com.hubspot.singularity.data;
import java.util.Collection;
import java.util.List;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.utils.ZKPaths;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.hubspot.singularity.RequestState;
import com.hubspot.singularity.SingularityCreateResult;
import com.hubspot.singularity.SingularityDeployKey;
import com.hubspot.singularity.SingularityPendingRequest;
import com.hubspot.singularity.SingularityRequest;
import com.hubspot.singularity.SingularityRequestCleanup;
import com.hubspot.singularity.SingularityRequestCleanup.RequestCleanupType;
import com.hubspot.singularity.SingularityRequestHistory;
import com.hubspot.singularity.SingularityRequestHistory.RequestHistoryType;
import com.hubspot.singularity.SingularityRequestWithState;
import com.hubspot.singularity.config.SingularityConfiguration;
import com.hubspot.singularity.data.transcoders.Transcoder;
@Singleton
public class RequestManager extends CuratorAsyncManager {
private static final Logger LOG = LoggerFactory.getLogger(RequestManager.class);
private final Transcoder requestTranscoder;
private final Transcoder pendingRequestTranscoder;
private final Transcoder requestCleanupTranscoder;
private final Transcoder requestHistoryTranscoder;
private final WebhookManager webhookManager;
private static final String REQUEST_ROOT = "/requests";
private static final String NORMAL_PATH_ROOT = REQUEST_ROOT + "/all";
private static final String PENDING_PATH_ROOT = REQUEST_ROOT + "/pending";
private static final String CLEANUP_PATH_ROOT = REQUEST_ROOT + "/cleanup";
private static final String HISTORY_PATH_ROOT = REQUEST_ROOT + "/history";
@Inject
public RequestManager(SingularityConfiguration configuration, CuratorFramework curator, WebhookManager webhookManager, Transcoder requestCleanupTranscoder,
Transcoder requestTranscoder, Transcoder pendingRequestTranscoder, Transcoder requestHistoryTranscoder) {
super(curator, configuration.getZookeeperAsyncTimeout());
this.requestTranscoder = requestTranscoder;
this.requestCleanupTranscoder = requestCleanupTranscoder;
this.pendingRequestTranscoder = pendingRequestTranscoder;
this.requestHistoryTranscoder = requestHistoryTranscoder;
this.webhookManager = webhookManager;
}
private String getRequestPath(String requestId) {
return ZKPaths.makePath(NORMAL_PATH_ROOT, requestId);
}
private String getHistoryParentPath(String requestId) {
return ZKPaths.makePath(HISTORY_PATH_ROOT, requestId);
}
private String getHistoryPath(SingularityRequestHistory history) {
return ZKPaths.makePath(getHistoryParentPath(history.getRequest().getId()), history.getEventType() + "-" + history.getCreatedAt());
}
private String getPendingPath(String requestId, String deployId) {
return ZKPaths.makePath(PENDING_PATH_ROOT, new SingularityDeployKey(requestId, deployId).getId());
}
private String getCleanupPath(String requestId, RequestCleanupType type) {
return ZKPaths.makePath(CLEANUP_PATH_ROOT, requestId + "-" + type.name());
}
public int getSizeOfPendingQueue() {
return getNumChildren(PENDING_PATH_ROOT);
}
public int getSizeOfCleanupQueue() {
return getNumChildren(CLEANUP_PATH_ROOT);
}
public int getNumRequests() {
return getNumChildren(NORMAL_PATH_ROOT);
}
public void deletePendingRequest(SingularityPendingRequest pendingRequest) {
delete(getPendingPath(pendingRequest.getRequestId(), pendingRequest.getDeployId()));
}
public void deleteHistoryParent(String requestId) {
delete(getHistoryParentPath(requestId));
}
public void deleteHistoryItem(SingularityRequestHistory history) {
delete(getHistoryPath(history));
}
public boolean cleanupRequestExists(String requestId) {
for (RequestCleanupType type : RequestCleanupType.values()) {
if (checkExists(getCleanupPath(requestId, type)).isPresent()) {
return true;
}
}
return false;
}
public void deleteCleanRequest(String requestId, RequestCleanupType type) {
delete(getCleanupPath(requestId, type));
}
public List getAllRequestIds() {
return getChildren(NORMAL_PATH_ROOT);
}
public List getRequestIdsWithHistory() {
return getChildren(HISTORY_PATH_ROOT);
}
public List getRequestHistory(String requestId) {
return getAsyncChildren(getHistoryParentPath(requestId), requestHistoryTranscoder);
}
public SingularityCreateResult createCleanupRequest(SingularityRequestCleanup cleanupRequest) {
return create(getCleanupPath(cleanupRequest.getRequestId(), cleanupRequest.getCleanupType()), cleanupRequest, requestCleanupTranscoder);
}
public SingularityCreateResult update(SingularityRequest request, long timestamp, Optional user) {
return save(request, getRequest(request.getId()).get().getState(), RequestHistoryType.UPDATED, timestamp, user);
}
private SingularityCreateResult save(SingularityRequest request, RequestState state, RequestHistoryType eventType, long timestamp, Optional user) {
saveHistory(new SingularityRequestHistory(timestamp, user, eventType, request));
return save(getRequestPath(request.getId()), new SingularityRequestWithState(request, state, timestamp), requestTranscoder);
}
public SingularityCreateResult pause(SingularityRequest request, long timestamp, Optional user) {
return save(request, RequestState.PAUSED, RequestHistoryType.PAUSED, timestamp, user);
}
public SingularityCreateResult cooldown(SingularityRequest request, long timestamp) {
return save(request, RequestState.SYSTEM_COOLDOWN, RequestHistoryType.ENTERED_COOLDOWN, timestamp, Optional. absent());
}
public SingularityCreateResult finish(SingularityRequest request, long timestamp) {
return save(request, RequestState.FINISHED, RequestHistoryType.FINISHED, timestamp, Optional. absent());
}
public SingularityCreateResult addToPendingQueue(SingularityPendingRequest pendingRequest) {
SingularityCreateResult result = create(getPendingPath(pendingRequest.getRequestId(), pendingRequest.getDeployId()), pendingRequest, pendingRequestTranscoder);
LOG.info("{} added to pending queue with result: {}", pendingRequest, result);
return result;
}
@VisibleForTesting
protected SingularityCreateResult saveHistory(SingularityRequestHistory history) {
final String path = getHistoryPath(history);
webhookManager.enqueueRequestUpdate(history);
return save(path, history, requestHistoryTranscoder);
}
public SingularityCreateResult unpause(SingularityRequest request, long timestamp, Optional user) {
return activate(request, RequestHistoryType.UNPAUSED, timestamp, user);
}
public SingularityCreateResult exitCooldown(SingularityRequest request, long timestamp) {
return activate(request, RequestHistoryType.EXITED_COOLDOWN, timestamp, Optional. absent());
}
public SingularityCreateResult deployToUnpause(SingularityRequest request, long timestamp, Optional user) {
return save(request, RequestState.DEPLOYING_TO_UNPAUSE, RequestHistoryType.DEPLOYED_TO_UNPAUSE, timestamp, user);
}
public SingularityCreateResult activate(SingularityRequest request, RequestHistoryType historyType, long timestamp, Optional user) {
return save(request, RequestState.ACTIVE, historyType, timestamp, user);
}
public List getPendingRequests() {
return getAsyncChildren(PENDING_PATH_ROOT, pendingRequestTranscoder);
}
public List getCleanupRequests() {
return getAsyncChildren(CLEANUP_PATH_ROOT, requestCleanupTranscoder);
}
public List getRequests(Collection requestIds) {
final List paths = Lists.newArrayListWithCapacity(requestIds.size());
for (String requestId : requestIds) {
paths.add(getRequestPath(requestId));
}
return getAsync(RequestManager.NORMAL_PATH_ROOT, paths, requestTranscoder);
}
private Iterable filter(List requests, final RequestState... states) {
return Iterables.filter(requests, new Predicate() {
@Override
public boolean apply(SingularityRequestWithState input) {
for (RequestState state : states) {
if (input.getState() == state) {
return true;
}
}
return false;
}
});
}
private Iterable getRequests(RequestState... states) {
return filter(getRequests(), states);
}
public Iterable getPausedRequests() {
return getRequests(RequestState.PAUSED);
}
public Iterable getActiveRequests() {
return getRequests(RequestState.ACTIVE, RequestState.DEPLOYING_TO_UNPAUSE);
}
public Iterable getCooldownRequests() {
return getRequests(RequestState.SYSTEM_COOLDOWN);
}
public Iterable getFinishedRequests() {
return getRequests(RequestState.FINISHED);
}
public List getRequests() {
return getAsyncChildren(NORMAL_PATH_ROOT, requestTranscoder);
}
public Optional getRequest(String requestId) {
return getData(getRequestPath(requestId), requestTranscoder);
}
public void deleteRequest(SingularityRequest request, Optional user) {
final long now = System.currentTimeMillis();
// delete it no matter if the delete request already exists.
createCleanupRequest(new SingularityRequestCleanup(user, RequestCleanupType.DELETING, now, Optional.of(Boolean.TRUE), request.getId(), Optional. absent()));
saveHistory(new SingularityRequestHistory(now, user, RequestHistoryType.DELETED, request));
delete(getRequestPath(request.getId()));
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy