You are currently browsing legacy 3.0 version of documentation. Click here to switch to the newest 4.2 version.

We can help you with migration to the latest RavenDB

Contact Us Now
see on GitHub

Plugins: Tasks

Another type of plugins gives us the ability to perform various actions during server/database startup process or enables us to perform actions periodically. For these instances we have introduced two interfaces and one abstract class.

public interface IStartupTask
{
	void Execute(DocumentDatabase database);
}

public interface IServerStartupTask
{
	void Execute(RavenDbServer server);
}

public abstract class AbstractBackgroundTask : IStartupTask
{
	private static readonly ILog log = LogManager.GetCurrentClassLogger();

	public DocumentDatabase Database { get; set; }

	public void Execute(DocumentDatabase database)
	{
		Database = database;
		Initialize();
		Task.Factory.StartNew(BackgroundTask, TaskCreationOptions.LongRunning);
	}

	protected virtual void Initialize()
	{
	}

	int workCounter;
	public void BackgroundTask()
	{
		string name = GetType().Name;
		WorkContext context = Database.WorkContext;
		while (context.DoWork)
		{
			bool foundWork = false;
			try
			{
				foundWork = HandleWork();
			}
			catch (Exception e)
			{
				log.ErrorException("Failed to execute background task", e);
			}
			if (foundWork == false)
			{
				context.WaitForWork(TimeoutForNextWork(), ref workCounter, name);
			}
			else
			{
				context.UpdateFoundWork();
			}
		}
	}

	protected virtual TimeSpan TimeoutForNextWork()
	{
		return TimeSpan.FromHours(1);
	}

	protected abstract bool HandleWork();
}

where:
* IStartupTask can be used to implement a task which will be started during database initialization.
* IServerStartupTask can be used to implement a task which will be started during server initialization.
* AbstractBackgroundTask is a base for all periodic tasks.

Example - Send email when server is starting

public class SendEmailWhenServerIsStartingTask : IServerStartupTask
{
	public void Execute(RavenDbServer server)
	{
		MailMessage message = new MailMessage("ravendb@myhost.com", "admin@myhost.com")
		{
			Subject = "RavenDB server started.",
			Body = "Start at: " + DateTime.Now.ToShortDateString()
		};

		using (SmtpClient smtpClient = new SmtpClient("mail.myhost.com"))
		{
			smtpClient.Send(message);
		}
	}
}

Example - Perform a cleanup task during database initialization

public class CleanupWhenDatabaseIsStarting : IStartupTask
{
	private const string SpecificDatabaseName = "Northwind";

	public void Execute(DocumentDatabase database)
	{
		if (database.Name != SpecificDatabaseName)
			return;

		using (CancellationTokenSource cts = new CancellationTokenSource())
		{
			bool stale;
			IEnumerable<string> queryResults = database.Queries.QueryDocumentIds(
				"Notifications/Temp",
				new IndexQuery(),
				CancellationTokenSource.CreateLinkedTokenSource(database.WorkContext.CancellationToken, cts.Token),
				out stale);

			foreach (string documentId in queryResults)
			{
				database.Documents.Delete(documentId, null, null);
			}
		}
	}
}

Example - Perform a cleanup task every six hours

public class RemoveAllTemporaryNotificationsTask : AbstractBackgroundTask
{
	protected override bool HandleWork()
	{
		QueryResultWithIncludes queryResults = Database.Queries.Query("Notifications/Temp", new IndexQuery(), Database.WorkContext.CancellationToken);
		foreach (RavenJObject document in queryResults.Results)
		{
			string id = ((RavenJObject)document["@metadata"]).Value<string>("@id");
			Database.Documents.Delete(id, null, null);
		}

		return true;
	}

	protected override TimeSpan TimeoutForNextWork()
	{
		return TimeSpan.FromHours(6);
	}
}