io.mantisrx.master.jobcluster.job.JobHelper Maven / Gradle / Ivy
/*
* Copyright 2019 Netflix, Inc.
*
* 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 io.mantisrx.master.jobcluster.job;
import static java.util.Optional.empty;
import static java.util.Optional.ofNullable;
import io.mantisrx.master.jobcluster.job.worker.WorkerHeartbeat;
import io.mantisrx.master.jobcluster.job.worker.WorkerState;
import io.mantisrx.master.jobcluster.job.worker.WorkerStatus;
import io.mantisrx.master.jobcluster.job.worker.WorkerTerminate;
import io.mantisrx.runtime.descriptor.SchedulingInfo;
import io.mantisrx.server.master.scheduler.WorkerEvent;
import io.mantisrx.server.master.scheduler.WorkerLaunched;
import io.mantisrx.server.master.scheduler.WorkerResourceStatus;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* General Job utility methods.
*/
public final class JobHelper {
private static final Logger LOGGER = LoggerFactory.getLogger(JobHelper.class);
private JobHelper() {
}
/**
* Give scheduling info and whether job has Job Master return the list of user stages.
* Job Master stage is considered a system stage so is excluded if present.
* @param schedulingInfo
* @param hasJobMaster
* @return
*/
public static List getUserStageNumbers(SchedulingInfo schedulingInfo, boolean hasJobMaster) {
List stageNumbers = new ArrayList<>();
int totalStages = schedulingInfo.getStages().size();
if (hasJobMaster) {
totalStages = totalStages - 1;
}
for (int i = 1; i <= totalStages; i++) {
stageNumbers.add(i);
}
return stageNumbers;
}
/**
* Determines whether a workerevent is terminal.
* @param workerEvent
* @return
*/
public static boolean isTerminalWorkerEvent(WorkerEvent workerEvent) {
if (workerEvent instanceof WorkerTerminate) {
return true;
} else if (workerEvent instanceof WorkerStatus) {
WorkerStatus status = (WorkerStatus) workerEvent;
if (WorkerState.isTerminalState(status.getState())) {
return true;
}
} else if (workerEvent instanceof WorkerResourceStatus) {
WorkerResourceStatus.VMResourceState state = ((WorkerResourceStatus) workerEvent).getState();
if (WorkerResourceStatus.VMResourceState.FAILED.equals(state)
|| WorkerResourceStatus.VMResourceState.COMPLETED.equals(state)) {
return true;
}
}
return false;
}
/**
* Extract hostname from worker event if present.
* @param event
* @return
*/
public static Optional getWorkerHostFromWorkerEvent(WorkerEvent event) {
Optional host = empty();
if (event instanceof WorkerLaunched) {
host = ofNullable(((WorkerLaunched) event).getHostname());
} else if (event instanceof WorkerHeartbeat) {
host = ofNullable(((WorkerHeartbeat) event).getStatus().getHostname());
} else {
LOGGER.warn("Host name unknown for workerId {}", event.getWorkerId());
}
return host;
}
/**
* Called after a) All workers started and job goes to Launched state
* b) Mantis Master is restarting and its reinitializing this Job
* This method calculates the remaining time for this job to run.
* @param maxRuntimeSecs
* @param startedAt
* @return
*/
public static long calculateRuntimeDuration(long maxRuntimeSecs, Instant startedAt) {
long terminateJobInSecs = maxRuntimeSecs;
if (maxRuntimeSecs > 0) {
Instant now = Instant.now();
if (now.isAfter(startedAt)) {
// Job was already running (Occurs when master was restarted)
long elapsedSeconds = now.getEpochSecond() - startedAt.getEpochSecond();
// Calculate remaining time to run
terminateJobInSecs = maxRuntimeSecs - elapsedSeconds;
if (terminateJobInSecs <= 0) {
// Runtime has already reached terminate.
// trigger terminate in a second.
terminateJobInSecs = 1;
}
}
}
return terminateJobInSecs;
}
}