private IScheduledTask makeFlappyTaskWithStates( String taskId, Iterable<ScheduleStatus> states, @Nullable String ancestorId) { Amount<Long, Time> timeInState = Amount.of(10L, Time.SECONDS); ScheduledTask base = makeTask(taskId, INIT).newBuilder(); for (ScheduleStatus status : states) { base.addToTaskEvents(new TaskEvent(clock.nowMillis(), status)); clock.advance(timeInState); } base.setAncestorId(ancestorId); final IScheduledTask result = IScheduledTask.build(base); // Insert the task if it doesn't already exist. storage.write( new MutateWork.NoResult.Quiet() { @Override protected void execute(MutableStoreProvider storeProvider) { TaskStore.Mutable taskStore = storeProvider.getUnsafeTaskStore(); if (taskStore.fetchTasks(Query.taskScoped(Tasks.id(result))).isEmpty()) { taskStore.saveTasks(ImmutableSet.of(result)); } } }); return result; }
@Test public void testResistsStarvation() { // TODO(wfarner): This test requires intimate knowledge of the way futures are used inside // TaskScheduler. It's time to test using a real ScheduledExecutorService. expectAnyMaintenanceCalls(); IScheduledTask jobA0 = makeTask("a0", PENDING); ScheduledTask jobA1Builder = jobA0.newBuilder(); jobA1Builder.getAssignedTask().setTaskId("a1"); jobA1Builder.getAssignedTask().setInstanceId(1); IScheduledTask jobA1 = IScheduledTask.build(jobA1Builder); ScheduledTask jobA2Builder = jobA0.newBuilder(); jobA2Builder.getAssignedTask().setTaskId("a2"); jobA2Builder.getAssignedTask().setInstanceId(2); IScheduledTask jobA2 = IScheduledTask.build(jobA2Builder); IScheduledTask jobB0 = makeTask("b0", PENDING); expectOfferDeclineIn(10); expectOfferDeclineIn(10); expectOfferDeclineIn(10); expectOfferDeclineIn(10); Capture<Runnable> timeoutA = expectTaskGroupBackoff(10); Capture<Runnable> timeoutB = expectTaskGroupBackoff(10); Capture<IScheduledTask> firstScheduled = expectTaskScheduled(jobA0); Capture<IScheduledTask> secondScheduled = expectTaskScheduled(jobB0); // Expect another watch of the task group for job A. expectTaskGroupBackoff(10); replayAndCreateScheduler(); offerQueue.addOffer(OFFER_A); offerQueue.addOffer(OFFER_B); offerQueue.addOffer(OFFER_C); offerQueue.addOffer(OFFER_D); changeState(jobA0, INIT, PENDING); changeState(jobA1, INIT, PENDING); changeState(jobA2, INIT, PENDING); changeState(jobB0, INIT, PENDING); timeoutA.getValue().run(); timeoutB.getValue().run(); assertEquals( ImmutableSet.of(jobA0, jobB0), ImmutableSet.of(firstScheduled.getValue(), secondScheduled.getValue())); }