All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.netflix.genie.web.tasks.leader.LeaderTasksCoordinator Maven / Gradle / Ivy

The newest version!
/*
 *
 *  Copyright 2016 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 com.netflix.genie.web.tasks.leader;

import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.integration.leader.event.AbstractLeaderEvent;
import org.springframework.integration.leader.event.OnGrantedEvent;
import org.springframework.integration.leader.event.OnRevokedEvent;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.Trigger;

import javax.annotation.PreDestroy;
import java.util.Collection;
import java.util.Set;
import java.util.concurrent.ScheduledFuture;

/**
 * Class which handles coordinating leadership related tasks. Listens for leadership grant and revoke events and starts
 * tasks associated with being the cluster leader.
 *
 * @author tgianos
 * @since 3.0.0
 */
@Slf4j
public class LeaderTasksCoordinator {

    private final Set tasks;
    private final Set> futures;
    private final TaskScheduler taskScheduler;
    private boolean isRunning;

    /**
     * Constructor.
     *
     * @param taskScheduler The task executor to use.
     * @param tasks         The leadership tasks to run
     */
    public LeaderTasksCoordinator(final TaskScheduler taskScheduler, final Collection tasks) {
        this.futures = Sets.newHashSet();
        this.taskScheduler = taskScheduler;
        this.isRunning = false;
        this.tasks = Sets.newHashSet();
        if (tasks != null) {
            this.tasks.addAll(tasks);
        }
    }

    /**
     * Make sure any threads are taken care of before this object is destroyed.
     */
    @PreDestroy
    public void preDestroy() {
        this.cancelTasks();
    }

    /**
     * Leadership event listener. Starts and stop processes when this Genie node is elected the leader of the cluster.
     * 

* Synchronized to ensure no race conditions between threads trying to start and stop leadership tasks. * * @param leaderEvent The leader grant or revoke event * @see org.springframework.integration.leader.event.OnGrantedEvent * @see org.springframework.integration.leader.event.OnRevokedEvent */ @EventListener public synchronized void onLeaderEvent(final AbstractLeaderEvent leaderEvent) { if (leaderEvent instanceof OnGrantedEvent) { if (this.isRunning) { return; } log.info("Leadership granted."); this.isRunning = true; this.tasks.forEach( task -> { switch (task.getScheduleType()) { case TRIGGER: final Trigger trigger = task.getTrigger(); log.info( "Scheduling leadership task {} to run with trigger {}", task.getClass().getCanonicalName(), trigger ); this.futures.add(this.taskScheduler.schedule(task, trigger)); break; case FIXED_RATE: final long rate = task.getFixedRate(); log.info( "Scheduling leadership task {} to run every {} second(s)", task.getClass().getCanonicalName(), rate / 1000.0 ); this.futures.add(this.taskScheduler.scheduleAtFixedRate(task, rate)); break; case FIXED_DELAY: final long delay = task.getFixedDelay(); log.info( "Scheduling leadership task {} to run at a fixed delay of every {} second(s)", task.getClass().getCanonicalName(), delay / 1000.0 ); this.futures.add(this.taskScheduler.scheduleWithFixedDelay(task, delay)); break; default: log.error("Unknown Genie task type {}", task.getScheduleType()); } } ); } else if (leaderEvent instanceof OnRevokedEvent) { if (!this.isRunning) { return; } log.info("Leadership revoked."); this.isRunning = false; this.cancelTasks(); } else { log.warn("Unknown leadership event {}. Ignoring.", leaderEvent); } } private void cancelTasks() { for (final ScheduledFuture future : this.futures) { log.info("Attempting to cancel thread {}", future); if (future.cancel(true)) { log.info("Successfully cancelled."); } else { log.info("Failed to cancel."); } } // Clear out the tasks this.futures.clear(); this.tasks.forEach(LeaderTask::cleanup); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy