Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deleting state #1386

Merged
merged 23 commits into from
Feb 10, 2017
Merged

Deleting state #1386

merged 23 commits into from
Feb 10, 2017

Conversation

matush-v
Copy link
Contributor

Creates a new request state DELETING to better know when a request is still going through cleanup. Request State begins as DELETING and is changed to DELETED once all tasks for the request are cleaned. Currently using USER_REQUESTED_DESTROY to determine if the task is a delete request.

@tpetr @ssalinas

@ssalinas ssalinas modified the milestone: 0.14.0 Jan 3, 2017
return save(request, RequestState.DELETING, historyType, timestamp, user, message);
}

public SingularityCreateResult deleted(SingularityRequest request, RequestHistoryType historyType, long timestamp, Optional<String> user, Optional<String> message) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe for these methods we name them more like an action. i.e. markDeleted or markDeleting, just to clarify what they are doing. Especially since we already have a deleteRequest method (which could maybe be renamed to something like startRequestDelete?)

Optional<SingularityRequestHistory> maybeHistory = requestHistoryHelper.getLastHistory(requestId);
if (maybeHistory.isPresent() && maybeHistory.get().getRequest().isLoadBalanced() && configuration.isDeleteRemovedRequestsFromLoadBalancer()) {
createLbCleanupRequest(requestId, matchingActiveTaskIds);
if (matchingActiveTaskIds.iterator().hasNext()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe Iterables.isEmpty(matchingActiveTaskIds) just for cleanliness/readability


private void cleanupRequestIfNoRemainingTasks(SingularityTaskId taskId, Map<String, List<String>> requestIdToTaskIds) {
List<String> requestTasks = requestIdToTaskIds.get(taskId.getRequestId());
requestTasks.remove(taskId.getId());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

requestIdToTaskIds isn't guaranteed to have the key present, will want to check that or this line will cause NPEs

Copy link
Contributor Author

@matush-v matush-v Jan 9, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, I didn't notice we would hit this method for other cleanup types that weren't in the requestIdToTaskIds map. updated to return early if it's null
bitmoji

@ssalinas
Copy link
Member

ssalinas commented Jan 3, 2017

Overall looks good, the few comments I left and a test that needs to be fixed:

  • SingularityHistoryTest.testMessage - count of history items is wrong now that we are creating another history entry

SingularityDeleteResult deleteResult = delete(getRequestPath(request.getId()));

markDeleting(request, RequestHistoryType.DELETED, System.currentTimeMillis(), user, message);

LOG.info("Request {} deleted ({}) by {} - {}", request.getId(), deleteResult, user, message);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ssalinas should we adjust these log messages too? They're a bit misleading since they kind of jump the gun on the status

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, might be good for the log line to suggest it was 'enqueued for delete' rather than 'deleted'

@@ -328,9 +334,12 @@ public SingularityDeleteResult deleteRequest(SingularityRequest request, Optiona

saveHistory(new SingularityRequestHistory(now, user, RequestHistoryType.DELETED, request, message));

// moves RequestState to DELETED
SingularityDeleteResult deleteResult = delete(getRequestPath(request.getId()));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we want to still be able to grab request data while it is in DELETING state, we shouldn't have this line here. This deletes all of the current request data. We should probably move this step to be triggered by the cleaner after everything is done (i.e. when the active deploy cleanup is happening)

@@ -1,5 +1,5 @@
package com.hubspot.singularity;

public enum SingularityDeleteResult {
DELETED, DIDNT_EXIST;
DELETING, DELETED, DIDNT_EXIST;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added this state to better reflect the state of the delete when it's first requested

@@ -16,7 +16,7 @@
private final Optional<String> message;

public enum RequestHistoryType {
CREATED, UPDATED, DELETED, PAUSED, UNPAUSED, ENTERED_COOLDOWN, EXITED_COOLDOWN, FINISHED, DEPLOYED_TO_UNPAUSE, BOUNCED, SCALED, SCALE_REVERTED;
CREATED, UPDATED, DELETING, DELETED, PAUSED, UNPAUSED, ENTERED_COOLDOWN, EXITED_COOLDOWN, FINISHED, DEPLOYED_TO_UNPAUSE, BOUNCED, SCALED, SCALE_REVERTED;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added this state to better reflect the state of the request history

@@ -346,7 +345,7 @@ private void drainRequestCleanupQueue() {
}
break;
case DELETING:
if (requestWithState.isPresent()) {
if (requestWithState.isPresent() && requestWithState.get().getState() != RequestState.DELETING) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added this to make sure deleting states aren't ignored and will be cleaned up properly

@ssalinas
Copy link
Member

mentioned in person, but to document here as well. Last change needed for this would be to remove the piece of ui code that makes the Remove button redirect you back to the requests page. Should be gtg after that

@matush-v
Copy link
Contributor Author

@ssalinas cool to move this into staging tmrw morning?

@ssalinas
Copy link
Member

@darcatron you can just do a then={fetchRequestAndHistory} rather that doing the window.reload in the ui portion. That will trigger a re-fetch of the request data from the api, but we won't need to reload the entire page. After that small change, yeah, think we are good for staging

@@ -458,6 +462,24 @@ private TaskCleanupType pause(SingularityRequestCleanup requestCleanup, Iterable
return cleanupType;
}

private void delete(SingularityRequestCleanup requestCleanup, Iterable<SingularityTaskId> activeTaskIds){
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ssalinas I kept the name as delete since it followed the pattern set by the other actions (pause, bounce, etc.)

@matush-v
Copy link
Contributor Author

matush-v commented Jan 20, 2017

Made the fixes and tested them locally. The request tasks are deleted appropriately and the request is then re-enqueued for cleanup. The user and message are preserved as well.

Also, I noticed the deploy and request history weren't updating so I fixed that. This is especially helpful when deleting a request so a user can see that it goes to a deleting state and then deleted state without refreshing the page

@ssalinas

Copy link
Member

@ssalinas ssalinas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's remove those output.log and the .json files from your testing and address the two comments. Should be good to re-test in staging after that.

@@ -91,7 +91,9 @@ const mapDispatchToProps = (dispatch, ownProps) => {
FetchRequest.trigger(ownProps.params.requestId, true),
FetchActiveTasksForRequest.trigger(ownProps.params.requestId),
FetchScheduledTasksForRequest.trigger(ownProps.params.requestId),
FetchTaskCleanups.trigger()
FetchTaskCleanups.trigger(),
FetchDeploysForRequest.trigger(ownProps.params.requestId, 5, 1),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't want to be fetching these two here. These are actions that will auto-refresh on an interval. Since deploy history and request history are paginated, fetching this would reset the user back to the first page on a schedule. We should instead use the then values of the buttons you are editing to make sure the correct api calls are made in reaction to a user action.

Additionally, the deploy history won't be changing in our request deletion updates, only the request history

@@ -162,7 +162,7 @@ const RequestActionButtons = ({requestParent, fetchRequest, fetchRequestHistory,

const navigateAwayOnSuccess = (response) => {
if (response.statusCode === 200) {
router.push('/requests');
then={fetchRequestAndHistory}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can move this a few lines down and get rid of the navigateAwayOnSuccess method:
<RemoveButton requestId={request.id} then={fetchRequestAndHistoryAndActiveTasks}>

  • Don't need the 200 check here since we are staying on the page regardless of the outcome of the api call
  • Added the ...AndActiveTasks portion because they will likely be updated to cleaning after the deletion is requested

runBeforeKillId = Optional.of(shellRequest.getId());
}

taskManager.createTaskCleanup(new SingularityTaskCleanup(requestCleanup.getUser(), TaskCleanupType.USER_REQUESTED_DESTROY, start, taskId, requestCleanup.getMessage(), requestCleanup.getActionId(), runBeforeKillId));
Copy link
Member

@ssalinas ssalinas Jan 24, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missed this one initially, my fault here. This has some unintended consequences. With this in place, any task that is forcibly killed by a user will then cause the request to be deleted as well. We need a new TaskCleanupType that is separate. Something like REQUEST_DELETING with killLongRunningTaskInstantly and killNonLongRunningTaskInstantly both set to true like they are for the destroy

de9a21d

@matush-v
Copy link
Contributor Author

matush-v commented Feb 8, 2017

Added a test to make sure that a single deleted task doesn't delete the entire request. Going to go through the branch merging (staging, qa, stable) to get it updated

@ssalinas
Copy link
Member

LGTM

@matush-v matush-v merged commit cb7271f into master Feb 10, 2017
@matush-v matush-v deleted the deleting-state branch February 10, 2017 15:56
@tpetr tpetr removed hs_qa labels Feb 10, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants