}
}
};
// To be called on a task transitioning into the FINISHED state.
final Command rescheduleIfService = new Command() {
@Override
public void execute() {
if (task.get().getAssignedTask().getTask().isIsService()) {
addFollowup(RESCHEDULE);
}
}
};
// To be called on a task transitioning into the FAILED state.
final Command incrementFailuresMaybeReschedule = new Command() {
@Override
public void execute() {
addFollowup(INCREMENT_FAILURES);
// Max failures is ignored for service task.
boolean isService = task.get().getAssignedTask().getTask().isIsService();
// Max failures is ignored when set to -1.
int maxFailures = task.get().getAssignedTask().getTask().getMaxTaskFailures();
boolean belowMaxFailures =
maxFailures == -1 || task.get().getFailureCount() < (maxFailures - 1);
if (isService || belowMaxFailures) {
addFollowup(RESCHEDULE);
} else {
LOG.info("Task " + name + " reached failure limit, not rescheduling");
}
}
};
final Closure<Transition<TaskState>> deleteIfKilling =
Closures.filter(Transition.to(KILLING), addFollowupClosure(DELETE));
stateMachine = StateMachine.<TaskState>builder(name)
.logTransitions()
.initialState(initialState)
.addState(
Rule.from(INIT)
.to(PENDING, THROTTLED))
.addState(
Rule.from(PENDING)
.to(ASSIGNED, KILLING)
.withCallback(deleteIfKilling))
.addState(
Rule.from(THROTTLED)
.to(PENDING, KILLING)
.withCallback(deleteIfKilling))
.addState(
Rule.from(ASSIGNED)
.to(STARTING, RUNNING, FINISHED, FAILED, RESTARTING, DRAINING,
KILLED, KILLING, LOST, PREEMPTING)
.withCallback(
new Closure<Transition<TaskState>>() {
@Override
public void execute(Transition<TaskState> transition) {
switch (transition.getTo()) {
case FINISHED:
rescheduleIfService.execute();
break;
case PREEMPTING:
addFollowup(KILL);
break;
case FAILED:
incrementFailuresMaybeReschedule.execute();
break;
case RESTARTING:
addFollowup(KILL);
break;
case DRAINING:
addFollowup(KILL);
break;
case KILLED:
addFollowup(RESCHEDULE);
break;
case LOST:
addFollowup(RESCHEDULE);
addFollowup(KILL);
break;
case KILLING:
addFollowup(KILL);
break;
default:
// No-op.
}
}
}
))
.addState(
Rule.from(STARTING)
.to(RUNNING, FINISHED, FAILED, RESTARTING, DRAINING, KILLING,
KILLED, LOST, PREEMPTING)
.withCallback(
new Closure<Transition<TaskState>>() {
@Override
public void execute(Transition<TaskState> transition) {
switch (transition.getTo()) {
case FINISHED:
rescheduleIfService.execute();
break;
case RESTARTING:
addFollowup(KILL);
break;
case DRAINING:
addFollowup(KILL);
break;
case PREEMPTING:
addFollowup(KILL);
break;
case FAILED:
incrementFailuresMaybeReschedule.execute();
break;
case KILLED:
addFollowup(RESCHEDULE);
break;
case KILLING:
addFollowup(KILL);
break;
case LOST:
addFollowup(RESCHEDULE);
break;
case SANDBOX_DELETED:
// The slave previously acknowledged that it had the task, and now
// stopped reporting it.
addFollowupTransition(LOST);
break;
default:
// No-op.
}
}
}
))
.addState(
Rule.from(RUNNING)
.to(FINISHED, RESTARTING, DRAINING, FAILED, KILLING, KILLED, LOST, PREEMPTING)
.withCallback(
new Closure<Transition<TaskState>>() {
@Override
public void execute(Transition<TaskState> transition) {
switch (transition.getTo()) {
case FINISHED:
rescheduleIfService.execute();
break;
case PREEMPTING:
addFollowup(KILL);
break;
case RESTARTING:
addFollowup(KILL);
break;
case DRAINING:
addFollowup(KILL);
break;
case FAILED:
incrementFailuresMaybeReschedule.execute();
break;
case KILLED:
addFollowup(RESCHEDULE);
break;