/* * Copyright 2014 the original author or authors. * * 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 net.kuujo.vertigo.io; import org.vertx.java.core.Handler; import org.vertx.java.core.Vertx; /** * Provides an interface for feeding outputs using a handler that will * be called whenever the given output is prepared to accept a single message. * * @author <a href="http://github.com/kuujo">Jordan Halterman</a> * * @param <T> The output type. */ public class Feeder<T extends Output<T>> { private static final long DEFAULT_FEED_DELAY = 10L; private final T output; private final Vertx vertx; private Handler<T> feedHandler; private boolean fed = true; private long feedDelay = DEFAULT_FEED_DELAY; private long feedTimer; private final Handler<Void> feedRunner = new Handler<Void>() { @Override public void handle(Void _) { int before = output.size(); feedHandler.handle(output); int after = output.size(); fed = after > before; doFeed(); } }; private final Handler<Long> recursiveRunner = new Handler<Long>() { @Override public void handle(Long timerID) { fed = true; doFeed(); } }; /** * Creates a new feeder. * * @param output The output to which to feed messages. * @return A new feeder. */ public static <T extends Output<T>> Feeder<T> createFeeder(T output) { return new Feeder<T>(output); } public Feeder(T output) { this.output = output; this.vertx = output.vertx(); } /** * Sets a feed handler on the feeder. * * @param handler A handler to be called each time a message should be * fed to the feeder. * @return The feeder. */ public Feeder<T> feedHandler(Handler<T> handler) { this.feedHandler = handler; return this; } /** * Sets the period the feeder will wait before calling the feed handler again * if the feed handler is called but no messages are produced. * * @param feedDelay The feed delay in milliseconds. * @return The feeder. */ public Feeder<T> setFeedDelay(long feedDelay) { this.feedDelay = feedDelay; return this; } /** * Returns the period the feeder will wait after a failed feed handler call. * * @return The feed delay. Defaults to <code>10</code> milliseconds. */ public long getFeedDelay() { return feedDelay; } /** * Starts the feeder. */ public void start() { doFeed(); } /** * Feeds the next message. */ private void doFeed() { if (fed && !output.sendQueueFull()) { fed = false; vertx.runOnContext(feedRunner); } else { feedTimer = vertx.setTimer(feedDelay, recursiveRunner); } } /** * Stops the feeder. */ public void stop() { if (feedTimer > 0) { vertx.cancelTimer(feedTimer); } } }