Reputation: 2424
I have a C# console app that I would like to keep running, even when its database crashes. In that case it should poll the database to see when it comes back online, and then resume operation. I have this code for it, that I don't like:
public static T Robust<T>(Func<T> function)
{
while (true)
{
try
{
return function();
}
catch (GenericADOException e)
{
Console.WriteLine("SQL Exception. Retrying in 10 seconds");
Thread.Sleep(10000);
}
}
}
[...]
N.Robust(() => Session.CreateCriteria(typeof(MyEntity)).List());
The problem is that I have to insert that pesky N.Robust
construct everywhere which clutters the code. Also, I run the risk of forgetting it somewhere. I have been looking into using NHibernate's EventListeners or Inceptors for it, but haven't been able to make it work. Do I really have to fork NHibernate to make this work?
Update Alright, so I've been able to overcome one of my two issues. By injecting my own event listeners I can at least ensure that all calls to the database goes through the above method.
_configuration.EventListeners.LoadEventListeners
= new ILoadEventListener[] { new RobustEventListener() };
[...]
public class RobustEventListener : ILoadEventListener
{
public void OnLoad(LoadEvent e, LoadType type)
{
if (!RobustMode)
throw new ApplicationException("Not allowed");
}
}
I am still left with a cluttered code base, but I think it's a reasonable price to pay for increasing service uptime.
Upvotes: 1
Views: 144
Reputation: 300589
One archtecturial approach to tolerate database downtime is to use a queue (client side and/or server side). For reads of static or largely static data, cache on the client side with an expiry window (say 15 - 30 minutes).
This is non-trivial if you have complex database transactions.
Sleeping like you propose, is rarely a good idea.
Another option (used mainly in occasionally connected applications) is to use Database Replication. Using a RDBMS with replication support (Sql Server, for example), have your application always talk to the local DB, and let the replication engine deal with synchronization with the remote database automatically when the connection is up. This will probably introduce the issue of conflict management/resolution.
Upvotes: 5