You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aurora.apache.org by wf...@apache.org on 2015/04/21 20:54:51 UTC
[2/3] aurora git commit: Require non-default primitive values in
StorageEntityUtil.
http://git-wip-us.apache.org/repos/asf/aurora/blob/449a835e/src/test/java/org/apache/aurora/scheduler/storage/db/DBJobUpdateStoreTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/storage/db/DBJobUpdateStoreTest.java b/src/test/java/org/apache/aurora/scheduler/storage/db/DBJobUpdateStoreTest.java
deleted file mode 100644
index 1f50515..0000000
--- a/src/test/java/org/apache/aurora/scheduler/storage/db/DBJobUpdateStoreTest.java
+++ /dev/null
@@ -1,1076 +0,0 @@
-/**
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.aurora.scheduler.storage.db;
-
-import java.util.List;
-import java.util.Set;
-
-import com.google.common.base.Optional;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-
-import org.apache.aurora.gen.Constraint;
-import org.apache.aurora.gen.ExecutorConfig;
-import org.apache.aurora.gen.Identity;
-import org.apache.aurora.gen.InstanceTaskConfig;
-import org.apache.aurora.gen.JobInstanceUpdateEvent;
-import org.apache.aurora.gen.JobKey;
-import org.apache.aurora.gen.JobUpdate;
-import org.apache.aurora.gen.JobUpdateAction;
-import org.apache.aurora.gen.JobUpdateDetails;
-import org.apache.aurora.gen.JobUpdateEvent;
-import org.apache.aurora.gen.JobUpdateInstructions;
-import org.apache.aurora.gen.JobUpdateKey;
-import org.apache.aurora.gen.JobUpdateQuery;
-import org.apache.aurora.gen.JobUpdateSettings;
-import org.apache.aurora.gen.JobUpdateState;
-import org.apache.aurora.gen.JobUpdateStatus;
-import org.apache.aurora.gen.JobUpdateSummary;
-import org.apache.aurora.gen.Lock;
-import org.apache.aurora.gen.LockKey;
-import org.apache.aurora.gen.Metadata;
-import org.apache.aurora.gen.Range;
-import org.apache.aurora.gen.TaskConfig;
-import org.apache.aurora.gen.TaskConstraint;
-import org.apache.aurora.gen.ValueConstraint;
-import org.apache.aurora.gen.storage.StoredJobUpdateDetails;
-import org.apache.aurora.scheduler.base.JobKeys;
-import org.apache.aurora.scheduler.storage.Storage;
-import org.apache.aurora.scheduler.storage.Storage.MutableStoreProvider;
-import org.apache.aurora.scheduler.storage.Storage.MutateWork;
-import org.apache.aurora.scheduler.storage.Storage.StorageException;
-import org.apache.aurora.scheduler.storage.Storage.Work.Quiet;
-import org.apache.aurora.scheduler.storage.entities.IJobInstanceUpdateEvent;
-import org.apache.aurora.scheduler.storage.entities.IJobKey;
-import org.apache.aurora.scheduler.storage.entities.IJobUpdate;
-import org.apache.aurora.scheduler.storage.entities.IJobUpdateDetails;
-import org.apache.aurora.scheduler.storage.entities.IJobUpdateEvent;
-import org.apache.aurora.scheduler.storage.entities.IJobUpdateInstructions;
-import org.apache.aurora.scheduler.storage.entities.IJobUpdateKey;
-import org.apache.aurora.scheduler.storage.entities.IJobUpdateQuery;
-import org.apache.aurora.scheduler.storage.entities.IJobUpdateSummary;
-import org.apache.aurora.scheduler.storage.entities.ILock;
-import org.apache.aurora.scheduler.storage.testing.StorageEntityUtil;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import static org.apache.aurora.gen.JobUpdateAction.INSTANCE_ROLLBACK_FAILED;
-import static org.apache.aurora.gen.JobUpdateAction.INSTANCE_ROLLED_BACK;
-import static org.apache.aurora.gen.JobUpdateAction.INSTANCE_ROLLING_BACK;
-import static org.apache.aurora.gen.JobUpdateAction.INSTANCE_UPDATED;
-import static org.apache.aurora.gen.JobUpdateAction.INSTANCE_UPDATING;
-import static org.apache.aurora.gen.JobUpdateStatus.ABORTED;
-import static org.apache.aurora.gen.JobUpdateStatus.ERROR;
-import static org.apache.aurora.gen.JobUpdateStatus.FAILED;
-import static org.apache.aurora.gen.JobUpdateStatus.ROLLED_BACK;
-import static org.apache.aurora.gen.JobUpdateStatus.ROLLING_BACK;
-import static org.apache.aurora.gen.JobUpdateStatus.ROLLING_FORWARD;
-import static org.apache.aurora.gen.JobUpdateStatus.ROLL_BACK_PAUSED;
-import static org.apache.aurora.gen.JobUpdateStatus.ROLL_FORWARD_PAUSED;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
-public class DBJobUpdateStoreTest {
-
- private static final IJobKey JOB = JobKeys.from("testRole", "testEnv", "job");
- private static final IJobUpdateKey UPDATE1 =
- IJobUpdateKey.build(new JobUpdateKey(JOB.newBuilder(), "update1"));
- private static final IJobUpdateKey UPDATE2 = IJobUpdateKey.build(
- new JobUpdateKey(JobKeys.from("testRole", "testEnv", "job2").newBuilder(), "update2"));
- private static final long CREATED_MS = 111L;
- private static final IJobUpdateEvent FIRST_EVENT =
- makeJobUpdateEvent(ROLLING_FORWARD, CREATED_MS);
-
- private Storage storage;
-
- @Before
- public void setUp() throws Exception {
- storage = DbUtil.createStorage();
- }
-
- @After
- public void tearDown() throws Exception {
- truncateUpdates();
- }
-
- @Test
- public void testSaveJobUpdates() {
- IJobUpdateKey updateId1 = makeKey(JobKeys.from("role", "env", "name1"), "u1");
- IJobUpdateKey updateId2 = makeKey(JobKeys.from("role", "env", "name2"), "u2");
-
- IJobUpdate update1 = makeJobUpdate(updateId1);
- IJobUpdate update2 = makeJobUpdate(updateId2);
-
- assertEquals(Optional.<IJobUpdate>absent(), getUpdate(updateId1));
- assertEquals(Optional.<IJobUpdate>absent(), getUpdate(updateId2));
-
- StorageEntityUtil.assertFullyPopulated(
- update1,
- StorageEntityUtil.getField(JobUpdateSummary.class, "state"),
- StorageEntityUtil.getField(IJobUpdateSummary.class, "state"));
- saveUpdate(update1, Optional.of("lock1"));
- assertUpdate(update1);
-
- saveUpdate(update2, Optional.<String>absent());
- assertUpdate(update2);
-
- // Colliding update IDs should be forbidden.
- IJobUpdate update3 =
- makeJobUpdate(makeKey(JobKeys.from("role", "env", "name3"), updateId2.getId()));
- try {
- saveUpdate(update3, Optional.<String>absent());
- fail("Update ID collision should not be allowed");
- } catch (StorageException e) {
- // Expected.
- }
- }
-
- @Test
- public void testSaveNullInitialState() {
- JobUpdate builder = makeJobUpdate(makeKey("u1")).newBuilder();
- builder.getInstructions().unsetInitialState();
-
- // Save with null initial state instances.
- saveUpdate(IJobUpdate.build(builder), Optional.of("lock"));
-
- builder.getInstructions().setInitialState(ImmutableSet.<InstanceTaskConfig>of());
- assertUpdate(IJobUpdate.build(builder));
- }
-
- @Test
- public void testSaveNullDesiredState() {
- JobUpdate builder = makeJobUpdate(makeKey("u1")).newBuilder();
- builder.getInstructions().unsetDesiredState();
-
- // Save with null desired state instances.
- saveUpdate(IJobUpdate.build(builder), Optional.of("lock"));
-
- assertUpdate(IJobUpdate.build(builder));
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testSaveBothInitialAndDesiredMissingThrows() {
- JobUpdate builder = makeJobUpdate(makeKey("u1")).newBuilder();
- builder.getInstructions().unsetInitialState();
- builder.getInstructions().unsetDesiredState();
-
- saveUpdate(IJobUpdate.build(builder), Optional.of("lock"));
- }
-
- @Test(expected = NullPointerException.class)
- public void testSaveNullInitialStateTaskThrows() {
- JobUpdate builder = makeJobUpdate(makeKey("u1")).newBuilder();
- builder.getInstructions().getInitialState().add(
- new InstanceTaskConfig(null, ImmutableSet.<Range>of()));
-
- saveUpdate(IJobUpdate.build(builder), Optional.of("lock"));
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testSaveEmptyInitialStateRangesThrows() {
- JobUpdate builder = makeJobUpdate(makeKey("u1")).newBuilder();
- builder.getInstructions().getInitialState().add(
- new InstanceTaskConfig(new TaskConfig(), ImmutableSet.<Range>of()));
-
- saveUpdate(IJobUpdate.build(builder), Optional.of("lock"));
- }
-
- @Test(expected = NullPointerException.class)
- public void testSaveNullDesiredStateTaskThrows() {
- JobUpdate builder = makeJobUpdate(makeKey("u1")).newBuilder();
- builder.getInstructions().getDesiredState().setTask(null);
-
- saveUpdate(IJobUpdate.build(builder), Optional.of("lock"));
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testSaveEmptyDesiredStateRangesThrows() {
- JobUpdate builder = makeJobUpdate(makeKey("u1")).newBuilder();
- builder.getInstructions().getDesiredState().setInstances(ImmutableSet.<Range>of());
-
- saveUpdate(IJobUpdate.build(builder), Optional.of("lock"));
- }
-
- @Test
- public void testSaveJobUpdateEmptyInstanceOverrides() {
- IJobUpdateKey updateId = makeKey("u1");
-
- IJobUpdate update = makeJobUpdate(updateId);
- JobUpdate builder = update.newBuilder();
- builder.getInstructions().getSettings().setUpdateOnlyTheseInstances(ImmutableSet.<Range>of());
-
- IJobUpdate expected = IJobUpdate.build(builder);
-
- // Save with empty overrides.
- saveUpdate(expected, Optional.of("lock"));
- assertUpdate(expected);
- }
-
- @Test
- public void testSaveJobUpdateNullInstanceOverrides() {
- IJobUpdateKey updateId = makeKey("u1");
-
- IJobUpdate update = makeJobUpdate(updateId);
- JobUpdate builder = update.newBuilder();
- builder.getInstructions().getSettings().setUpdateOnlyTheseInstances(ImmutableSet.<Range>of());
-
- IJobUpdate expected = IJobUpdate.build(builder);
-
- // Save with null overrides.
- builder.getInstructions().getSettings().setUpdateOnlyTheseInstances(null);
- saveUpdate(IJobUpdate.build(builder), Optional.of("lock"));
- assertUpdate(expected);
- }
-
- @Test(expected = StorageException.class)
- public void testSaveJobUpdateTwiceThrows() {
- IJobUpdateKey updateId = makeKey("u1");
- IJobUpdate update = makeJobUpdate(updateId);
-
- saveUpdate(update, Optional.of("lock1"));
- saveUpdate(update, Optional.of("lock2"));
- }
-
- @Test
- public void testSaveJobEvents() {
- IJobUpdateKey updateId = makeKey("u3");
- IJobUpdate update = makeJobUpdate(updateId);
- IJobUpdateEvent event1 = makeJobUpdateEvent(ROLLING_FORWARD, 124L);
- IJobUpdateEvent event2 = makeJobUpdateEvent(ROLL_FORWARD_PAUSED, 125L);
-
- saveUpdate(update, Optional.of("lock1"));
- assertUpdate(update);
- assertEquals(ImmutableList.of(FIRST_EVENT), getUpdateDetails(updateId).get().getUpdateEvents());
-
- saveJobEvent(event1, updateId);
- assertEquals(
- populateExpected(update, ROLLING_FORWARD, CREATED_MS, 124L),
- getUpdateDetails(updateId).get().getUpdate());
- assertEquals(event1, getUpdateDetails(updateId).get().getUpdateEvents().get(1));
-
- saveJobEvent(event2, updateId);
- assertEquals(
- populateExpected(update, ROLL_FORWARD_PAUSED, CREATED_MS, 125L),
- getUpdateDetails(updateId).get().getUpdate());
- assertEquals(event1, getUpdateDetails(updateId).get().getUpdateEvents().get(1));
- assertEquals(event2, getUpdateDetails(updateId).get().getUpdateEvents().get(2));
- }
-
- @Test
- public void testSaveInstanceEvents() {
- IJobUpdateKey updateId = makeKey("u3");
- IJobUpdate update = makeJobUpdate(updateId);
- IJobInstanceUpdateEvent event1 = makeJobInstanceEvent(0, 125L, INSTANCE_UPDATED);
- IJobInstanceUpdateEvent event2 = makeJobInstanceEvent(1, 126L, INSTANCE_ROLLING_BACK);
-
- saveUpdate(update, Optional.of("lock"));
- assertUpdate(update);
- assertEquals(0, getUpdateDetails(updateId).get().getInstanceEvents().size());
-
- saveJobInstanceEvent(event1, updateId);
- assertEquals(
- populateExpected(update, ROLLING_FORWARD, CREATED_MS, 125L),
- getUpdateDetails(updateId).get().getUpdate());
- assertEquals(
- event1,
- Iterables.getOnlyElement(getUpdateDetails(updateId).get().getInstanceEvents()));
-
- saveJobInstanceEvent(event2, updateId);
- assertEquals(
- populateExpected(update, ROLLING_FORWARD, CREATED_MS, 126L),
- getUpdateDetails(updateId).get().getUpdate());
- assertEquals(event1, getUpdateDetails(updateId).get().getInstanceEvents().get(0));
- assertEquals(event2, getUpdateDetails(updateId).get().getInstanceEvents().get(1));
- }
-
- @Test(expected = StorageException.class)
- public void testSaveJobEventWithoutUpdateFails() {
- saveJobEvent(makeJobUpdateEvent(ROLLING_FORWARD, 123L), makeKey("u2"));
- }
-
- @Test(expected = StorageException.class)
- public void testSaveInstanceEventWithoutUpdateFails() {
- saveJobInstanceEvent(makeJobInstanceEvent(0, 125L, INSTANCE_UPDATED), makeKey("u1"));
- }
-
- @Test
- public void testSaveJobUpdateStateIgnored() {
- IJobUpdateKey updateId = makeKey("u1");
- IJobUpdate update = populateExpected(makeJobUpdate(updateId), ABORTED, 567L, 567L);
- saveUpdate(update, Optional.of("lock1"));
-
- // Assert state fields were ignored.
- assertUpdate(update);
- }
-
- @Test
- public void testSaveJobUpdateWithoutEventFailsSelect() {
- final IJobUpdateKey updateId = makeKey("u3");
- storage.write(new MutateWork.NoResult.Quiet() {
- @Override
- public void execute(MutableStoreProvider storeProvider) {
- IJobUpdate update = makeJobUpdate(updateId);
- storeProvider.getLockStore().saveLock(makeLock(update.getSummary().getJobKey(), "lock1"));
- storeProvider.getJobUpdateStore().saveJobUpdate(update, Optional.of("lock1"));
- }
- });
- assertEquals(Optional.<IJobUpdateDetails>absent(), getUpdateDetails(updateId));
- }
-
- @Test
- public void testMultipleJobDetails() {
- IJobUpdateKey updateId1 = makeKey(JobKeys.from("role", "env", "name1"), "u1");
- IJobUpdateKey updateId2 = makeKey(JobKeys.from("role", "env", "name2"), "u2");
- IJobUpdateDetails details1 = makeJobDetails(makeJobUpdate(updateId1));
- IJobUpdateDetails details2 = makeJobDetails(makeJobUpdate(updateId2));
-
- assertEquals(ImmutableList.<IJobInstanceUpdateEvent>of(), getInstanceEvents(updateId2, 3));
-
- saveUpdate(details1.getUpdate(), Optional.of("lock1"));
- saveUpdate(details2.getUpdate(), Optional.of("lock2"));
-
- details1 = updateJobDetails(populateExpected(details1.getUpdate()), FIRST_EVENT);
- details2 = updateJobDetails(populateExpected(details2.getUpdate()), FIRST_EVENT);
- assertEquals(Optional.of(details1), getUpdateDetails(updateId1));
- assertEquals(Optional.of(details2), getUpdateDetails(updateId2));
-
- IJobUpdateEvent jEvent11 = makeJobUpdateEvent(ROLLING_FORWARD, 456L);
- IJobUpdateEvent jEvent12 = makeJobUpdateEvent(ERROR, 457L);
- IJobInstanceUpdateEvent iEvent11 = makeJobInstanceEvent(1, 451L, INSTANCE_UPDATED);
- IJobInstanceUpdateEvent iEvent12 = makeJobInstanceEvent(2, 452L, INSTANCE_UPDATING);
-
- IJobUpdateEvent jEvent21 = makeJobUpdateEvent(ROLL_FORWARD_PAUSED, 567L);
- IJobUpdateEvent jEvent22 = makeJobUpdateEvent(ABORTED, 568L);
- IJobInstanceUpdateEvent iEvent21 = makeJobInstanceEvent(3, 561L, INSTANCE_UPDATING);
- IJobInstanceUpdateEvent iEvent22 = makeJobInstanceEvent(3, 562L, INSTANCE_UPDATED);
-
- saveJobEvent(jEvent11, updateId1);
- saveJobEvent(jEvent12, updateId1);
- saveJobInstanceEvent(iEvent11, updateId1);
- saveJobInstanceEvent(iEvent12, updateId1);
-
- saveJobEvent(jEvent21, updateId2);
- saveJobEvent(jEvent22, updateId2);
- assertEquals(ImmutableList.<IJobInstanceUpdateEvent>of(), getInstanceEvents(updateId2, 3));
- saveJobInstanceEvent(iEvent21, updateId2);
-
- assertEquals(ImmutableList.of(iEvent21), getInstanceEvents(updateId2, 3));
- saveJobInstanceEvent(iEvent22, updateId2);
- assertEquals(ImmutableList.of(iEvent21, iEvent22), getInstanceEvents(updateId2, 3));
-
- details1 = updateJobDetails(
- populateExpected(details1.getUpdate(), ERROR, CREATED_MS, 457L),
- ImmutableList.of(FIRST_EVENT, jEvent11, jEvent12), ImmutableList.of(iEvent11, iEvent12));
-
- details2 = updateJobDetails(
- populateExpected(details2.getUpdate(), ABORTED, CREATED_MS, 568L),
- ImmutableList.of(FIRST_EVENT, jEvent21, jEvent22), ImmutableList.of(iEvent21, iEvent22));
-
- assertEquals(Optional.of(details1), getUpdateDetails(updateId1));
- assertEquals(Optional.of(details2), getUpdateDetails(updateId2));
-
- assertEquals(
- ImmutableSet.of(
- new StoredJobUpdateDetails(details1.newBuilder(), "lock1"),
- new StoredJobUpdateDetails(details2.newBuilder(), "lock2")),
- getAllUpdateDetails());
-
- assertEquals(
- ImmutableList.of(getUpdateDetails(updateId2).get(), getUpdateDetails(updateId1).get()),
- queryDetails(new JobUpdateQuery().setRole("role")));
- }
-
- @Test
- public void testTruncateJobUpdates() {
- IJobUpdateKey updateId = makeKey("u5");
- IJobUpdate update = makeJobUpdate(updateId);
- IJobInstanceUpdateEvent instanceEvent = IJobInstanceUpdateEvent.build(
- new JobInstanceUpdateEvent(0, 125L, INSTANCE_ROLLBACK_FAILED));
-
- saveUpdate(update, Optional.of("lock"));
- saveJobEvent(makeJobUpdateEvent(ROLLING_FORWARD, 123L), updateId);
- saveJobInstanceEvent(instanceEvent, updateId);
- assertEquals(
- populateExpected(update, ROLLING_FORWARD, CREATED_MS, 125L),
- getUpdate(updateId).get());
- assertEquals(2, getUpdateDetails(updateId).get().getUpdateEvents().size());
- assertEquals(1, getUpdateDetails(updateId).get().getInstanceEvents().size());
-
- truncateUpdates();
- assertEquals(Optional.<IJobUpdateDetails>absent(), getUpdateDetails(updateId));
- }
-
- @Test
- public void testPruneHistory() {
- IJobUpdateKey updateId1 = makeKey("u11");
- IJobUpdateKey updateId2 = makeKey("u12");
- IJobUpdateKey updateId3 = makeKey("u13");
- IJobUpdateKey updateId4 = makeKey("u14");
- IJobKey job2 = JobKeys.from("testRole2", "testEnv2", "job2");
- IJobUpdateKey updateId5 = makeKey(job2, "u15");
- IJobUpdateKey updateId6 = makeKey(job2, "u16");
- IJobUpdateKey updateId7 = makeKey(job2, "u17");
-
- IJobUpdate update1 = makeJobUpdate(updateId1);
- IJobUpdate update2 = makeJobUpdate(updateId2);
- IJobUpdate update3 = makeJobUpdate(updateId3);
- IJobUpdate update4 = makeJobUpdate(updateId4);
- IJobUpdate update5 = makeJobUpdate(updateId5);
- IJobUpdate update6 = makeJobUpdate(updateId6);
- IJobUpdate update7 = makeJobUpdate(updateId7);
-
- IJobUpdateEvent updateEvent1 = makeJobUpdateEvent(ROLLING_BACK, 123L);
- IJobUpdateEvent updateEvent2 = makeJobUpdateEvent(ABORTED, 124L);
- IJobUpdateEvent updateEvent3 = makeJobUpdateEvent(ROLLED_BACK, 125L);
- IJobUpdateEvent updateEvent4 = makeJobUpdateEvent(FAILED, 126L);
- IJobUpdateEvent updateEvent5 = makeJobUpdateEvent(ERROR, 123L);
- IJobUpdateEvent updateEvent6 = makeJobUpdateEvent(FAILED, 125L);
- IJobUpdateEvent updateEvent7 = makeJobUpdateEvent(ROLLING_FORWARD, 126L);
-
- update1 = populateExpected(
- saveUpdateNoEvent(update1, Optional.of("lock1")), ROLLING_BACK, 123L, 123L);
- update2 = populateExpected(
- saveUpdateNoEvent(update2, Optional.<String>absent()), ABORTED, 124L, 124L);
- update3 = populateExpected(
- saveUpdateNoEvent(update3, Optional.<String>absent()), ROLLED_BACK, 125L, 125L);
- update4 = populateExpected(
- saveUpdateNoEvent(update4, Optional.<String>absent()), FAILED, 126L, 126L);
- update5 = populateExpected(
- saveUpdateNoEvent(update5, Optional.<String>absent()), ERROR, 123L, 123L);
- update6 = populateExpected(
- saveUpdateNoEvent(update6, Optional.<String>absent()), FAILED, 125L, 125L);
- update7 = populateExpected(
- saveUpdateNoEvent(update7, Optional.of("lock2")), ROLLING_FORWARD, 126L, 126L);
-
- saveJobEvent(updateEvent1, updateId1);
- saveJobEvent(updateEvent2, updateId2);
- saveJobEvent(updateEvent3, updateId3);
- saveJobEvent(updateEvent4, updateId4);
- saveJobEvent(updateEvent5, updateId5);
- saveJobEvent(updateEvent6, updateId6);
- saveJobEvent(updateEvent7, updateId7);
-
- assertEquals(update1, getUpdate(updateId1).get());
- assertEquals(update2, getUpdate(updateId2).get());
- assertEquals(update3, getUpdate(updateId3).get());
- assertEquals(update4, getUpdate(updateId4).get());
- assertEquals(update5, getUpdate(updateId5).get());
- assertEquals(update6, getUpdate(updateId6).get());
- assertEquals(update7, getUpdate(updateId7).get());
-
- long pruningThreshold = 120L;
-
- // No updates pruned.
- assertEquals(ImmutableSet.<IJobUpdateKey>of(), pruneHistory(3, pruningThreshold));
- assertEquals(Optional.of(update7), getUpdate(updateId7)); // active update
- assertEquals(Optional.of(update6), getUpdate(updateId6));
- assertEquals(Optional.of(update5), getUpdate(updateId5));
-
- assertEquals(Optional.of(update4), getUpdate(updateId4));
- assertEquals(Optional.of(update3), getUpdate(updateId3));
- assertEquals(Optional.of(update2), getUpdate(updateId2));
- assertEquals(Optional.of(update1), getUpdate(updateId1)); // active update
-
- assertEquals(ImmutableSet.of(updateId2), pruneHistory(2, pruningThreshold));
- // No updates pruned.
- assertEquals(Optional.of(update7), getUpdate(updateId7)); // active update
- assertEquals(Optional.of(update6), getUpdate(updateId6));
- assertEquals(Optional.of(update5), getUpdate(updateId5));
-
- // 1 update pruned.
- assertEquals(Optional.of(update4), getUpdate(updateId4));
- assertEquals(Optional.of(update3), getUpdate(updateId3));
- assertEquals(Optional.<IJobUpdate>absent(), getUpdate(updateId2));
- assertEquals(Optional.of(update1), getUpdate(updateId1)); // active update
-
- assertEquals(ImmutableSet.of(updateId5, updateId3), pruneHistory(1, pruningThreshold));
- // 1 update pruned.
- assertEquals(Optional.of(update7), getUpdate(updateId7)); // active update
- assertEquals(Optional.of(update6), getUpdate(updateId6));
- assertEquals(Optional.<IJobUpdate>absent(), getUpdate(updateId5));
-
- // 2 updates pruned.
- assertEquals(Optional.of(update4), getUpdate(updateId4));
- assertEquals(Optional.<IJobUpdate>absent(), getUpdate(updateId3));
- assertEquals(Optional.of(update1), getUpdate(updateId1)); // active update
-
- // The oldest update is pruned.
- assertEquals(ImmutableSet.of(updateId6), pruneHistory(1, 126L));
- assertEquals(Optional.of(update7), getUpdate(updateId7)); // active update
- assertEquals(Optional.<IJobUpdate>absent(), getUpdate(updateId6));
-
- assertEquals(Optional.of(update4), getUpdate(updateId4));
- assertEquals(Optional.of(update1), getUpdate(updateId1)); // active update
-
- // Nothing survives the 0 per job count.
- assertEquals(ImmutableSet.of(updateId4), pruneHistory(0, pruningThreshold));
- assertEquals(Optional.of(update7), getUpdate(updateId7)); // active update
-
- assertEquals(Optional.<IJobUpdate>absent(), getUpdate(updateId4));
- assertEquals(Optional.of(update1), getUpdate(updateId1)); // active update
- }
-
- @Test(expected = StorageException.class)
- public void testSaveUpdateWithoutLock() {
- final IJobUpdate update = makeJobUpdate(makeKey("updateId"));
- storage.write(new MutateWork.NoResult.Quiet() {
- @Override
- public void execute(MutableStoreProvider storeProvider) {
- storeProvider.getJobUpdateStore().saveJobUpdate(update, Optional.of("lock"));
- }
- });
- }
-
- @Test(expected = StorageException.class)
- public void testSaveTwoUpdatesForOneJob() {
- final IJobUpdate update = makeJobUpdate(makeKey("updateId"));
- saveUpdate(update, Optional.of("lock1"));
- saveUpdate(update, Optional.of("lock2"));
- }
-
- @Test(expected = StorageException.class)
- public void testSaveTwoUpdatesSameJobKey() {
- final IJobUpdate update1 = makeJobUpdate(makeKey("update1"));
- final IJobUpdate update2 = makeJobUpdate(makeKey("update2"));
- saveUpdate(update1, Optional.of("lock1"));
- saveUpdate(update2, Optional.of("lock1"));
- }
-
- @Test
- public void testLockCleared() {
- final IJobUpdate update = makeJobUpdate(makeKey("update1"));
- saveUpdate(update, Optional.of("lock1"));
-
- removeLock(update, "lock1");
-
- assertEquals(
- Optional.of(updateJobDetails(populateExpected(update), FIRST_EVENT)),
- getUpdateDetails(makeKey("update1")));
- assertEquals(
- ImmutableSet.of(
- new StoredJobUpdateDetails(
- updateJobDetails(populateExpected(update), FIRST_EVENT).newBuilder(),
- null)),
- getAllUpdateDetails());
-
- assertEquals(
- ImmutableList.of(populateExpected(update).getSummary()),
- getSummaries(new JobUpdateQuery().setKey(UPDATE1.newBuilder())));
-
- // If the lock has been released for this job, we can start another update.
- saveUpdate(makeJobUpdate(makeKey("update2")), Optional.of("lock2"));
- }
-
- private static final Optional<String> NO_TOKEN = Optional.absent();
-
- @Test
- public void testGetLockToken() {
- storage.write(new MutateWork.NoResult.Quiet() {
- @Override
- public void execute(MutableStoreProvider storeProvider) {
- final IJobUpdate update1 = makeJobUpdate(UPDATE1);
- final IJobUpdate update2 = makeJobUpdate(UPDATE2);
- saveUpdate(update1, Optional.of("lock1"));
- assertEquals(
- Optional.of("lock1"),
- storeProvider.getJobUpdateStore().getLockToken(UPDATE1));
- assertEquals(NO_TOKEN, storeProvider.getJobUpdateStore().getLockToken(UPDATE2));
-
- saveUpdate(update2, Optional.of("lock2"));
- assertEquals(
- Optional.of("lock1"),
- storeProvider.getJobUpdateStore().getLockToken(UPDATE1));
- assertEquals(
- Optional.of("lock2"),
- storeProvider.getJobUpdateStore().getLockToken(UPDATE2));
-
- storeProvider.getLockStore().removeLock(
- makeLock(update1.getSummary().getJobKey(), "lock1").getKey());
- assertEquals(NO_TOKEN, storeProvider.getJobUpdateStore().getLockToken(UPDATE1));
- assertEquals(
- Optional.of("lock2"),
- storeProvider.getJobUpdateStore().getLockToken(UPDATE2));
-
- storeProvider.getLockStore().removeLock(
- makeLock(update2.getSummary().getJobKey(), "lock2").getKey());
- assertEquals(NO_TOKEN, storeProvider.getJobUpdateStore().getLockToken(UPDATE1));
- assertEquals(NO_TOKEN, storeProvider.getJobUpdateStore().getLockToken(UPDATE2));
- }
- });
- }
-
- @Test
- public void testGetSummaries() {
- String role1 = "role1";
- IJobKey job1 = JobKeys.from(role1, "env", "name1");
- IJobKey job2 = JobKeys.from(role1, "env", "name2");
- IJobKey job3 = JobKeys.from(role1, "env", "name3");
- IJobKey job4 = JobKeys.from(role1, "env", "name4");
- IJobKey job5 = JobKeys.from("role", "env", "name5");
- IJobUpdateSummary s1 =
- saveSummary(makeKey(job1, "u1"), 1230L, ROLLED_BACK, "user", Optional.of("lock1"));
- IJobUpdateSummary s2 =
- saveSummary(makeKey(job2, "u2"), 1231L, ABORTED, "user", Optional.of("lock2"));
- IJobUpdateSummary s3 =
- saveSummary(makeKey(job3, "u3"), 1239L, ERROR, "user2", Optional.of("lock3"));
- IJobUpdateSummary s4 =
- saveSummary(makeKey(job4, "u4"), 1234L, ROLL_BACK_PAUSED, "user3", Optional.of("lock4"));
- IJobUpdateSummary s5 =
- saveSummary(makeKey(job5, "u5"), 1235L, ROLLING_FORWARD, "user4", Optional.of("lock5"));
-
- // Test empty query returns all.
- assertEquals(ImmutableList.of(s3, s5, s4, s2, s1), getSummaries(new JobUpdateQuery()));
-
- // Test query by updateId.
- assertEquals(
- ImmutableList.of(s1),
- getSummaries(new JobUpdateQuery().setKey(new JobUpdateKey(job1.newBuilder(), "u1"))));
-
- // Test query by role.
- assertEquals(
- ImmutableList.of(s3, s4, s2, s1),
- getSummaries(new JobUpdateQuery().setRole(role1)));
-
- // Test query by job key.
- assertEquals(
- ImmutableList.of(s5),
- getSummaries(new JobUpdateQuery().setJobKey(job5.newBuilder())));
-
- // Test querying by update key.
- assertEquals(
- ImmutableList.of(s5),
- getSummaries(
- new JobUpdateQuery().setKey(new JobUpdateKey(job5.newBuilder(), s5.getUpdateId()))));
-
- // Test querying by incorrect update keys.
- assertEquals(
- ImmutableList.<IJobUpdateSummary>of(),
- getSummaries(
- new JobUpdateQuery().setKey(new JobUpdateKey(job5.newBuilder(), s4.getUpdateId()))));
- assertEquals(
- ImmutableList.<IJobUpdateSummary>of(),
- getSummaries(
- new JobUpdateQuery().setKey(new JobUpdateKey(job4.newBuilder(), s5.getUpdateId()))));
-
- // Test query by user.
- assertEquals(ImmutableList.of(s2, s1), getSummaries(new JobUpdateQuery().setUser("user")));
-
- // Test query by one status.
- assertEquals(ImmutableList.of(s3), getSummaries(new JobUpdateQuery().setUpdateStatuses(
- ImmutableSet.of(ERROR))));
-
- // Test query by multiple statuses.
- assertEquals(ImmutableList.of(s3, s2, s1), getSummaries(new JobUpdateQuery().setUpdateStatuses(
- ImmutableSet.of(ERROR, ABORTED, ROLLED_BACK))));
-
- // Test query by empty statuses.
- assertEquals(
- ImmutableList.of(s3, s5, s4, s2, s1),
- getSummaries(new JobUpdateQuery().setUpdateStatuses(ImmutableSet.<JobUpdateStatus>of())));
-
- // Test paging.
- assertEquals(
- ImmutableList.of(s3, s5),
- getSummaries(new JobUpdateQuery().setLimit(2).setOffset(0)));
- assertEquals(
- ImmutableList.of(s4, s2),
- getSummaries(new JobUpdateQuery().setLimit(2).setOffset(2)));
- assertEquals(
- ImmutableList.of(s1),
- getSummaries(new JobUpdateQuery().setLimit(2).setOffset(4)));
-
- // Test no match.
- assertEquals(
- ImmutableList.<IJobUpdateSummary>of(),
- getSummaries(new JobUpdateQuery().setRole("no_match")));
- }
-
- @Test
- public void testQueryDetails() {
- IJobKey jobKey1 = JobKeys.from("role1", "env", "name1");
- IJobUpdateKey updateId1 = makeKey(jobKey1, "u1");
- IJobKey jobKey2 = JobKeys.from("role2", "env", "name2");
- IJobUpdateKey updateId2 = makeKey(jobKey2, "u2");
-
- IJobUpdate update1 = makeJobUpdate(updateId1);
- IJobUpdate update2 = makeJobUpdate(updateId2);
-
- assertEquals(ImmutableList.<IJobInstanceUpdateEvent>of(), getInstanceEvents(updateId2, 3));
-
- saveUpdate(update1, Optional.of("lock1"));
- saveUpdate(update2, Optional.of("lock2"));
-
- updateJobDetails(populateExpected(update1), FIRST_EVENT);
- updateJobDetails(populateExpected(update2), FIRST_EVENT);
-
- IJobUpdateEvent jEvent11 = makeJobUpdateEvent(ROLLING_BACK, 450L);
- IJobUpdateEvent jEvent12 = makeJobUpdateEvent(ROLLED_BACK, 500L);
- IJobInstanceUpdateEvent iEvent11 = makeJobInstanceEvent(1, 451L, INSTANCE_ROLLING_BACK);
- IJobInstanceUpdateEvent iEvent12 = makeJobInstanceEvent(2, 458L, INSTANCE_ROLLED_BACK);
-
- IJobUpdateEvent jEvent21 = makeJobUpdateEvent(ROLL_FORWARD_PAUSED, 550L);
- IJobUpdateEvent jEvent22 = makeJobUpdateEvent(ABORTED, 600L);
- IJobInstanceUpdateEvent iEvent21 = makeJobInstanceEvent(3, 561L, INSTANCE_UPDATING);
- IJobInstanceUpdateEvent iEvent22 = makeJobInstanceEvent(3, 570L, INSTANCE_UPDATED);
-
- saveJobEvent(jEvent11, updateId1);
- saveJobEvent(jEvent12, updateId1);
- saveJobInstanceEvent(iEvent11, updateId1);
- saveJobInstanceEvent(iEvent12, updateId1);
-
- saveJobEvent(jEvent21, updateId2);
- saveJobEvent(jEvent22, updateId2);
-
- saveJobInstanceEvent(iEvent21, updateId2);
- saveJobInstanceEvent(iEvent22, updateId2);
-
- IJobUpdateDetails details1 = getUpdateDetails(updateId1).get();
- IJobUpdateDetails details2 = getUpdateDetails(updateId2).get();
-
- // Test empty query returns all.
- assertEquals(ImmutableList.of(details2, details1), queryDetails(new JobUpdateQuery()));
-
- // Test query by update ID.
- assertEquals(
- ImmutableList.of(details1),
- queryDetails(new JobUpdateQuery().setKey(updateId1.newBuilder())));
-
- // Test query by role.
- assertEquals(
- ImmutableList.of(details2),
- queryDetails(new JobUpdateQuery().setRole(jobKey2.getRole())));
-
- // Test query by job key.
- assertEquals(
- ImmutableList.of(details2),
- queryDetails(new JobUpdateQuery().setJobKey(jobKey2.newBuilder())));
-
- // Test query by status.
- assertEquals(
- ImmutableList.of(details2),
- queryDetails(new JobUpdateQuery().setUpdateStatuses(ImmutableSet.of(ABORTED))));
-
- // Test no match.
- assertEquals(
- ImmutableList.<IJobUpdateDetails>of(),
- queryDetails(new JobUpdateQuery().setRole("no match")));
- }
-
- private static IJobUpdateKey makeKey(String id) {
- return makeKey(JOB, id);
- }
-
- private static IJobUpdateKey makeKey(IJobKey job, String id) {
- return IJobUpdateKey.build(new JobUpdateKey(job.newBuilder(), id));
- }
-
- private void assertUpdate(IJobUpdate expected) {
- IJobUpdateKey key = expected.getSummary().getKey();
- assertEquals(populateExpected(expected), getUpdate(key).get());
- assertEquals(getUpdate(key).get(), getUpdateDetails(key).get().getUpdate());
- assertEquals(getUpdateInstructions(key).get(), expected.getInstructions());
- }
-
- private Optional<IJobUpdate> getUpdate(final IJobUpdateKey key) {
- return storage.read(new Quiet<Optional<IJobUpdate>>() {
- @Override
- public Optional<IJobUpdate> apply(Storage.StoreProvider storeProvider) {
- return storeProvider.getJobUpdateStore().fetchJobUpdate(key);
- }
- });
- }
-
- private List<IJobInstanceUpdateEvent> getInstanceEvents(final IJobUpdateKey key, final int id) {
- return storage.read(new Quiet<List<IJobInstanceUpdateEvent>>() {
- @Override
- public List<IJobInstanceUpdateEvent> apply(Storage.StoreProvider storeProvider) {
- return storeProvider.getJobUpdateStore().fetchInstanceEvents(key, id);
- }
- });
- }
-
- private Optional<IJobUpdateInstructions> getUpdateInstructions(final IJobUpdateKey key) {
- return storage.read(new Quiet<Optional<IJobUpdateInstructions>>() {
- @Override
- public Optional<IJobUpdateInstructions> apply(Storage.StoreProvider storeProvider) {
- return storeProvider.getJobUpdateStore().fetchJobUpdateInstructions(key);
- }
- });
- }
-
- private Optional<IJobUpdateDetails> getUpdateDetails(final IJobUpdateKey key) {
- return storage.read(new Quiet<Optional<IJobUpdateDetails>>() {
- @Override
- public Optional<IJobUpdateDetails> apply(Storage.StoreProvider storeProvider) {
- return storeProvider.getJobUpdateStore().fetchJobUpdateDetails(key);
- }
- });
- }
-
- private Set<StoredJobUpdateDetails> getAllUpdateDetails() {
- return storage.read(new Quiet<Set<StoredJobUpdateDetails>>() {
- @Override
- public Set<StoredJobUpdateDetails> apply(Storage.StoreProvider storeProvider) {
- return storeProvider.getJobUpdateStore().fetchAllJobUpdateDetails();
- }
- });
- }
-
- private List<IJobUpdateDetails> queryDetails(final JobUpdateQuery query) {
- return storage.read(new Quiet<List<IJobUpdateDetails>>() {
- @Override
- public List<IJobUpdateDetails> apply(Storage.StoreProvider storeProvider) {
- return storeProvider.getJobUpdateStore().fetchJobUpdateDetails(
- IJobUpdateQuery.build(query));
- }
- });
- }
-
- private List<IJobUpdateSummary> getSummaries(final JobUpdateQuery query) {
- return storage.read(new Quiet<List<IJobUpdateSummary>>() {
- @Override
- public List<IJobUpdateSummary> apply(Storage.StoreProvider storeProvider) {
- return storeProvider.getJobUpdateStore().fetchJobUpdateSummaries(
- IJobUpdateQuery.build(query));
- }
- });
- }
-
- private static ILock makeLock(IJobKey jobKey, String lockToken) {
- return ILock.build(new Lock()
- .setKey(LockKey.job(jobKey.newBuilder()))
- .setToken(lockToken)
- .setTimestampMs(100)
- .setUser("fake user"));
- }
-
- private IJobUpdate saveUpdate(final IJobUpdate update, final Optional<String> lockToken) {
- storage.write(new MutateWork.NoResult.Quiet() {
- @Override
- public void execute(MutableStoreProvider storeProvider) {
- if (lockToken.isPresent()) {
- storeProvider.getLockStore().saveLock(
- makeLock(update.getSummary().getJobKey(), lockToken.get()));
- }
- storeProvider.getJobUpdateStore().saveJobUpdate(update, lockToken);
- storeProvider.getJobUpdateStore().saveJobUpdateEvent(
- update.getSummary().getKey(),
- FIRST_EVENT);
- }
- });
-
- return update;
- }
-
- private IJobUpdate saveUpdateNoEvent(final IJobUpdate update, final Optional<String> lockToken) {
- storage.write(new MutateWork.NoResult.Quiet() {
- @Override
- public void execute(MutableStoreProvider storeProvider) {
- if (lockToken.isPresent()) {
- storeProvider.getLockStore().saveLock(
- makeLock(update.getSummary().getJobKey(), lockToken.get()));
- }
- storeProvider.getJobUpdateStore().saveJobUpdate(update, lockToken);
- }
- });
-
- return update;
- }
-
- private void saveJobEvent(final IJobUpdateEvent event, final IJobUpdateKey key) {
- storage.write(new MutateWork.NoResult.Quiet() {
- @Override
- public void execute(MutableStoreProvider storeProvider) {
- storeProvider.getJobUpdateStore().saveJobUpdateEvent(key, event);
- }
- });
- }
-
- private void saveJobInstanceEvent(final IJobInstanceUpdateEvent event, final IJobUpdateKey key) {
- storage.write(new MutateWork.NoResult.Quiet() {
- @Override
- public void execute(MutableStoreProvider storeProvider) {
- storeProvider.getJobUpdateStore().saveJobInstanceUpdateEvent(key, event);
- }
- });
- }
-
- private void truncateUpdates() {
- storage.write(new MutateWork.NoResult.Quiet() {
- @Override
- public void execute(MutableStoreProvider storeProvider) {
- storeProvider.getJobUpdateStore().deleteAllUpdatesAndEvents();
- }
- });
- }
-
- private Set<IJobUpdateKey> pruneHistory(final int retainCount, final long pruningThresholdMs) {
- return storage.write(new MutateWork.Quiet<Set<IJobUpdateKey>>() {
- @Override
- public Set<IJobUpdateKey> apply(MutableStoreProvider storeProvider) {
- return storeProvider.getJobUpdateStore().pruneHistory(retainCount, pruningThresholdMs);
- }
- });
- }
-
- private void removeLock(final IJobUpdate update, final String lockToken) {
- storage.write(new MutateWork.NoResult.Quiet() {
- @Override
- public void execute(MutableStoreProvider storeProvider) {
- storeProvider.getLockStore().removeLock(
- makeLock(update.getSummary().getJobKey(), lockToken).getKey());
- }
- });
- }
-
- private IJobUpdate populateExpected(IJobUpdate update) {
- return populateExpected(update, ROLLING_FORWARD, CREATED_MS, CREATED_MS);
- }
-
- private IJobUpdate populateExpected(
- IJobUpdate update,
- JobUpdateStatus status,
- long createdMs,
- long lastMs) {
-
- JobUpdateState state = new JobUpdateState()
- .setCreatedTimestampMs(createdMs)
- .setLastModifiedTimestampMs(lastMs)
- .setStatus(status);
- JobUpdate builder = update.newBuilder();
- builder.getSummary().setState(state);
- return IJobUpdate.build(builder);
- }
-
- private static IJobUpdateEvent makeJobUpdateEvent(JobUpdateStatus status, long timestampMs) {
- return IJobUpdateEvent.build(
- new JobUpdateEvent(status, timestampMs)
- .setUser("user")
- .setMessage("message"));
- }
-
- private IJobInstanceUpdateEvent makeJobInstanceEvent(
- int instanceId,
- long timestampMs,
- JobUpdateAction action) {
-
- return IJobInstanceUpdateEvent.build(
- new JobInstanceUpdateEvent(instanceId, timestampMs, action));
- }
-
- private IJobUpdateDetails makeJobDetails(IJobUpdate update) {
- return updateJobDetails(
- update,
- ImmutableList.of(FIRST_EVENT),
- ImmutableList.<IJobInstanceUpdateEvent>of());
- }
-
- private IJobUpdateDetails updateJobDetails(IJobUpdate update, IJobUpdateEvent event) {
- return updateJobDetails(
- update,
- ImmutableList.of(event),
- ImmutableList.<IJobInstanceUpdateEvent>of());
- }
-
- private IJobUpdateDetails updateJobDetails(
- IJobUpdate update,
- List<IJobUpdateEvent> jobEvents,
- List<IJobInstanceUpdateEvent> instanceEvents) {
-
- return IJobUpdateDetails.build(new JobUpdateDetails()
- .setUpdate(update.newBuilder())
- .setUpdateEvents(IJobUpdateEvent.toBuildersList(jobEvents))
- .setInstanceEvents(IJobInstanceUpdateEvent.toBuildersList(instanceEvents)));
- }
-
- private IJobUpdateSummary makeSummary(IJobUpdateKey key, String user) {
- return IJobUpdateSummary.build(new JobUpdateSummary()
- .setKey(key.newBuilder())
- .setUpdateId(key.getId())
- .setJobKey(key.getJob().newBuilder())
- .setUser(user));
- }
-
- private IJobUpdateSummary saveSummary(
- IJobUpdateKey key,
- Long modifiedTimestampMs,
- JobUpdateStatus status,
- String user,
- Optional<String> lockToken) {
-
- IJobUpdateSummary summary = IJobUpdateSummary.build(new JobUpdateSummary()
- .setKey(key.newBuilder())
- .setUpdateId(key.getId())
- .setJobKey(key.getJob().newBuilder())
- .setUser(user));
-
- IJobUpdate update = makeJobUpdate(summary);
- saveUpdate(update, lockToken);
- saveJobEvent(makeJobUpdateEvent(status, modifiedTimestampMs), key);
- return populateExpected(update, status, CREATED_MS, modifiedTimestampMs).getSummary();
- }
-
- private IJobUpdate makeJobUpdate(IJobUpdateSummary summary) {
- return IJobUpdate.build(makeJobUpdate().newBuilder().setSummary(summary.newBuilder()));
- }
-
- private IJobUpdate makeJobUpdate(IJobUpdateKey key) {
- return IJobUpdate.build(makeJobUpdate().newBuilder()
- .setSummary(makeSummary(key, "user").newBuilder()));
- }
-
- private IJobUpdate makeJobUpdate() {
- return IJobUpdate.build(new JobUpdate()
- .setInstructions(makeJobUpdateInstructions().newBuilder()));
- }
-
- private IJobUpdateInstructions makeJobUpdateInstructions() {
- return IJobUpdateInstructions.build(new JobUpdateInstructions()
- .setDesiredState(new InstanceTaskConfig()
- .setTask(makeTaskConfig())
- .setInstances(ImmutableSet.of(new Range(0, 7), new Range(8, 9))))
- .setInitialState(ImmutableSet.of(
- new InstanceTaskConfig()
- .setInstances(ImmutableSet.of(new Range(0, 1), new Range(2, 3)))
- .setTask(makeTaskConfig()),
- new InstanceTaskConfig()
- .setInstances(ImmutableSet.of(new Range(4, 5), new Range(6, 7)))
- .setTask(makeTaskConfig())))
- .setSettings(new JobUpdateSettings()
- .setBlockIfNoPulsesAfterMs(500)
- .setUpdateOnlyTheseInstances(ImmutableSet.of(new Range(0, 0), new Range(3, 5)))));
- }
-
- private TaskConfig makeTaskConfig() {
- return new TaskConfig()
- .setJobName(JOB.getName())
- .setEnvironment(JOB.getEnvironment())
- .setOwner(new Identity(JOB.getRole(), "user"))
- .setJob(new JobKey("role", "env", "job"))
- .setIsService(true)
- .setConstraints(ImmutableSet.of(
- new Constraint(
- "name",
- TaskConstraint.value(new ValueConstraint(true, ImmutableSet.of("x86"))))))
- .setRequestedPorts(ImmutableSet.of("http"))
- .setTaskLinks(ImmutableMap.of("key", "url"))
- .setContactEmail("foo@bar.com")
- .setExecutorConfig(new ExecutorConfig("name", "data"))
- .setMetadata(ImmutableSet.of(new Metadata("name", "value")));
- }
-}
http://git-wip-us.apache.org/repos/asf/aurora/blob/449a835e/src/test/java/org/apache/aurora/scheduler/storage/db/DbJobUpdateStoreTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/storage/db/DbJobUpdateStoreTest.java b/src/test/java/org/apache/aurora/scheduler/storage/db/DbJobUpdateStoreTest.java
new file mode 100644
index 0000000..219676f
--- /dev/null
+++ b/src/test/java/org/apache/aurora/scheduler/storage/db/DbJobUpdateStoreTest.java
@@ -0,0 +1,1061 @@
+/**
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.aurora.scheduler.storage.db;
+
+import java.util.List;
+import java.util.Set;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+
+import org.apache.aurora.gen.InstanceTaskConfig;
+import org.apache.aurora.gen.JobInstanceUpdateEvent;
+import org.apache.aurora.gen.JobUpdate;
+import org.apache.aurora.gen.JobUpdateAction;
+import org.apache.aurora.gen.JobUpdateDetails;
+import org.apache.aurora.gen.JobUpdateEvent;
+import org.apache.aurora.gen.JobUpdateInstructions;
+import org.apache.aurora.gen.JobUpdateKey;
+import org.apache.aurora.gen.JobUpdateQuery;
+import org.apache.aurora.gen.JobUpdateSettings;
+import org.apache.aurora.gen.JobUpdateState;
+import org.apache.aurora.gen.JobUpdateStatus;
+import org.apache.aurora.gen.JobUpdateSummary;
+import org.apache.aurora.gen.Lock;
+import org.apache.aurora.gen.LockKey;
+import org.apache.aurora.gen.Range;
+import org.apache.aurora.gen.TaskConfig;
+import org.apache.aurora.gen.storage.StoredJobUpdateDetails;
+import org.apache.aurora.scheduler.base.JobKeys;
+import org.apache.aurora.scheduler.base.TaskTestUtil;
+import org.apache.aurora.scheduler.storage.Storage;
+import org.apache.aurora.scheduler.storage.Storage.MutableStoreProvider;
+import org.apache.aurora.scheduler.storage.Storage.MutateWork;
+import org.apache.aurora.scheduler.storage.Storage.StorageException;
+import org.apache.aurora.scheduler.storage.Storage.Work.Quiet;
+import org.apache.aurora.scheduler.storage.entities.IJobInstanceUpdateEvent;
+import org.apache.aurora.scheduler.storage.entities.IJobKey;
+import org.apache.aurora.scheduler.storage.entities.IJobUpdate;
+import org.apache.aurora.scheduler.storage.entities.IJobUpdateDetails;
+import org.apache.aurora.scheduler.storage.entities.IJobUpdateEvent;
+import org.apache.aurora.scheduler.storage.entities.IJobUpdateInstructions;
+import org.apache.aurora.scheduler.storage.entities.IJobUpdateKey;
+import org.apache.aurora.scheduler.storage.entities.IJobUpdateQuery;
+import org.apache.aurora.scheduler.storage.entities.IJobUpdateSummary;
+import org.apache.aurora.scheduler.storage.entities.ILock;
+import org.apache.aurora.scheduler.storage.testing.StorageEntityUtil;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.apache.aurora.gen.JobUpdateAction.INSTANCE_ROLLBACK_FAILED;
+import static org.apache.aurora.gen.JobUpdateAction.INSTANCE_ROLLED_BACK;
+import static org.apache.aurora.gen.JobUpdateAction.INSTANCE_ROLLING_BACK;
+import static org.apache.aurora.gen.JobUpdateAction.INSTANCE_UPDATED;
+import static org.apache.aurora.gen.JobUpdateAction.INSTANCE_UPDATING;
+import static org.apache.aurora.gen.JobUpdateStatus.ABORTED;
+import static org.apache.aurora.gen.JobUpdateStatus.ERROR;
+import static org.apache.aurora.gen.JobUpdateStatus.FAILED;
+import static org.apache.aurora.gen.JobUpdateStatus.ROLLED_BACK;
+import static org.apache.aurora.gen.JobUpdateStatus.ROLLING_BACK;
+import static org.apache.aurora.gen.JobUpdateStatus.ROLLING_FORWARD;
+import static org.apache.aurora.gen.JobUpdateStatus.ROLL_BACK_PAUSED;
+import static org.apache.aurora.gen.JobUpdateStatus.ROLL_FORWARD_PAUSED;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+public class DbJobUpdateStoreTest {
+
+ private static final IJobKey JOB = JobKeys.from("testRole", "testEnv", "job");
+ private static final IJobUpdateKey UPDATE1 =
+ IJobUpdateKey.build(new JobUpdateKey(JOB.newBuilder(), "update1"));
+ private static final IJobUpdateKey UPDATE2 = IJobUpdateKey.build(
+ new JobUpdateKey(JobKeys.from("testRole", "testEnv", "job2").newBuilder(), "update2"));
+ private static final long CREATED_MS = 111L;
+ private static final IJobUpdateEvent FIRST_EVENT =
+ makeJobUpdateEvent(ROLLING_FORWARD, CREATED_MS);
+
+ private Storage storage;
+
+ @Before
+ public void setUp() throws Exception {
+ storage = DbUtil.createStorage();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ truncateUpdates();
+ }
+
+ @Test
+ public void testSaveJobUpdates() {
+ IJobUpdateKey updateId1 = makeKey(JobKeys.from("role", "env", "name1"), "u1");
+ IJobUpdateKey updateId2 = makeKey(JobKeys.from("role", "env", "name2"), "u2");
+
+ IJobUpdate update1 = makeJobUpdate(updateId1);
+ IJobUpdate update2 = makeJobUpdate(updateId2);
+
+ assertEquals(Optional.<IJobUpdate>absent(), getUpdate(updateId1));
+ assertEquals(Optional.<IJobUpdate>absent(), getUpdate(updateId2));
+
+ StorageEntityUtil.assertFullyPopulated(
+ update1,
+ StorageEntityUtil.getField(JobUpdateSummary.class, "state"),
+ StorageEntityUtil.getField(IJobUpdateSummary.class, "state"),
+ StorageEntityUtil.getField(Range.class, "first"),
+ StorageEntityUtil.getField(Range.class, "last"));
+ saveUpdate(update1, Optional.of("lock1"));
+ assertUpdate(update1);
+
+ saveUpdate(update2, Optional.<String>absent());
+ assertUpdate(update2);
+
+ // Colliding update IDs should be forbidden.
+ IJobUpdate update3 =
+ makeJobUpdate(makeKey(JobKeys.from("role", "env", "name3"), updateId2.getId()));
+ try {
+ saveUpdate(update3, Optional.<String>absent());
+ fail("Update ID collision should not be allowed");
+ } catch (StorageException e) {
+ // Expected.
+ }
+ }
+
+ @Test
+ public void testSaveNullInitialState() {
+ JobUpdate builder = makeJobUpdate(makeKey("u1")).newBuilder();
+ builder.getInstructions().unsetInitialState();
+
+ // Save with null initial state instances.
+ saveUpdate(IJobUpdate.build(builder), Optional.of("lock"));
+
+ builder.getInstructions().setInitialState(ImmutableSet.<InstanceTaskConfig>of());
+ assertUpdate(IJobUpdate.build(builder));
+ }
+
+ @Test
+ public void testSaveNullDesiredState() {
+ JobUpdate builder = makeJobUpdate(makeKey("u1")).newBuilder();
+ builder.getInstructions().unsetDesiredState();
+
+ // Save with null desired state instances.
+ saveUpdate(IJobUpdate.build(builder), Optional.of("lock"));
+
+ assertUpdate(IJobUpdate.build(builder));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testSaveBothInitialAndDesiredMissingThrows() {
+ JobUpdate builder = makeJobUpdate(makeKey("u1")).newBuilder();
+ builder.getInstructions().unsetInitialState();
+ builder.getInstructions().unsetDesiredState();
+
+ saveUpdate(IJobUpdate.build(builder), Optional.of("lock"));
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testSaveNullInitialStateTaskThrows() {
+ JobUpdate builder = makeJobUpdate(makeKey("u1")).newBuilder();
+ builder.getInstructions().getInitialState().add(
+ new InstanceTaskConfig(null, ImmutableSet.<Range>of()));
+
+ saveUpdate(IJobUpdate.build(builder), Optional.of("lock"));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testSaveEmptyInitialStateRangesThrows() {
+ JobUpdate builder = makeJobUpdate(makeKey("u1")).newBuilder();
+ builder.getInstructions().getInitialState().add(
+ new InstanceTaskConfig(new TaskConfig(), ImmutableSet.<Range>of()));
+
+ saveUpdate(IJobUpdate.build(builder), Optional.of("lock"));
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testSaveNullDesiredStateTaskThrows() {
+ JobUpdate builder = makeJobUpdate(makeKey("u1")).newBuilder();
+ builder.getInstructions().getDesiredState().setTask(null);
+
+ saveUpdate(IJobUpdate.build(builder), Optional.of("lock"));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testSaveEmptyDesiredStateRangesThrows() {
+ JobUpdate builder = makeJobUpdate(makeKey("u1")).newBuilder();
+ builder.getInstructions().getDesiredState().setInstances(ImmutableSet.<Range>of());
+
+ saveUpdate(IJobUpdate.build(builder), Optional.of("lock"));
+ }
+
+ @Test
+ public void testSaveJobUpdateEmptyInstanceOverrides() {
+ IJobUpdateKey updateId = makeKey("u1");
+
+ IJobUpdate update = makeJobUpdate(updateId);
+ JobUpdate builder = update.newBuilder();
+ builder.getInstructions().getSettings().setUpdateOnlyTheseInstances(ImmutableSet.<Range>of());
+
+ IJobUpdate expected = IJobUpdate.build(builder);
+
+ // Save with empty overrides.
+ saveUpdate(expected, Optional.of("lock"));
+ assertUpdate(expected);
+ }
+
+ @Test
+ public void testSaveJobUpdateNullInstanceOverrides() {
+ IJobUpdateKey updateId = makeKey("u1");
+
+ IJobUpdate update = makeJobUpdate(updateId);
+ JobUpdate builder = update.newBuilder();
+ builder.getInstructions().getSettings().setUpdateOnlyTheseInstances(ImmutableSet.<Range>of());
+
+ IJobUpdate expected = IJobUpdate.build(builder);
+
+ // Save with null overrides.
+ builder.getInstructions().getSettings().setUpdateOnlyTheseInstances(null);
+ saveUpdate(IJobUpdate.build(builder), Optional.of("lock"));
+ assertUpdate(expected);
+ }
+
+ @Test(expected = StorageException.class)
+ public void testSaveJobUpdateTwiceThrows() {
+ IJobUpdateKey updateId = makeKey("u1");
+ IJobUpdate update = makeJobUpdate(updateId);
+
+ saveUpdate(update, Optional.of("lock1"));
+ saveUpdate(update, Optional.of("lock2"));
+ }
+
+ @Test
+ public void testSaveJobEvents() {
+ IJobUpdateKey updateId = makeKey("u3");
+ IJobUpdate update = makeJobUpdate(updateId);
+ IJobUpdateEvent event1 = makeJobUpdateEvent(ROLLING_FORWARD, 124L);
+ IJobUpdateEvent event2 = makeJobUpdateEvent(ROLL_FORWARD_PAUSED, 125L);
+
+ saveUpdate(update, Optional.of("lock1"));
+ assertUpdate(update);
+ assertEquals(ImmutableList.of(FIRST_EVENT), getUpdateDetails(updateId).get().getUpdateEvents());
+
+ saveJobEvent(event1, updateId);
+ assertEquals(
+ populateExpected(update, ROLLING_FORWARD, CREATED_MS, 124L),
+ getUpdateDetails(updateId).get().getUpdate());
+ assertEquals(event1, getUpdateDetails(updateId).get().getUpdateEvents().get(1));
+
+ saveJobEvent(event2, updateId);
+ assertEquals(
+ populateExpected(update, ROLL_FORWARD_PAUSED, CREATED_MS, 125L),
+ getUpdateDetails(updateId).get().getUpdate());
+ assertEquals(event1, getUpdateDetails(updateId).get().getUpdateEvents().get(1));
+ assertEquals(event2, getUpdateDetails(updateId).get().getUpdateEvents().get(2));
+ }
+
+ @Test
+ public void testSaveInstanceEvents() {
+ IJobUpdateKey updateId = makeKey("u3");
+ IJobUpdate update = makeJobUpdate(updateId);
+ IJobInstanceUpdateEvent event1 = makeJobInstanceEvent(0, 125L, INSTANCE_UPDATED);
+ IJobInstanceUpdateEvent event2 = makeJobInstanceEvent(1, 126L, INSTANCE_ROLLING_BACK);
+
+ saveUpdate(update, Optional.of("lock"));
+ assertUpdate(update);
+ assertEquals(0, getUpdateDetails(updateId).get().getInstanceEvents().size());
+
+ saveJobInstanceEvent(event1, updateId);
+ assertEquals(
+ populateExpected(update, ROLLING_FORWARD, CREATED_MS, 125L),
+ getUpdateDetails(updateId).get().getUpdate());
+ assertEquals(
+ event1,
+ Iterables.getOnlyElement(getUpdateDetails(updateId).get().getInstanceEvents()));
+
+ saveJobInstanceEvent(event2, updateId);
+ assertEquals(
+ populateExpected(update, ROLLING_FORWARD, CREATED_MS, 126L),
+ getUpdateDetails(updateId).get().getUpdate());
+ assertEquals(event1, getUpdateDetails(updateId).get().getInstanceEvents().get(0));
+ assertEquals(event2, getUpdateDetails(updateId).get().getInstanceEvents().get(1));
+ }
+
+ @Test(expected = StorageException.class)
+ public void testSaveJobEventWithoutUpdateFails() {
+ saveJobEvent(makeJobUpdateEvent(ROLLING_FORWARD, 123L), makeKey("u2"));
+ }
+
+ @Test(expected = StorageException.class)
+ public void testSaveInstanceEventWithoutUpdateFails() {
+ saveJobInstanceEvent(makeJobInstanceEvent(0, 125L, INSTANCE_UPDATED), makeKey("u1"));
+ }
+
+ @Test
+ public void testSaveJobUpdateStateIgnored() {
+ IJobUpdateKey updateId = makeKey("u1");
+ IJobUpdate update = populateExpected(makeJobUpdate(updateId), ABORTED, 567L, 567L);
+ saveUpdate(update, Optional.of("lock1"));
+
+ // Assert state fields were ignored.
+ assertUpdate(update);
+ }
+
+ @Test
+ public void testSaveJobUpdateWithoutEventFailsSelect() {
+ final IJobUpdateKey updateId = makeKey("u3");
+ storage.write(new MutateWork.NoResult.Quiet() {
+ @Override
+ public void execute(MutableStoreProvider storeProvider) {
+ IJobUpdate update = makeJobUpdate(updateId);
+ storeProvider.getLockStore().saveLock(makeLock(update.getSummary().getJobKey(), "lock1"));
+ storeProvider.getJobUpdateStore().saveJobUpdate(update, Optional.of("lock1"));
+ }
+ });
+ assertEquals(Optional.<IJobUpdateDetails>absent(), getUpdateDetails(updateId));
+ }
+
+ @Test
+ public void testMultipleJobDetails() {
+ IJobUpdateKey updateId1 = makeKey(JobKeys.from("role", "env", "name1"), "u1");
+ IJobUpdateKey updateId2 = makeKey(JobKeys.from("role", "env", "name2"), "u2");
+ IJobUpdateDetails details1 = makeJobDetails(makeJobUpdate(updateId1));
+ IJobUpdateDetails details2 = makeJobDetails(makeJobUpdate(updateId2));
+
+ assertEquals(ImmutableList.<IJobInstanceUpdateEvent>of(), getInstanceEvents(updateId2, 3));
+
+ saveUpdate(details1.getUpdate(), Optional.of("lock1"));
+ saveUpdate(details2.getUpdate(), Optional.of("lock2"));
+
+ details1 = updateJobDetails(populateExpected(details1.getUpdate()), FIRST_EVENT);
+ details2 = updateJobDetails(populateExpected(details2.getUpdate()), FIRST_EVENT);
+ assertEquals(Optional.of(details1), getUpdateDetails(updateId1));
+ assertEquals(Optional.of(details2), getUpdateDetails(updateId2));
+
+ IJobUpdateEvent jEvent11 = makeJobUpdateEvent(ROLLING_FORWARD, 456L);
+ IJobUpdateEvent jEvent12 = makeJobUpdateEvent(ERROR, 457L);
+ IJobInstanceUpdateEvent iEvent11 = makeJobInstanceEvent(1, 451L, INSTANCE_UPDATED);
+ IJobInstanceUpdateEvent iEvent12 = makeJobInstanceEvent(2, 452L, INSTANCE_UPDATING);
+
+ IJobUpdateEvent jEvent21 = makeJobUpdateEvent(ROLL_FORWARD_PAUSED, 567L);
+ IJobUpdateEvent jEvent22 = makeJobUpdateEvent(ABORTED, 568L);
+ IJobInstanceUpdateEvent iEvent21 = makeJobInstanceEvent(3, 561L, INSTANCE_UPDATING);
+ IJobInstanceUpdateEvent iEvent22 = makeJobInstanceEvent(3, 562L, INSTANCE_UPDATED);
+
+ saveJobEvent(jEvent11, updateId1);
+ saveJobEvent(jEvent12, updateId1);
+ saveJobInstanceEvent(iEvent11, updateId1);
+ saveJobInstanceEvent(iEvent12, updateId1);
+
+ saveJobEvent(jEvent21, updateId2);
+ saveJobEvent(jEvent22, updateId2);
+ assertEquals(ImmutableList.<IJobInstanceUpdateEvent>of(), getInstanceEvents(updateId2, 3));
+ saveJobInstanceEvent(iEvent21, updateId2);
+
+ assertEquals(ImmutableList.of(iEvent21), getInstanceEvents(updateId2, 3));
+ saveJobInstanceEvent(iEvent22, updateId2);
+ assertEquals(ImmutableList.of(iEvent21, iEvent22), getInstanceEvents(updateId2, 3));
+
+ details1 = updateJobDetails(
+ populateExpected(details1.getUpdate(), ERROR, CREATED_MS, 457L),
+ ImmutableList.of(FIRST_EVENT, jEvent11, jEvent12), ImmutableList.of(iEvent11, iEvent12));
+
+ details2 = updateJobDetails(
+ populateExpected(details2.getUpdate(), ABORTED, CREATED_MS, 568L),
+ ImmutableList.of(FIRST_EVENT, jEvent21, jEvent22), ImmutableList.of(iEvent21, iEvent22));
+
+ assertEquals(Optional.of(details1), getUpdateDetails(updateId1));
+ assertEquals(Optional.of(details2), getUpdateDetails(updateId2));
+
+ assertEquals(
+ ImmutableSet.of(
+ new StoredJobUpdateDetails(details1.newBuilder(), "lock1"),
+ new StoredJobUpdateDetails(details2.newBuilder(), "lock2")),
+ getAllUpdateDetails());
+
+ assertEquals(
+ ImmutableList.of(getUpdateDetails(updateId2).get(), getUpdateDetails(updateId1).get()),
+ queryDetails(new JobUpdateQuery().setRole("role")));
+ }
+
+ @Test
+ public void testTruncateJobUpdates() {
+ IJobUpdateKey updateId = makeKey("u5");
+ IJobUpdate update = makeJobUpdate(updateId);
+ IJobInstanceUpdateEvent instanceEvent = IJobInstanceUpdateEvent.build(
+ new JobInstanceUpdateEvent(0, 125L, INSTANCE_ROLLBACK_FAILED));
+
+ saveUpdate(update, Optional.of("lock"));
+ saveJobEvent(makeJobUpdateEvent(ROLLING_FORWARD, 123L), updateId);
+ saveJobInstanceEvent(instanceEvent, updateId);
+ assertEquals(
+ populateExpected(update, ROLLING_FORWARD, CREATED_MS, 125L),
+ getUpdate(updateId).get());
+ assertEquals(2, getUpdateDetails(updateId).get().getUpdateEvents().size());
+ assertEquals(1, getUpdateDetails(updateId).get().getInstanceEvents().size());
+
+ truncateUpdates();
+ assertEquals(Optional.<IJobUpdateDetails>absent(), getUpdateDetails(updateId));
+ }
+
+ @Test
+ public void testPruneHistory() {
+ IJobUpdateKey updateId1 = makeKey("u11");
+ IJobUpdateKey updateId2 = makeKey("u12");
+ IJobUpdateKey updateId3 = makeKey("u13");
+ IJobUpdateKey updateId4 = makeKey("u14");
+ IJobKey job2 = JobKeys.from("testRole2", "testEnv2", "job2");
+ IJobUpdateKey updateId5 = makeKey(job2, "u15");
+ IJobUpdateKey updateId6 = makeKey(job2, "u16");
+ IJobUpdateKey updateId7 = makeKey(job2, "u17");
+
+ IJobUpdate update1 = makeJobUpdate(updateId1);
+ IJobUpdate update2 = makeJobUpdate(updateId2);
+ IJobUpdate update3 = makeJobUpdate(updateId3);
+ IJobUpdate update4 = makeJobUpdate(updateId4);
+ IJobUpdate update5 = makeJobUpdate(updateId5);
+ IJobUpdate update6 = makeJobUpdate(updateId6);
+ IJobUpdate update7 = makeJobUpdate(updateId7);
+
+ IJobUpdateEvent updateEvent1 = makeJobUpdateEvent(ROLLING_BACK, 123L);
+ IJobUpdateEvent updateEvent2 = makeJobUpdateEvent(ABORTED, 124L);
+ IJobUpdateEvent updateEvent3 = makeJobUpdateEvent(ROLLED_BACK, 125L);
+ IJobUpdateEvent updateEvent4 = makeJobUpdateEvent(FAILED, 126L);
+ IJobUpdateEvent updateEvent5 = makeJobUpdateEvent(ERROR, 123L);
+ IJobUpdateEvent updateEvent6 = makeJobUpdateEvent(FAILED, 125L);
+ IJobUpdateEvent updateEvent7 = makeJobUpdateEvent(ROLLING_FORWARD, 126L);
+
+ update1 = populateExpected(
+ saveUpdateNoEvent(update1, Optional.of("lock1")), ROLLING_BACK, 123L, 123L);
+ update2 = populateExpected(
+ saveUpdateNoEvent(update2, Optional.<String>absent()), ABORTED, 124L, 124L);
+ update3 = populateExpected(
+ saveUpdateNoEvent(update3, Optional.<String>absent()), ROLLED_BACK, 125L, 125L);
+ update4 = populateExpected(
+ saveUpdateNoEvent(update4, Optional.<String>absent()), FAILED, 126L, 126L);
+ update5 = populateExpected(
+ saveUpdateNoEvent(update5, Optional.<String>absent()), ERROR, 123L, 123L);
+ update6 = populateExpected(
+ saveUpdateNoEvent(update6, Optional.<String>absent()), FAILED, 125L, 125L);
+ update7 = populateExpected(
+ saveUpdateNoEvent(update7, Optional.of("lock2")), ROLLING_FORWARD, 126L, 126L);
+
+ saveJobEvent(updateEvent1, updateId1);
+ saveJobEvent(updateEvent2, updateId2);
+ saveJobEvent(updateEvent3, updateId3);
+ saveJobEvent(updateEvent4, updateId4);
+ saveJobEvent(updateEvent5, updateId5);
+ saveJobEvent(updateEvent6, updateId6);
+ saveJobEvent(updateEvent7, updateId7);
+
+ assertEquals(update1, getUpdate(updateId1).get());
+ assertEquals(update2, getUpdate(updateId2).get());
+ assertEquals(update3, getUpdate(updateId3).get());
+ assertEquals(update4, getUpdate(updateId4).get());
+ assertEquals(update5, getUpdate(updateId5).get());
+ assertEquals(update6, getUpdate(updateId6).get());
+ assertEquals(update7, getUpdate(updateId7).get());
+
+ long pruningThreshold = 120L;
+
+ // No updates pruned.
+ assertEquals(ImmutableSet.<IJobUpdateKey>of(), pruneHistory(3, pruningThreshold));
+ assertEquals(Optional.of(update7), getUpdate(updateId7)); // active update
+ assertEquals(Optional.of(update6), getUpdate(updateId6));
+ assertEquals(Optional.of(update5), getUpdate(updateId5));
+
+ assertEquals(Optional.of(update4), getUpdate(updateId4));
+ assertEquals(Optional.of(update3), getUpdate(updateId3));
+ assertEquals(Optional.of(update2), getUpdate(updateId2));
+ assertEquals(Optional.of(update1), getUpdate(updateId1)); // active update
+
+ assertEquals(ImmutableSet.of(updateId2), pruneHistory(2, pruningThreshold));
+ // No updates pruned.
+ assertEquals(Optional.of(update7), getUpdate(updateId7)); // active update
+ assertEquals(Optional.of(update6), getUpdate(updateId6));
+ assertEquals(Optional.of(update5), getUpdate(updateId5));
+
+ // 1 update pruned.
+ assertEquals(Optional.of(update4), getUpdate(updateId4));
+ assertEquals(Optional.of(update3), getUpdate(updateId3));
+ assertEquals(Optional.<IJobUpdate>absent(), getUpdate(updateId2));
+ assertEquals(Optional.of(update1), getUpdate(updateId1)); // active update
+
+ assertEquals(ImmutableSet.of(updateId5, updateId3), pruneHistory(1, pruningThreshold));
+ // 1 update pruned.
+ assertEquals(Optional.of(update7), getUpdate(updateId7)); // active update
+ assertEquals(Optional.of(update6), getUpdate(updateId6));
+ assertEquals(Optional.<IJobUpdate>absent(), getUpdate(updateId5));
+
+ // 2 updates pruned.
+ assertEquals(Optional.of(update4), getUpdate(updateId4));
+ assertEquals(Optional.<IJobUpdate>absent(), getUpdate(updateId3));
+ assertEquals(Optional.of(update1), getUpdate(updateId1)); // active update
+
+ // The oldest update is pruned.
+ assertEquals(ImmutableSet.of(updateId6), pruneHistory(1, 126L));
+ assertEquals(Optional.of(update7), getUpdate(updateId7)); // active update
+ assertEquals(Optional.<IJobUpdate>absent(), getUpdate(updateId6));
+
+ assertEquals(Optional.of(update4), getUpdate(updateId4));
+ assertEquals(Optional.of(update1), getUpdate(updateId1)); // active update
+
+ // Nothing survives the 0 per job count.
+ assertEquals(ImmutableSet.of(updateId4), pruneHistory(0, pruningThreshold));
+ assertEquals(Optional.of(update7), getUpdate(updateId7)); // active update
+
+ assertEquals(Optional.<IJobUpdate>absent(), getUpdate(updateId4));
+ assertEquals(Optional.of(update1), getUpdate(updateId1)); // active update
+ }
+
+ @Test(expected = StorageException.class)
+ public void testSaveUpdateWithoutLock() {
+ final IJobUpdate update = makeJobUpdate(makeKey("updateId"));
+ storage.write(new MutateWork.NoResult.Quiet() {
+ @Override
+ public void execute(MutableStoreProvider storeProvider) {
+ storeProvider.getJobUpdateStore().saveJobUpdate(update, Optional.of("lock"));
+ }
+ });
+ }
+
+ @Test(expected = StorageException.class)
+ public void testSaveTwoUpdatesForOneJob() {
+ final IJobUpdate update = makeJobUpdate(makeKey("updateId"));
+ saveUpdate(update, Optional.of("lock1"));
+ saveUpdate(update, Optional.of("lock2"));
+ }
+
+ @Test(expected = StorageException.class)
+ public void testSaveTwoUpdatesSameJobKey() {
+ final IJobUpdate update1 = makeJobUpdate(makeKey("update1"));
+ final IJobUpdate update2 = makeJobUpdate(makeKey("update2"));
+ saveUpdate(update1, Optional.of("lock1"));
+ saveUpdate(update2, Optional.of("lock1"));
+ }
+
+ @Test
+ public void testLockCleared() {
+ final IJobUpdate update = makeJobUpdate(makeKey("update1"));
+ saveUpdate(update, Optional.of("lock1"));
+
+ removeLock(update, "lock1");
+
+ assertEquals(
+ Optional.of(updateJobDetails(populateExpected(update), FIRST_EVENT)),
+ getUpdateDetails(makeKey("update1")));
+ assertEquals(
+ ImmutableSet.of(
+ new StoredJobUpdateDetails(
+ updateJobDetails(populateExpected(update), FIRST_EVENT).newBuilder(),
+ null)),
+ getAllUpdateDetails());
+
+ assertEquals(
+ ImmutableList.of(populateExpected(update).getSummary()),
+ getSummaries(new JobUpdateQuery().setKey(UPDATE1.newBuilder())));
+
+ // If the lock has been released for this job, we can start another update.
+ saveUpdate(makeJobUpdate(makeKey("update2")), Optional.of("lock2"));
+ }
+
+ private static final Optional<String> NO_TOKEN = Optional.absent();
+
+ @Test
+ public void testGetLockToken() {
+ storage.write(new MutateWork.NoResult.Quiet() {
+ @Override
+ public void execute(MutableStoreProvider storeProvider) {
+ final IJobUpdate update1 = makeJobUpdate(UPDATE1);
+ final IJobUpdate update2 = makeJobUpdate(UPDATE2);
+ saveUpdate(update1, Optional.of("lock1"));
+ assertEquals(
+ Optional.of("lock1"),
+ storeProvider.getJobUpdateStore().getLockToken(UPDATE1));
+ assertEquals(NO_TOKEN, storeProvider.getJobUpdateStore().getLockToken(UPDATE2));
+
+ saveUpdate(update2, Optional.of("lock2"));
+ assertEquals(
+ Optional.of("lock1"),
+ storeProvider.getJobUpdateStore().getLockToken(UPDATE1));
+ assertEquals(
+ Optional.of("lock2"),
+ storeProvider.getJobUpdateStore().getLockToken(UPDATE2));
+
+ storeProvider.getLockStore().removeLock(
+ makeLock(update1.getSummary().getJobKey(), "lock1").getKey());
+ assertEquals(NO_TOKEN, storeProvider.getJobUpdateStore().getLockToken(UPDATE1));
+ assertEquals(
+ Optional.of("lock2"),
+ storeProvider.getJobUpdateStore().getLockToken(UPDATE2));
+
+ storeProvider.getLockStore().removeLock(
+ makeLock(update2.getSummary().getJobKey(), "lock2").getKey());
+ assertEquals(NO_TOKEN, storeProvider.getJobUpdateStore().getLockToken(UPDATE1));
+ assertEquals(NO_TOKEN, storeProvider.getJobUpdateStore().getLockToken(UPDATE2));
+ }
+ });
+ }
+
+ @Test
+ public void testGetSummaries() {
+ String role1 = "role1";
+ IJobKey job1 = JobKeys.from(role1, "env", "name1");
+ IJobKey job2 = JobKeys.from(role1, "env", "name2");
+ IJobKey job3 = JobKeys.from(role1, "env", "name3");
+ IJobKey job4 = JobKeys.from(role1, "env", "name4");
+ IJobKey job5 = JobKeys.from("role", "env", "name5");
+ IJobUpdateSummary s1 =
+ saveSummary(makeKey(job1, "u1"), 1230L, ROLLED_BACK, "user", Optional.of("lock1"));
+ IJobUpdateSummary s2 =
+ saveSummary(makeKey(job2, "u2"), 1231L, ABORTED, "user", Optional.of("lock2"));
+ IJobUpdateSummary s3 =
+ saveSummary(makeKey(job3, "u3"), 1239L, ERROR, "user2", Optional.of("lock3"));
+ IJobUpdateSummary s4 =
+ saveSummary(makeKey(job4, "u4"), 1234L, ROLL_BACK_PAUSED, "user3", Optional.of("lock4"));
+ IJobUpdateSummary s5 =
+ saveSummary(makeKey(job5, "u5"), 1235L, ROLLING_FORWARD, "user4", Optional.of("lock5"));
+
+ // Test empty query returns all.
+ assertEquals(ImmutableList.of(s3, s5, s4, s2, s1), getSummaries(new JobUpdateQuery()));
+
+ // Test query by updateId.
+ assertEquals(
+ ImmutableList.of(s1),
+ getSummaries(new JobUpdateQuery().setKey(new JobUpdateKey(job1.newBuilder(), "u1"))));
+
+ // Test query by role.
+ assertEquals(
+ ImmutableList.of(s3, s4, s2, s1),
+ getSummaries(new JobUpdateQuery().setRole(role1)));
+
+ // Test query by job key.
+ assertEquals(
+ ImmutableList.of(s5),
+ getSummaries(new JobUpdateQuery().setJobKey(job5.newBuilder())));
+
+ // Test querying by update key.
+ assertEquals(
+ ImmutableList.of(s5),
+ getSummaries(
+ new JobUpdateQuery().setKey(new JobUpdateKey(job5.newBuilder(), s5.getUpdateId()))));
+
+ // Test querying by incorrect update keys.
+ assertEquals(
+ ImmutableList.<IJobUpdateSummary>of(),
+ getSummaries(
+ new JobUpdateQuery().setKey(new JobUpdateKey(job5.newBuilder(), s4.getUpdateId()))));
+ assertEquals(
+ ImmutableList.<IJobUpdateSummary>of(),
+ getSummaries(
+ new JobUpdateQuery().setKey(new JobUpdateKey(job4.newBuilder(), s5.getUpdateId()))));
+
+ // Test query by user.
+ assertEquals(ImmutableList.of(s2, s1), getSummaries(new JobUpdateQuery().setUser("user")));
+
+ // Test query by one status.
+ assertEquals(ImmutableList.of(s3), getSummaries(new JobUpdateQuery().setUpdateStatuses(
+ ImmutableSet.of(ERROR))));
+
+ // Test query by multiple statuses.
+ assertEquals(ImmutableList.of(s3, s2, s1), getSummaries(new JobUpdateQuery().setUpdateStatuses(
+ ImmutableSet.of(ERROR, ABORTED, ROLLED_BACK))));
+
+ // Test query by empty statuses.
+ assertEquals(
+ ImmutableList.of(s3, s5, s4, s2, s1),
+ getSummaries(new JobUpdateQuery().setUpdateStatuses(ImmutableSet.<JobUpdateStatus>of())));
+
+ // Test paging.
+ assertEquals(
+ ImmutableList.of(s3, s5),
+ getSummaries(new JobUpdateQuery().setLimit(2).setOffset(0)));
+ assertEquals(
+ ImmutableList.of(s4, s2),
+ getSummaries(new JobUpdateQuery().setLimit(2).setOffset(2)));
+ assertEquals(
+ ImmutableList.of(s1),
+ getSummaries(new JobUpdateQuery().setLimit(2).setOffset(4)));
+
+ // Test no match.
+ assertEquals(
+ ImmutableList.<IJobUpdateSummary>of(),
+ getSummaries(new JobUpdateQuery().setRole("no_match")));
+ }
+
+ @Test
+ public void testQueryDetails() {
+ IJobKey jobKey1 = JobKeys.from("role1", "env", "name1");
+ IJobUpdateKey updateId1 = makeKey(jobKey1, "u1");
+ IJobKey jobKey2 = JobKeys.from("role2", "env", "name2");
+ IJobUpdateKey updateId2 = makeKey(jobKey2, "u2");
+
+ IJobUpdate update1 = makeJobUpdate(updateId1);
+ IJobUpdate update2 = makeJobUpdate(updateId2);
+
+ assertEquals(ImmutableList.<IJobInstanceUpdateEvent>of(), getInstanceEvents(updateId2, 3));
+
+ saveUpdate(update1, Optional.of("lock1"));
+ saveUpdate(update2, Optional.of("lock2"));
+
+ updateJobDetails(populateExpected(update1), FIRST_EVENT);
+ updateJobDetails(populateExpected(update2), FIRST_EVENT);
+
+ IJobUpdateEvent jEvent11 = makeJobUpdateEvent(ROLLING_BACK, 450L);
+ IJobUpdateEvent jEvent12 = makeJobUpdateEvent(ROLLED_BACK, 500L);
+ IJobInstanceUpdateEvent iEvent11 = makeJobInstanceEvent(1, 451L, INSTANCE_ROLLING_BACK);
+ IJobInstanceUpdateEvent iEvent12 = makeJobInstanceEvent(2, 458L, INSTANCE_ROLLED_BACK);
+
+ IJobUpdateEvent jEvent21 = makeJobUpdateEvent(ROLL_FORWARD_PAUSED, 550L);
+ IJobUpdateEvent jEvent22 = makeJobUpdateEvent(ABORTED, 600L);
+ IJobInstanceUpdateEvent iEvent21 = makeJobInstanceEvent(3, 561L, INSTANCE_UPDATING);
+ IJobInstanceUpdateEvent iEvent22 = makeJobInstanceEvent(3, 570L, INSTANCE_UPDATED);
+
+ saveJobEvent(jEvent11, updateId1);
+ saveJobEvent(jEvent12, updateId1);
+ saveJobInstanceEvent(iEvent11, updateId1);
+ saveJobInstanceEvent(iEvent12, updateId1);
+
+ saveJobEvent(jEvent21, updateId2);
+ saveJobEvent(jEvent22, updateId2);
+
+ saveJobInstanceEvent(iEvent21, updateId2);
+ saveJobInstanceEvent(iEvent22, updateId2);
+
+ IJobUpdateDetails details1 = getUpdateDetails(updateId1).get();
+ IJobUpdateDetails details2 = getUpdateDetails(updateId2).get();
+
+ // Test empty query returns all.
+ assertEquals(ImmutableList.of(details2, details1), queryDetails(new JobUpdateQuery()));
+
+ // Test query by update ID.
+ assertEquals(
+ ImmutableList.of(details1),
+ queryDetails(new JobUpdateQuery().setKey(updateId1.newBuilder())));
+
+ // Test query by role.
+ assertEquals(
+ ImmutableList.of(details2),
+ queryDetails(new JobUpdateQuery().setRole(jobKey2.getRole())));
+
+ // Test query by job key.
+ assertEquals(
+ ImmutableList.of(details2),
+ queryDetails(new JobUpdateQuery().setJobKey(jobKey2.newBuilder())));
+
+ // Test query by status.
+ assertEquals(
+ ImmutableList.of(details2),
+ queryDetails(new JobUpdateQuery().setUpdateStatuses(ImmutableSet.of(ABORTED))));
+
+ // Test no match.
+ assertEquals(
+ ImmutableList.<IJobUpdateDetails>of(),
+ queryDetails(new JobUpdateQuery().setRole("no match")));
+ }
+
+ private static IJobUpdateKey makeKey(String id) {
+ return makeKey(JOB, id);
+ }
+
+ private static IJobUpdateKey makeKey(IJobKey job, String id) {
+ return IJobUpdateKey.build(new JobUpdateKey(job.newBuilder(), id));
+ }
+
+ private void assertUpdate(IJobUpdate expected) {
+ IJobUpdateKey key = expected.getSummary().getKey();
+ assertEquals(populateExpected(expected), getUpdate(key).get());
+ assertEquals(getUpdate(key).get(), getUpdateDetails(key).get().getUpdate());
+ assertEquals(getUpdateInstructions(key).get(), expected.getInstructions());
+ }
+
+ private Optional<IJobUpdate> getUpdate(final IJobUpdateKey key) {
+ return storage.read(new Quiet<Optional<IJobUpdate>>() {
+ @Override
+ public Optional<IJobUpdate> apply(Storage.StoreProvider storeProvider) {
+ return storeProvider.getJobUpdateStore().fetchJobUpdate(key);
+ }
+ });
+ }
+
+ private List<IJobInstanceUpdateEvent> getInstanceEvents(final IJobUpdateKey key, final int id) {
+ return storage.read(new Quiet<List<IJobInstanceUpdateEvent>>() {
+ @Override
+ public List<IJobInstanceUpdateEvent> apply(Storage.StoreProvider storeProvider) {
+ return storeProvider.getJobUpdateStore().fetchInstanceEvents(key, id);
+ }
+ });
+ }
+
+ private Optional<IJobUpdateInstructions> getUpdateInstructions(final IJobUpdateKey key) {
+ return storage.read(new Quiet<Optional<IJobUpdateInstructions>>() {
+ @Override
+ public Optional<IJobUpdateInstructions> apply(Storage.StoreProvider storeProvider) {
+ return storeProvider.getJobUpdateStore().fetchJobUpdateInstructions(key);
+ }
+ });
+ }
+
+ private Optional<IJobUpdateDetails> getUpdateDetails(final IJobUpdateKey key) {
+ return storage.read(new Quiet<Optional<IJobUpdateDetails>>() {
+ @Override
+ public Optional<IJobUpdateDetails> apply(Storage.StoreProvider storeProvider) {
+ return storeProvider.getJobUpdateStore().fetchJobUpdateDetails(key);
+ }
+ });
+ }
+
+ private Set<StoredJobUpdateDetails> getAllUpdateDetails() {
+ return storage.read(new Quiet<Set<StoredJobUpdateDetails>>() {
+ @Override
+ public Set<StoredJobUpdateDetails> apply(Storage.StoreProvider storeProvider) {
+ return storeProvider.getJobUpdateStore().fetchAllJobUpdateDetails();
+ }
+ });
+ }
+
+ private List<IJobUpdateDetails> queryDetails(final JobUpdateQuery query) {
+ return storage.read(new Quiet<List<IJobUpdateDetails>>() {
+ @Override
+ public List<IJobUpdateDetails> apply(Storage.StoreProvider storeProvider) {
+ return storeProvider.getJobUpdateStore().fetchJobUpdateDetails(
+ IJobUpdateQuery.build(query));
+ }
+ });
+ }
+
+ private List<IJobUpdateSummary> getSummaries(final JobUpdateQuery query) {
+ return storage.read(new Quiet<List<IJobUpdateSummary>>() {
+ @Override
+ public List<IJobUpdateSummary> apply(Storage.StoreProvider storeProvider) {
+ return storeProvider.getJobUpdateStore().fetchJobUpdateSummaries(
+ IJobUpdateQuery.build(query));
+ }
+ });
+ }
+
+ private static ILock makeLock(IJobKey jobKey, String lockToken) {
+ return ILock.build(new Lock()
+ .setKey(LockKey.job(jobKey.newBuilder()))
+ .setToken(lockToken)
+ .setTimestampMs(100)
+ .setUser("fake user"));
+ }
+
+ private IJobUpdate saveUpdate(final IJobUpdate update, final Optional<String> lockToken) {
+ storage.write(new MutateWork.NoResult.Quiet() {
+ @Override
+ public void execute(MutableStoreProvider storeProvider) {
+ if (lockToken.isPresent()) {
+ storeProvider.getLockStore().saveLock(
+ makeLock(update.getSummary().getJobKey(), lockToken.get()));
+ }
+ storeProvider.getJobUpdateStore().saveJobUpdate(update, lockToken);
+ storeProvider.getJobUpdateStore().saveJobUpdateEvent(
+ update.getSummary().getKey(),
+ FIRST_EVENT);
+ }
+ });
+
+ return update;
+ }
+
+ private IJobUpdate saveUpdateNoEvent(final IJobUpdate update, final Optional<String> lockToken) {
+ storage.write(new MutateWork.NoResult.Quiet() {
+ @Override
+ public void execute(MutableStoreProvider storeProvider) {
+ if (lockToken.isPresent()) {
+ storeProvider.getLockStore().saveLock(
+ makeLock(update.getSummary().getJobKey(), lockToken.get()));
+ }
+ storeProvider.getJobUpdateStore().saveJobUpdate(update, lockToken);
+ }
+ });
+
+ return update;
+ }
+
+ private void saveJobEvent(final IJobUpdateEvent event, final IJobUpdateKey key) {
+ storage.write(new MutateWork.NoResult.Quiet() {
+ @Override
+ public void execute(MutableStoreProvider storeProvider) {
+ storeProvider.getJobUpdateStore().saveJobUpdateEvent(key, event);
+ }
+ });
+ }
+
+ private void saveJobInstanceEvent(final IJobInstanceUpdateEvent event, final IJobUpdateKey key) {
+ storage.write(new MutateWork.NoResult.Quiet() {
+ @Override
+ public void execute(MutableStoreProvider storeProvider) {
+ storeProvider.getJobUpdateStore().saveJobInstanceUpdateEvent(key, event);
+ }
+ });
+ }
+
+ private void truncateUpdates() {
+ storage.write(new MutateWork.NoResult.Quiet() {
+ @Override
+ public void execute(MutableStoreProvider storeProvider) {
+ storeProvider.getJobUpdateStore().deleteAllUpdatesAndEvents();
+ }
+ });
+ }
+
+ private Set<IJobUpdateKey> pruneHistory(final int retainCount, final long pruningThresholdMs) {
+ return storage.write(new MutateWork.Quiet<Set<IJobUpdateKey>>() {
+ @Override
+ public Set<IJobUpdateKey> apply(MutableStoreProvider storeProvider) {
+ return storeProvider.getJobUpdateStore().pruneHistory(retainCount, pruningThresholdMs);
+ }
+ });
+ }
+
+ private void removeLock(final IJobUpdate update, final String lockToken) {
+ storage.write(new MutateWork.NoResult.Quiet() {
+ @Override
+ public void execute(MutableStoreProvider storeProvider) {
+ storeProvider.getLockStore().removeLock(
+ makeLock(update.getSummary().getJobKey(), lockToken).getKey());
+ }
+ });
+ }
+
+ private IJobUpdate populateExpected(IJobUpdate update) {
+ return populateExpected(update, ROLLING_FORWARD, CREATED_MS, CREATED_MS);
+ }
+
+ private IJobUpdate populateExpected(
+ IJobUpdate update,
+ JobUpdateStatus status,
+ long createdMs,
+ long lastMs) {
+
+ JobUpdateState state = new JobUpdateState()
+ .setCreatedTimestampMs(createdMs)
+ .setLastModifiedTimestampMs(lastMs)
+ .setStatus(status);
+ JobUpdate builder = update.newBuilder();
+ builder.getSummary().setState(state);
+ return IJobUpdate.build(builder);
+ }
+
+ private static IJobUpdateEvent makeJobUpdateEvent(JobUpdateStatus status, long timestampMs) {
+ return IJobUpdateEvent.build(
+ new JobUpdateEvent(status, timestampMs)
+ .setUser("user")
+ .setMessage("message"));
+ }
+
+ private IJobInstanceUpdateEvent makeJobInstanceEvent(
+ int instanceId,
+ long timestampMs,
+ JobUpdateAction action) {
+
+ return IJobInstanceUpdateEvent.build(
+ new JobInstanceUpdateEvent(instanceId, timestampMs, action));
+ }
+
+ private IJobUpdateDetails makeJobDetails(IJobUpdate update) {
+ return updateJobDetails(
+ update,
+ ImmutableList.of(FIRST_EVENT),
+ ImmutableList.<IJobInstanceUpdateEvent>of());
+ }
+
+ private IJobUpdateDetails updateJobDetails(IJobUpdate update, IJobUpdateEvent event) {
+ return updateJobDetails(
+ update,
+ ImmutableList.of(event),
+ ImmutableList.<IJobInstanceUpdateEvent>of());
+ }
+
+ private IJobUpdateDetails updateJobDetails(
+ IJobUpdate update,
+ List<IJobUpdateEvent> jobEvents,
+ List<IJobInstanceUpdateEvent> instanceEvents) {
+
+ return IJobUpdateDetails.build(new JobUpdateDetails()
+ .setUpdate(update.newBuilder())
+ .setUpdateEvents(IJobUpdateEvent.toBuildersList(jobEvents))
+ .setInstanceEvents(IJobInstanceUpdateEvent.toBuildersList(instanceEvents)));
+ }
+
+ private IJobUpdateSummary makeSummary(IJobUpdateKey key, String user) {
+ return IJobUpdateSummary.build(new JobUpdateSummary()
+ .setKey(key.newBuilder())
+ .setUpdateId(key.getId())
+ .setJobKey(key.getJob().newBuilder())
+ .setUser(user));
+ }
+
+ private IJobUpdateSummary saveSummary(
+ IJobUpdateKey key,
+ Long modifiedTimestampMs,
+ JobUpdateStatus status,
+ String user,
+ Optional<String> lockToken) {
+
+ IJobUpdateSummary summary = IJobUpdateSummary.build(new JobUpdateSummary()
+ .setKey(key.newBuilder())
+ .setUpdateId(key.getId())
+ .setJobKey(key.getJob().newBuilder())
+ .setUser(user));
+
+ IJobUpdate update = makeJobUpdate(summary);
+ saveUpdate(update, lockToken);
+ saveJobEvent(makeJobUpdateEvent(status, modifiedTimestampMs), key);
+ return populateExpected(update, status, CREATED_MS, modifiedTimestampMs).getSummary();
+ }
+
+ private IJobUpdate makeJobUpdate(IJobUpdateSummary summary) {
+ return IJobUpdate.build(makeJobUpdate().newBuilder().setSummary(summary.newBuilder()));
+ }
+
+ private IJobUpdate makeJobUpdate(IJobUpdateKey key) {
+ return IJobUpdate.build(makeJobUpdate().newBuilder()
+ .setSummary(makeSummary(key, "user").newBuilder()));
+ }
+
+ private IJobUpdate makeJobUpdate() {
+ return IJobUpdate.build(new JobUpdate()
+ .setInstructions(makeJobUpdateInstructions().newBuilder()));
+ }
+
+ private IJobUpdateInstructions makeJobUpdateInstructions() {
+ TaskConfig config = TaskTestUtil.makeConfig(JOB).newBuilder();
+ return IJobUpdateInstructions.build(new JobUpdateInstructions()
+ .setDesiredState(new InstanceTaskConfig()
+ .setTask(config)
+ .setInstances(ImmutableSet.of(new Range(0, 7), new Range(8, 9))))
+ .setInitialState(ImmutableSet.of(
+ new InstanceTaskConfig()
+ .setInstances(ImmutableSet.of(new Range(0, 1), new Range(2, 3)))
+ .setTask(config),
+ new InstanceTaskConfig()
+ .setInstances(ImmutableSet.of(new Range(4, 5), new Range(6, 7)))
+ .setTask(config)))
+ .setSettings(new JobUpdateSettings()
+ .setBlockIfNoPulsesAfterMs(500)
+ .setUpdateGroupSize(1)
+ .setMaxPerInstanceFailures(1)
+ .setMaxFailedInstances(1)
+ .setMaxWaitToInstanceRunningMs(100)
+ .setMinWaitInInstanceRunningMs(200)
+ .setRollbackOnFailure(true)
+ .setWaitForBatchCompletion(true)
+ .setUpdateOnlyTheseInstances(ImmutableSet.of(new Range(0, 0), new Range(3, 5)))));
+ }
+}