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

com.almende.eve.transport.AsyncCallbackQueue Maven / Gradle / Ivy

There is a newer version: 3.1.1
Show newest version
package com.almende.eve.transport;

import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeoutException;

/**
 * Queue to hold a list with callbacks in progress.
 * The Queue handles timeouts on the callbacks.
 */
public class AsyncCallbackQueue {
	private static int TIMEOUT = 30000; // timeout in milliseconds
	// TODO: make the timeout customizable in eve.yaml
	
	/**
	 * Append a callback to the queue. 
     * 
	 * The callback must be pulled from the queue again within the 
	 * timeout. If not, the callback.onFailure will be called with a
	 * TimeoutException as argument, and is deleted from the queue.
	 * 
	 * The method will throw an exception when a callback with the same id
	 * is already in the queue. 
	 * @param id
	 * @param callback
	 * @throws Exception
	 */
	public synchronized void push(final String id, 
			AsyncCallback callback) throws Exception {
		if (queue.containsKey(id)) {
			throw new Exception("Callback with id '" + id + "' already in queue");
		}
		
		final AsyncCallbackQueue me = this;
		CallbackHandler handler = new CallbackHandler();
		handler.callback = callback;
		handler.timeout = new TimerTask() {
			@Override
			public void run() {
				AsyncCallback callback = me.pull(id);
				if (callback != null) {
					callback.onFailure(new TimeoutException(
						"Timeout occurred for request with id '" + id + "'"));
				}
			}
        };
		timer.schedule(handler.timeout, TIMEOUT);
		queue.put(id, handler);
	}

	/**
	 * Pull a callback from the queue. The callback can be pulled from the
	 * queue only once. If no callback is found with given id, null will
	 * be returned.
	 * @param id
	 * @return
	 */
	public synchronized AsyncCallback pull(String id) {
		CallbackHandler handler = queue.get(id);
		if (handler != null) {
			queue.remove(id);
			handler.timeout.cancel(); // stop the timeout
			return handler.callback;
		}
		return null;
	}
	
	/**
	 * Remove all callbacks from the queue.
	 */
	public void clear() {
		queue.clear();
		timer.cancel();
	}
	
	/**
	 * Helper class to store a callback and its timeout task
	 */
	private class CallbackHandler {
		public AsyncCallback callback;
		public TimerTask timeout;
	}
	
	private Map queue = 
			new ConcurrentHashMap();
	private Timer timer = new Timer(true);  // deamon timer
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy