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

nebula.plugin.metrics.dispatcher.AbstractQueuedExecutionThreadService Maven / Gradle / Ivy

Go to download

Gradle Metrics plugin: Collects gradle metrics and publishes to ElasticSearch HTTP/Splunk/REST endpoints

There is a newer version: 10.1.8
Show newest version
/*
 *  Copyright 2015-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 nebula.plugin.metrics.dispatcher;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Throwables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.AbstractExecutionThreadService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nullable;
import java.util.List;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static org.apache.commons.lang3.exception.ExceptionUtils.getRootCauseMessage;

/**
 * An {@link AbstractQueuedExecutionThreadService} that allows actions of type 
E
to be queued and executed in * the order received. * * @author Danny Thomas */ public abstract class AbstractQueuedExecutionThreadService extends AbstractExecutionThreadService { private static final Set QUEUE_AVAILABLE_STATES = Sets.newHashSet(State.STARTING, State.RUNNING, State.STOPPING); // We can't use the MetricsLoggerFactory here, or we'll get a feedback loop from the debug statements in the indexing critical paths private final Logger logger = LoggerFactory.getLogger(AbstractExecutionThreadService.class); private final BlockingQueue queue; private final boolean failOnError; private final AtomicBoolean failed = new AtomicBoolean(); private final boolean verboseErrorOuput; public AbstractQueuedExecutionThreadService(boolean failOnError, boolean verboseErrorOuput) { this(new LinkedBlockingQueue(), failOnError, verboseErrorOuput); } @VisibleForTesting AbstractQueuedExecutionThreadService(BlockingQueue queue, boolean failOnError, boolean verboseErrorOutput) { this.queue = checkNotNull(queue); this.failOnError = failOnError; this.verboseErrorOuput = verboseErrorOutput; } protected abstract void execute(E action) throws Exception; @Override protected final void run() throws Exception { while (isRunning() || !queue.isEmpty()) { E action = queue.poll(100, TimeUnit.MILLISECONDS); doExecute(action); } logger.debug("Service is not running and queue is empty, returning from run()"); } private void doExecute(@Nullable E action) { try { if (action != null) { logger.debug("Executing {}", action); execute(action); } } catch (Exception e) { logger.debug("Error executing metrics action {}: {}", action, getRootCauseMessage(e)); if (failOnError) { logger.debug("Shutting down {} due to previous failure", this); queue.clear(); failed.set(true); if (verboseErrorOuput) throw Throwables.propagate(e); } } } protected final boolean hasFailed() { return failed.get(); } @Override protected final void shutDown() throws Exception { try { beforeShutDown(); // We want any problems with the before shutdown hook to prevent queue draining, so we handle that inside this try logger.debug("Shutting down queued execution service {}. Draining queue...", this); List remaining = Lists.newArrayListWithCapacity(queue.size()); queue.drainTo(remaining); for (E e : remaining) { execute(e); } checkState(queue.isEmpty(), "The queue should have been drained before shutdown"); } catch (Exception e) { logger.error("An error occurred during shutdown (error message: )", getRootCauseMessage(e)); } postShutDown(); } protected void beforeShutDown() throws Exception { } protected void postShutDown() throws Exception { } protected final void queue(E action) { checkNotNull(action); if (!QUEUE_AVAILABLE_STATES.contains(state())) { logger.debug("Dispatcher is not running, dropping action {}", action); } else if (isAsync()) { logger.debug("Queueing {}", action); queue.add(action); } else { doExecute(action); } } protected final void executeSynchronously(E action) { checkNotNull(action); if (!QUEUE_AVAILABLE_STATES.contains(state())) { logger.debug("Dispatcher is not running, dropping action {}", action); } else { doExecute(action); } } /** * Allow service to run non-asynchronously to allow unit testing of concrete implementations, without needing to * deal with timing issues. * * @return true if the service is asynchronous */ protected boolean isAsync() { return true; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy