package com.peterphi.std.guice.common.daemon;

import com.peterphi.std.threading.Timeout;
import org.apache.log4j.Logger;

public abstract class GuiceRecurringDaemon extends GuiceDaemon
{
	private static final Logger log = Logger.getLogger(GuiceRecurringDaemon.class);

	protected Timeout sleepTime;


	/**
	 * Creates a new Daemon; the Daemon will start once the guice object is fully constructed
	 *
	 * @param sleepTime
	 * 		the amount of time to sleep between calls to the  {@link #execute()} method
	 */
	protected GuiceRecurringDaemon(Timeout sleepTime)
	{
		this(true, sleepTime);
	}


	/**
	 * Creates a new Daemon; the Daemon will start once the guice object is fully constructed
	 *
	 * @param daemonThread
	 * 		true if the thread should be started as a daemon thread, otherwise false
	 * @param sleepTime
	 * 		the amount of time to sleep between calls to the  {@link #execute()} method
	 */
	protected GuiceRecurringDaemon(final boolean daemonThread, final Timeout sleepTime)
	{
		super(daemonThread);

		if (sleepTime == null || sleepTime.getMilliseconds() < 0)
			throw new IllegalArgumentException("Cannot provide a negative sleep time!");
		else
			this.sleepTime = sleepTime;
	}


	@Override
	public void run()
	{
		while (isRunning())
		{
			try
			{
				execute();
			}
			catch (Throwable t)
			{
				log.error("Ignoring exception in GuiceRecurringDaemon call", t);
			}

			// Sleep for the default sleep time
			sleep(sleepTime);
		}
	}


	/**
	 * Run one iteration of the daemon
	 *
	 * @throws Exception
	 * 		if an exception occurs (the exception will be logged but otherwise ignored)
	 */
	protected abstract void execute() throws Exception;
}

@@ -1452,24 +1452,538 @@
 );%0A%09%09%7D%0A%09%7D%0A%0A%0A
+%09/**%0A%09 * %3Cp%3ECalled when the %7B@link #execute()%7D method throws an exception. This method can be overridden by subclasses to record%0A%09 * exception details or to take remedial action. By default it will log the exception at the ERROR level.%3C/p%3E%0A%09 * %3Cp%3E%3Cb%3ENote: Any exception thrown by this method will cause the thread to terminate%3C/b%3E%3C/p%3E%0A%09 *%0A%09 * @param t%0A%09 * %09%09the exception that was caught%0A%09 */%0A%09protected void executeException(Throwable t)%0A%09%7B%0A%09%09log.error(%22Ignoring exception in GuiceRecurringDaemon call%22, t);%0A%09%7D%0A%0A%0A
 %09/**%0A%09 * Run
@@ -2093,14 +2093,54 @@
  be 
-logged
+passed to %7B@link #executeException(Throwable)%7D
  but

allow GuiceRecurringDaemon instances to take some action if the execute method throws an exception