Search in sources :

Example 21 with Pair

use of com.netflix.titus.common.util.tuple.Pair in project titus-control-plane by Netflix.

the class TaskMigrationDeschedulerTest method testAgentInstanceRequiredMigration.

@Test
public void testAgentInstanceRequiredMigration() {
    Task job1Task0 = jobOperations.getTasks("job1").get(0);
    relocationConnectorStubs.place("active1", job1Task0);
    relocationConnectorStubs.setQuota("job1", 1);
    job1Task0 = jobOperations.findTaskById(job1Task0.getId()).get().getRight();
    relocationConnectorStubs.markNodeRelocationRequired(job1Task0.getTaskContext().get(TaskAttributes.TASK_ATTRIBUTES_AGENT_INSTANCE_ID));
    Optional<Pair<TitusNode, List<Task>>> results = newDescheduler(Collections.emptyMap()).nextBestMatch();
    assertThat(results).isNotEmpty();
}
Also used : Task(com.netflix.titus.api.jobmanager.model.job.Task) Pair(com.netflix.titus.common.util.tuple.Pair) Test(org.junit.Test)

Example 22 with Pair

use of com.netflix.titus.common.util.tuple.Pair in project titus-control-plane by Netflix.

the class TaskMigrationDeschedulerTest method testSelfMigration.

@Test
public void testSelfMigration() {
    Task job1Task0 = jobOperations.getTasks("job1").get(0);
    relocationConnectorStubs.place("removable1", job1Task0);
    relocationConnectorStubs.setQuota("job1", 1);
    TaskRelocationPlan job1Task0Plan = TaskRelocationPlan.newBuilder().withTaskId(job1Task0.getId()).withRelocationTime(Long.MAX_VALUE / 2).build();
    Optional<Pair<TitusNode, List<Task>>> results = newDescheduler(Collections.singletonMap(job1Task0.getId(), job1Task0Plan)).nextBestMatch();
    assertThat(results).isEmpty();
}
Also used : Task(com.netflix.titus.api.jobmanager.model.job.Task) TaskRelocationPlan(com.netflix.titus.api.relocation.model.TaskRelocationPlan) Pair(com.netflix.titus.common.util.tuple.Pair) Test(org.junit.Test)

Example 23 with Pair

use of com.netflix.titus.common.util.tuple.Pair in project titus-control-plane by Netflix.

the class DefaultDeschedulerService method deschedule.

@Override
public List<DeschedulingResult> deschedule(Map<String, TaskRelocationPlan> plannedAheadTaskRelocationPlans) {
    List<Pair<Job, List<Task>>> allJobsAndTasks = jobOperations.getJobsAndTasks();
    Map<String, Job<?>> jobs = allJobsAndTasks.stream().map(Pair::getLeft).collect(Collectors.toMap(Job::getId, j -> j));
    Map<String, Task> tasksById = allJobsAndTasks.stream().flatMap(p -> p.getRight().stream()).collect(Collectors.toMap(Task::getId, t -> t));
    EvacuatedAgentsAllocationTracker evacuatedAgentsAllocationTracker = new EvacuatedAgentsAllocationTracker(nodeDataResolver.resolve(), tasksById);
    EvictionQuotaTracker evictionQuotaTracker = new EvictionQuotaTracker(evictionOperations, jobs);
    TaskMigrationDescheduler taskMigrationDescheduler = new TaskMigrationDescheduler(plannedAheadTaskRelocationPlans, evacuatedAgentsAllocationTracker, evictionQuotaTracker, evictionConfiguration, jobs, tasksById, titusRuntime);
    Map<String, DeschedulingResult> requestedImmediateEvictions = taskMigrationDescheduler.findAllImmediateEvictions();
    Map<String, DeschedulingResult> requestedEvictions = taskMigrationDescheduler.findRequestedJobOrTaskMigrations();
    Map<String, DeschedulingResult> allRequestedEvictions = CollectionsExt.merge(requestedImmediateEvictions, requestedEvictions);
    Map<String, DeschedulingResult> regularEvictions = new HashMap<>();
    Optional<Pair<TitusNode, List<Task>>> bestMatch;
    while ((bestMatch = taskMigrationDescheduler.nextBestMatch()).isPresent()) {
        TitusNode agent = bestMatch.get().getLeft();
        List<Task> tasks = bestMatch.get().getRight();
        tasks.forEach(task -> {
            if (!allRequestedEvictions.containsKey(task.getId())) {
                Optional<TaskRelocationPlan> relocationPlanForTask = getRelocationPlanForTask(agent, task, plannedAheadTaskRelocationPlans);
                relocationPlanForTask.ifPresent(rp -> regularEvictions.put(task.getId(), DeschedulingResult.newBuilder().withTask(task).withAgentInstance(agent).withTaskRelocationPlan(rp).build()));
            }
        });
    }
    // Find eviction which could not be scheduled now.
    for (Task task : tasksById.values()) {
        if (allRequestedEvictions.containsKey(task.getId()) || regularEvictions.containsKey(task.getId())) {
            continue;
        }
        if (evacuatedAgentsAllocationTracker.isEvacuated(task)) {
            DeschedulingFailure failure = taskMigrationDescheduler.getDeschedulingFailure(task);
            TaskRelocationPlan relocationPlan = plannedAheadTaskRelocationPlans.get(task.getId());
            if (relocationPlan == null) {
                relocationPlan = newNotDelayedRelocationPlan(task, false);
            }
            TitusNode agent = evacuatedAgentsAllocationTracker.getRemovableAgent(task);
            regularEvictions.put(task.getId(), DeschedulingResult.newBuilder().withTask(task).withAgentInstance(agent).withTaskRelocationPlan(relocationPlan).withFailure(failure).build());
        }
    }
    return CollectionsExt.merge(new ArrayList<>(allRequestedEvictions.values()), new ArrayList<>(regularEvictions.values()));
}
Also used : Task(com.netflix.titus.api.jobmanager.model.job.Task) CollectionsExt(com.netflix.titus.common.util.CollectionsExt) HashMap(java.util.HashMap) RelocationPredicates(com.netflix.titus.supplementary.relocation.util.RelocationPredicates) Singleton(javax.inject.Singleton) AtomicReference(java.util.concurrent.atomic.AtomicReference) ArrayList(java.util.ArrayList) Inject(javax.inject.Inject) Pair(com.netflix.titus.common.util.tuple.Pair) Map(java.util.Map) EvictionConfiguration(com.netflix.titus.runtime.connector.eviction.EvictionConfiguration) NodeDataResolver(com.netflix.titus.supplementary.relocation.connector.NodeDataResolver) ReadOnlyJobOperations(com.netflix.titus.api.jobmanager.service.ReadOnlyJobOperations) TaskRelocationReason(com.netflix.titus.api.relocation.model.TaskRelocationPlan.TaskRelocationReason) TaskRelocationPlan(com.netflix.titus.api.relocation.model.TaskRelocationPlan) DeschedulingFailure(com.netflix.titus.supplementary.relocation.model.DeschedulingFailure) DeschedulingResult(com.netflix.titus.supplementary.relocation.model.DeschedulingResult) Job(com.netflix.titus.api.jobmanager.model.job.Job) Collectors(java.util.stream.Collectors) List(java.util.List) ReadOnlyEvictionOperations(com.netflix.titus.api.eviction.service.ReadOnlyEvictionOperations) Optional(java.util.Optional) RelocationUtil(com.netflix.titus.supplementary.relocation.util.RelocationUtil) VisibleForTesting(com.google.common.annotations.VisibleForTesting) TitusRuntime(com.netflix.titus.common.runtime.TitusRuntime) Clock(com.netflix.titus.common.util.time.Clock) TitusNode(com.netflix.titus.supplementary.relocation.connector.TitusNode) JobFunctions.hasDisruptionBudget(com.netflix.titus.api.jobmanager.model.job.JobFunctions.hasDisruptionBudget) Task(com.netflix.titus.api.jobmanager.model.job.Task) HashMap(java.util.HashMap) DeschedulingResult(com.netflix.titus.supplementary.relocation.model.DeschedulingResult) TaskRelocationPlan(com.netflix.titus.api.relocation.model.TaskRelocationPlan) DeschedulingFailure(com.netflix.titus.supplementary.relocation.model.DeschedulingFailure) Job(com.netflix.titus.api.jobmanager.model.job.Job) TitusNode(com.netflix.titus.supplementary.relocation.connector.TitusNode) Pair(com.netflix.titus.common.util.tuple.Pair)

Example 24 with Pair

use of com.netflix.titus.common.util.tuple.Pair in project titus-control-plane by Netflix.

the class ReactorMapWithStateTransformer method apply.

@Override
public Publisher<R> apply(Flux<T> source) {
    return Flux.create(sink -> {
        AtomicReference<S> lastState = new AtomicReference<>(zeroSupplier.get());
        Flux<Either<T, Function<S, Pair<R, S>>>> sourceEither = source.map(Either::ofValue);
        Flux<Either<T, Function<S, Pair<R, S>>>> cleanupEither = cleanupActions.map(Either::ofError);
        Disposable subscription = Flux.merge(sourceEither, cleanupEither).subscribe(next -> {
            Pair<R, S> result;
            if (next.hasValue()) {
                try {
                    result = transformer.apply(next.getValue(), lastState.get());
                } catch (Throwable e) {
                    sink.error(e);
                    return;
                }
            } else {
                try {
                    Function<S, Pair<R, S>> action = next.getError();
                    result = action.apply(lastState.get());
                } catch (Throwable e) {
                    sink.error(e);
                    return;
                }
            }
            lastState.set(result.getRight());
            sink.next(result.getLeft());
        }, sink::error, sink::complete);
        sink.onCancel(subscription);
    });
}
Also used : Disposable(reactor.core.Disposable) Either(com.netflix.titus.common.util.tuple.Either) AtomicReference(java.util.concurrent.atomic.AtomicReference) Pair(com.netflix.titus.common.util.tuple.Pair)

Example 25 with Pair

use of com.netflix.titus.common.util.tuple.Pair in project titus-control-plane by Netflix.

the class CassandraJobStore method retrieveJobs.

@Override
public Observable<Pair<List<Job<?>>, Integer>> retrieveJobs() {
    Observable result = Observable.fromCallable(() -> {
        List<String> jobIds = activeJobIdsBucketManager.getItems();
        return jobIds.stream().map(retrieveActiveJobStatement::bind).map(this::execute).collect(Collectors.toList());
    }).flatMap(observables -> Observable.merge(observables, getConcurrencyLimit()).flatMapIterable(resultSet -> {
        List<Row> allRows = resultSet.all();
        if (allRows.isEmpty()) {
            logger.debug("Job id with no record");
            return Collections.emptyList();
        }
        return allRows.stream().map(row -> row.getString(0)).map(value -> {
            String effectiveValue;
            if (fitBadDataInjection.isPresent()) {
                effectiveValue = fitBadDataInjection.get().afterImmediate(JobStoreFitAction.ErrorKind.CorruptedRawJobRecords.name(), value);
            } else {
                effectiveValue = value;
            }
            Job<?> job;
            try {
                job = deserializeJob(effectiveValue);
            } catch (Exception e) {
                logger.error("Cannot map serialized job data to Job class: {}", effectiveValue, e);
                return Either.ofError(e);
            }
            if (job.getJobDescriptor().getDisruptionBudget() == null) {
                titusRuntime.getCodeInvariants().inconsistent("jobWithNoDisruptionBudget: jobId=%s", job.getId());
                job = JobFunctions.changeDisruptionBudget(job, DisruptionBudget.none());
            }
            // TODO Remove this code when there are no more jobs with missing migration data (caused by a bug in ServiceJobExt builder).
            if (job.getJobDescriptor().getExtensions() instanceof ServiceJobExt) {
                Job<ServiceJobExt> serviceJob = (Job<ServiceJobExt>) job;
                ServiceJobExt ext = serviceJob.getJobDescriptor().getExtensions();
                if (ext.getMigrationPolicy() == null) {
                    titusRuntime.getCodePointTracker().markReachable("Corrupted task migration record in Cassandra: " + job.getId());
                    ServiceJobExt fixedExt = ext.toBuilder().withMigrationPolicy(SystemDefaultMigrationPolicy.newBuilder().build()).build();
                    logger.warn("Service job with no migration policy defined. Setting system default: {}", job.getId());
                    job = serviceJob.toBuilder().withJobDescriptor(serviceJob.getJobDescriptor().toBuilder().withExtensions(fixedExt).build()).build();
                }
            }
            if (!fitBadDataInjection.isPresent()) {
                return Either.ofValue(job);
            }
            Job<?> effectiveJob = fitBadDataInjection.get().afterImmediate(JobStoreFitAction.ErrorKind.CorruptedJobRecords.name(), job);
            return Either.ofValue(effectiveJob);
        }).collect(Collectors.toList());
    })).toList().map(everything -> {
        List<Job> goodJobs = (List<Job>) everything.stream().filter(Either::hasValue).map(Either::getValue).collect(Collectors.toList());
        int errors = everything.size() - goodJobs.size();
        return Pair.of(goodJobs, errors);
    });
    return result;
}
Also used : JobStoreException(com.netflix.titus.api.jobmanager.store.JobStoreException) Task(com.netflix.titus.api.jobmanager.model.job.Task) LoggerFactory(org.slf4j.LoggerFactory) ConsistencyLevel(com.datastax.driver.core.ConsistencyLevel) Session(com.datastax.driver.core.Session) JobState(com.netflix.titus.api.jobmanager.model.job.JobState) Either(com.netflix.titus.common.util.tuple.Either) JobStore(com.netflix.titus.api.jobmanager.store.JobStore) BatchStatement(com.datastax.driver.core.BatchStatement) JobStoreFitAction(com.netflix.titus.api.jobmanager.store.JobStoreFitAction) Job(com.netflix.titus.api.jobmanager.model.job.Job) StoreTransactionLoggers.transactionLogger(com.netflix.titus.ext.cassandra.store.StoreTransactionLoggers.transactionLogger) JobFunctions(com.netflix.titus.api.jobmanager.model.job.JobFunctions) Collectors(java.util.stream.Collectors) TaskState(com.netflix.titus.api.jobmanager.model.job.TaskState) List(java.util.List) Stream(java.util.stream.Stream) DisruptionBudget(com.netflix.titus.api.jobmanager.model.job.disruptionbudget.DisruptionBudget) ProxyConfiguration(com.netflix.titus.common.util.guice.annotation.ProxyConfiguration) Optional(java.util.Optional) Logging(com.netflix.titus.common.util.guice.ProxyType.Logging) Statement(com.datastax.driver.core.Statement) Completable(rx.Completable) MoreExecutors(com.google.common.util.concurrent.MoreExecutors) ListenableFuture(com.google.common.util.concurrent.ListenableFuture) QueryTrace(com.datastax.driver.core.QueryTrace) Row(com.datastax.driver.core.Row) Exceptions(rx.exceptions.Exceptions) Callable(java.util.concurrent.Callable) Singleton(javax.inject.Singleton) ArrayList(java.util.ArrayList) Observable(rx.Observable) Inject(javax.inject.Inject) PreparedStatement(com.datastax.driver.core.PreparedStatement) ResultSet(com.datastax.driver.core.ResultSet) Pair(com.netflix.titus.common.util.tuple.Pair) Spectator(com.netflix.titus.common.util.guice.ProxyType.Spectator) DriverException(com.datastax.driver.core.exceptions.DriverException) Nonnull(javax.annotation.Nonnull) Nullable(javax.annotation.Nullable) FitFramework(com.netflix.titus.common.framework.fit.FitFramework) Logger(org.slf4j.Logger) ServiceJobExt(com.netflix.titus.api.jobmanager.model.job.ext.ServiceJobExt) FitInjection(com.netflix.titus.common.framework.fit.FitInjection) SystemDefaultMigrationPolicy(com.netflix.titus.api.jobmanager.model.job.migration.SystemDefaultMigrationPolicy) ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) Emitter(rx.Emitter) FutureCallback(com.google.common.util.concurrent.FutureCallback) Futures(com.google.common.util.concurrent.Futures) V3JobOperations(com.netflix.titus.api.jobmanager.service.V3JobOperations) ObjectMappers(com.netflix.titus.api.json.ObjectMappers) Version(com.netflix.titus.api.jobmanager.model.job.Version) TitusRuntime(com.netflix.titus.common.runtime.TitusRuntime) Collections(java.util.Collections) ServiceJobExt(com.netflix.titus.api.jobmanager.model.job.ext.ServiceJobExt) Either(com.netflix.titus.common.util.tuple.Either) List(java.util.List) ArrayList(java.util.ArrayList) Job(com.netflix.titus.api.jobmanager.model.job.Job) Observable(rx.Observable) JobStoreException(com.netflix.titus.api.jobmanager.store.JobStoreException) DriverException(com.datastax.driver.core.exceptions.DriverException)

Aggregations

Pair (com.netflix.titus.common.util.tuple.Pair)41 Task (com.netflix.titus.api.jobmanager.model.job.Task)22 List (java.util.List)21 ArrayList (java.util.ArrayList)18 Job (com.netflix.titus.api.jobmanager.model.job.Job)14 Map (java.util.Map)10 Collectors (java.util.stream.Collectors)10 TitusRuntime (com.netflix.titus.common.runtime.TitusRuntime)8 Optional (java.util.Optional)8 Logger (org.slf4j.Logger)8 LoggerFactory (org.slf4j.LoggerFactory)8 TaskState (com.netflix.titus.api.jobmanager.model.job.TaskState)7 HashMap (java.util.HashMap)7 JobFunctions (com.netflix.titus.api.jobmanager.model.job.JobFunctions)6 Collections (java.util.Collections)6 Observable (rx.Observable)6 TaskRelocationPlan (com.netflix.titus.api.relocation.model.TaskRelocationPlan)5 Function (java.util.function.Function)5 PreparedStatement (com.datastax.driver.core.PreparedStatement)4 Session (com.datastax.driver.core.Session)4