blob: 7d87ddf464e5ac2be8aca459e55ee98448c24da0 [file] [log] [blame]
/**
* 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.updater;
import java.util.Optional;
import static java.util.Objects.requireNonNull;
/**
* Determines actions that must be taken to change the configuration of a running task.
* <p>
* A state evaluator is expected to be used multiple times over the course of changing an active
* task's configuration. This should be invoked every time the state of an instance changes to
* determine what action to take next. It's expected that it will eventually converge by
* {@link Result#SUCCEEDED succeeding}, or failing with {@link Result#FAILED_TERMINATED}.
*
* @param <T> Instance state type.
*/
interface StateEvaluator<T> {
/**
* Evaluates the state differences between the desired state and the provided {@code actualState}.
* <p>
* This function should be idempotent, with the exception of an internal failure counter that
* increments when an updating task exits, or an active but not
* {@link org.apache.aurora.gen.ScheduleStatus#RUNNING RUNNING} task takes too long to start.
* <p>
* It is the responsibility of the caller to ensure that the {@code actualState} is the latest
* value. Note: the caller should avoid calling this when a terminal task is moving to another
* terminal state. It should also suppress deletion events for tasks that have been replaced by
* an active task.
*
* @param actualState The actual observed state of the task.
* @return the evaluation result, including the state of the instance update, and a necessary
* action to perform.
*/
Result evaluate(T actualState);
Optional<Failure> NO_FAILURE = Optional.empty();
enum Result {
EVALUATE_ON_STATE_CHANGE(Optional.of(InstanceAction.AWAIT_STATE_CHANGE), NO_FAILURE),
REPLACE_TASK_AND_EVALUATE_ON_STATE_CHANGE(Optional.of(InstanceAction.ADD_TASK), NO_FAILURE),
KILL_TASK_AND_EVALUATE_ON_STATE_CHANGE(Optional.of(InstanceAction.KILL_TASK), NO_FAILURE),
KILL_TASK_WITH_RESERVATION_AND_EVALUATE_ON_STATE_CHANGE(
Optional.of(InstanceAction.KILL_TASK_AND_RESERVE), NO_FAILURE),
EVALUATE_AFTER_MIN_RUNNING_MS(Optional.of(InstanceAction.WATCH_TASK), NO_FAILURE),
SUCCEEDED(Optional.empty(), NO_FAILURE),
FAILED_TERMINATED(Optional.empty(), Optional.of(Failure.EXITED));
private final Optional<InstanceAction> action;
private final Optional<Failure> failure;
Result(Optional<InstanceAction> action, Optional<Failure> failure) {
this.action = requireNonNull(action);
this.failure = requireNonNull(failure);
}
public Optional<InstanceAction> getAction() {
return action;
}
public Optional<Failure> getFailure() {
return failure;
}
}
enum Failure {
EXITED("exited.");
private final String reason;
Failure(String reason) {
this.reason = reason;
}
public String getReason() {
return reason;
}
}
}