package com.hubspot.singularity.scheduler; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; import org.apache.mesos.Protos.TaskState; import org.junit.Assert; import org.junit.Test; import com.google.common.base.Optional; import com.google.inject.Inject; import com.hubspot.singularity.RequestType; import com.hubspot.singularity.SingularityDeploy; import com.hubspot.singularity.SingularityRequest; import com.hubspot.singularity.SingularityRequestBuilder; import com.hubspot.singularity.SingularityRequestHistory.RequestHistoryType; import com.hubspot.singularity.SingularityTask; import com.hubspot.singularity.SingularityTaskId; import com.hubspot.singularity.data.history.SingularityDeployHistoryPersister; import com.hubspot.singularity.data.history.SingularityRequestHistoryPersister; import com.hubspot.singularity.data.history.SingularityTaskHistoryPersister; import io.dropwizard.db.DataSourceFactory; public class HistoryPersisterTest extends SingularitySchedulerTestBase { @Inject protected SingularityRequestHistoryPersister requestHistoryPersister; @Inject protected SingularityTaskHistoryPersister taskHistoryPersister; @Inject protected SingularityDeployHistoryPersister deployHistoryPersister; @Inject protected SingularityCleaner cleaner; public HistoryPersisterTest() { super(false); } @Test public void testRequestAgePurging() { initRequest(); configuration.setDeleteStaleRequestsFromZkWhenNoDatabaseAfterHours(7); requestHistoryPersister.runActionOnPoll(); Assert.assertTrue(!requestManager.getRequestHistory(requestId).isEmpty()); requestManager.startDeletingRequest(request, user, Optional.<String> absent(), Optional.<String> absent()); requestManager.deleteHistoryParent(requestId); requestManager.activate(request, RequestHistoryType.CREATED, System.currentTimeMillis() - TimeUnit.HOURS.toMillis(3), Optional.<String> absent(), Optional.<String> absent()); requestManager.cooldown(request, System.currentTimeMillis() - TimeUnit.HOURS.toMillis(2)); requestHistoryPersister.runActionOnPoll(); Assert.assertTrue(!requestManager.getRequestHistory(requestId).isEmpty()); configuration.setDeleteStaleRequestsFromZkWhenNoDatabaseAfterHours(1); requestHistoryPersister.runActionOnPoll(); Assert.assertTrue(requestManager.getRequestHistory(requestId).isEmpty()); } @Test public void testRequestCountPurging() { final SingularityRequest requestOne = new SingularityRequestBuilder("request1", RequestType.WORKER).build(); final SingularityRequest requestTwo = new SingularityRequestBuilder("request2", RequestType.WORKER).build(); final SingularityRequest requestThree = new SingularityRequestBuilder("request3", RequestType.WORKER).build(); saveRequest(requestOne); saveRequest(requestTwo); saveRequest(requestThree); configuration.setMaxRequestsWithHistoryInZkWhenNoDatabase(Optional.of(2)); configuration.setDeleteStaleRequestsFromZkWhenNoDatabaseAfterHours(7); requestManager.startDeletingRequest(requestOne, user, Optional.<String>absent(), Optional.<String>absent()); requestManager.deleteHistoryParent(requestOne.getId()); requestManager.activate(requestOne, RequestHistoryType.CREATED, System.currentTimeMillis() - TimeUnit.HOURS.toMillis(4), Optional.<String> absent(), Optional.<String> absent()); requestManager.cooldown(requestOne, System.currentTimeMillis() - TimeUnit.HOURS.toMillis(3)); requestManager.startDeletingRequest(requestTwo, user, Optional.<String>absent(), Optional.<String>absent()); requestManager.deleteHistoryParent(requestTwo.getId()); requestManager.activate(requestTwo, RequestHistoryType.CREATED, System.currentTimeMillis() - TimeUnit.HOURS.toMillis(4), Optional.<String> absent(), Optional.<String> absent()); requestManager.cooldown(requestTwo, System.currentTimeMillis() - TimeUnit.HOURS.toMillis(3)); requestManager.startDeletingRequest(requestThree, user, Optional.<String>absent(), Optional.<String>absent()); requestManager.deleteHistoryParent(requestThree.getId()); requestManager.activate(requestThree, RequestHistoryType.CREATED, System.currentTimeMillis() - TimeUnit.HOURS.toMillis(4), Optional.<String> absent(), Optional.<String> absent()); requestManager.cooldown(requestThree, System.currentTimeMillis() - TimeUnit.HOURS.toMillis(3)); Assert.assertEquals(2, requestManager.getRequestHistory(requestOne.getId()).size()); Assert.assertEquals(2, requestManager.getRequestHistory(requestTwo.getId()).size()); Assert.assertEquals(2, requestManager.getRequestHistory(requestThree.getId()).size()); requestHistoryPersister.runActionOnPoll(); Assert.assertEquals(0, requestManager.getRequestHistory(requestOne.getId()).size()); Assert.assertEquals(2, requestManager.getRequestHistory(requestTwo.getId()).size()); Assert.assertEquals(2, requestManager.getRequestHistory(requestThree.getId()).size()); } @Test public void testTaskAgePurging() { initLoadBalancedRequest(); initFirstDeploy(); SingularityTask taskOne = launchTask(request, firstDeploy, System.currentTimeMillis() - TimeUnit.HOURS.toMillis(3), 1, TaskState.TASK_RUNNING); SingularityTask taskTwo = launchTask(request, firstDeploy, System.currentTimeMillis() - TimeUnit.HOURS.toMillis(3), 2, TaskState.TASK_RUNNING); taskHistoryPersister.runActionOnPoll(); Assert.assertTrue(taskManager.getTaskHistory(taskOne.getTaskId()).isPresent()); Assert.assertTrue(taskManager.getTaskHistory(taskTwo.getTaskId()).isPresent()); configuration.setDeleteTasksFromZkWhenNoDatabaseAfterHours(1); taskHistoryPersister.runActionOnPoll(); Assert.assertTrue(taskManager.getTaskHistory(taskOne.getTaskId()).isPresent()); Assert.assertTrue(taskManager.getTaskHistory(taskTwo.getTaskId()).isPresent()); statusUpdate(taskOne, TaskState.TASK_FINISHED, Optional.of(System.currentTimeMillis() - TimeUnit.HOURS.toMillis(2))); taskHistoryPersister.runActionOnPoll(); Assert.assertTrue(taskManager.getTaskHistory(taskOne.getTaskId()).isPresent()); Assert.assertTrue(taskManager.getTaskHistory(taskTwo.getTaskId()).isPresent()); cleaner.drainCleanupQueue(); taskHistoryPersister.runActionOnPoll(); Assert.assertTrue(!taskManager.getTaskHistory(taskOne.getTaskId()).isPresent()); Assert.assertTrue(taskManager.getTaskHistory(taskTwo.getTaskId()).isPresent()); } @Test public void testTaskCountPurging() { initLoadBalancedRequest(); initFirstDeploy(); configuration.setMaxStaleTasksPerRequestInZkWhenNoDatabase(Optional.of(2)); final int tasksToLaunch = 10; final List<SingularityTaskId> taskIds = new ArrayList<>(); for (int i=0; i<tasksToLaunch; i++) { final SingularityTask task = launchTask(request, firstDeploy, System.currentTimeMillis() - TimeUnit.HOURS.toMillis(3), 1, TaskState.TASK_RUNNING); statusUpdate(task, TaskState.TASK_FINISHED, Optional.of(System.currentTimeMillis() - TimeUnit.HOURS.toMillis(2))); cleaner.drainCleanupQueue(); taskIds.add(task.getTaskId()); } final List<SingularityTaskId> tasksBeforePurge = taskManager.getInactiveTaskIdsForDeploy(requestId, firstDeployId); Assert.assertEquals(taskIds.size(), tasksBeforePurge.size()); Assert.assertTrue(tasksBeforePurge.containsAll(taskIds)); taskHistoryPersister.runActionOnPoll(); final List<SingularityTaskId> tasksAfterPurge = taskManager.getInactiveTaskIdsForDeploy(requestId, firstDeployId); Assert.assertEquals(configuration.getMaxStaleTasksPerRequestInZkWhenNoDatabase().get().intValue(), tasksAfterPurge.size()); Assert.assertTrue(tasksAfterPurge.containsAll(taskIds.subList(tasksToLaunch-2, tasksToLaunch-1))); // we should just have the last 2 tasks } @Test public void testDeployCountPurging() { SingularityRequest requestOne = buildRequest("request1"); SingularityRequest requestTwo = buildRequest("request2"); SingularityDeploy requestOneDeployOne = initAndFinishDeploy(requestOne, "r1d1"); SingularityDeploy requestOneDeployTwo = initAndFinishDeploy(requestOne, "r1d2"); SingularityDeploy requestOneDeployThree = initAndFinishDeploy(requestOne, "r1d3"); SingularityDeploy requestOneDeployFour = initAndFinishDeploy(requestOne, "r1d4"); // r1d4 is the active deploy, not eligible for purging SingularityDeploy requestTwoDeployOne = initAndFinishDeploy(requestTwo, "r2d1"); SingularityDeploy requestTwoDeployTwo = initAndFinishDeploy(requestTwo, "r2d2"); // r2d2 is the active deploy, not eligible for purging configuration.setMaxStaleDeploysPerRequestInZkWhenNoDatabase(Optional.of(2)); deployHistoryPersister.runActionOnPoll(); Assert.assertTrue(!deployManager.getDeployHistory(requestOneDeployOne.getRequestId(), requestOneDeployOne.getId(), true).isPresent()); Assert.assertTrue(deployManager.getDeployHistory(requestOneDeployTwo.getRequestId(), requestOneDeployTwo.getId(), true).isPresent()); Assert.assertTrue(deployManager.getDeployHistory(requestOneDeployThree.getRequestId(), requestOneDeployThree.getId(), true).isPresent()); Assert.assertTrue(deployManager.getDeployHistory(requestOneDeployFour.getRequestId(), requestOneDeployFour.getId(), true).isPresent()); Assert.assertTrue(deployManager.getDeployHistory(requestTwoDeployOne.getRequestId(), requestTwoDeployOne.getId(), true).isPresent()); Assert.assertTrue(deployManager.getDeployHistory(requestTwoDeployTwo.getRequestId(), requestTwoDeployTwo.getId(), true).isPresent()); } @Test public void testPurgingDoesntApplyIfDatabasePresent() { initRequest(); initFirstDeploy(); requestManager.startDeletingRequest(request, user, Optional.<String> absent(), Optional.<String> absent()); requestManager.deleteHistoryParent(requestId); requestManager.activate(request, RequestHistoryType.CREATED, System.currentTimeMillis() - TimeUnit.HOURS.toMillis(3), Optional.<String> absent(), Optional.<String> absent()); configuration.setDatabaseConfiguration(new DataSourceFactory()); configuration.setDeleteStaleRequestsFromZkWhenNoDatabaseAfterHours(1); requestHistoryPersister.runActionOnPoll(); Assert.assertTrue(!requestManager.getRequestHistory(requestId).isEmpty()); } }