"If at first you don't succeed, try, try again."
We have all encountered situations where we need to attempt an operation, with full knowledge that the operation might very well fail. And if it does, we should retry it. Usually after a delay, usually with a maximum number of retries.
Today's anonymous submitter inherited a site-scraping application. Already, we're in dangerous territory- site-scraping is inherently fragile, dangerous code. It's more dangerous, of course, when it's written by the culprit behind this:
public void ScrapeASite()
{
try
{
//Some setup work
var doc = HtmlWeb().Load(url); //a synchronous call
//use the returned data to do stuff
}
catch(Exception e)
{
//recurse, and hope the next request for the same domain
//gets a different host from the load balancer
try
{
Console.WriteLine(DateTime.Now + " " + BAD SERVER!!! " + e.Message);
}
catch(Exception)
{ }
//Rinse Repeat
ScrapeASite();
}
}
The Load
method getting called is synchronous, which certainly makes this code simpler, even if it's probably not the best idea. If what goes wrong is a timeout, you might be waiting quite awhile as your program hangs.
And when something does go wrong, we handle the exception.
I'm first delighted to see that Console.WriteLine
is wrapped in a try/catch. We can't be too careful, I suppose. We'll just swallow that exception, if it happens, and then we call ScrapeASite
. Recursively.
This is C#. The .NET runtime does support tail call optimizations, but the compiled Intermediate Language needs to contain certain op-codes to enable it. The F# complier emits those op-codes. The C# compiler does not.
So if the site goes down, or the network is out, or what have you, we start sending request after request by piling frame after frame up on the call stack. The good news is that this method probably only uses a relatively small amount of space on the call stack, which means you can do this many many times before getting a StackOverflowException
.
Perhaps the person responsible for this code should try, try, try a little harder to catch their own mistakes.