AlexanderTheGreat
AlexanderTheGreat

Reputation: 23

How to in case of timeout to execute method again and again until it completes successfully?

I have asp.net application. All business logic in business layer.

Here is the example of the method

public void DoSomething()
{
        PersonClass pc = new PersonClass();

        pc.CreatePerson();
        pc.AssignBasicTask();
        pc.ChangePersonsStatus();
        pc.CreateDefaultSettings();    
}

what happens once in a while, one of the sub method can timeout, so as a result the process can be incompleted.

what I think in this case to make sure all steps completed properly is

public void DoSomething()
    {
            PersonClass pc = new PersonClass();
            var error = null;

            error =  pc.CreatePerson();

            if(error != timeout exception)                  
             error = pc.AssignBasicTask();
            else
              return to step above

            if(error != timeout exception)
              error = pc.ChangePersonsStatus();
            else
              return to step above

            if(error != timeout exception)
              error = pc.CreateDefaultSettings();
            else
              return to step above    
    }

but it's just an idea, more then sure it's a proper way how to handle this.

Upvotes: 2

Views: 581

Answers (3)

CodingGorilla
CodingGorilla

Reputation: 19862

You have it pretty close to correct in your psuedo-code, and there a lot of ways to do this, but here is how I would do it:

PersonClass pc = new PersonClass();
while(true)
   if(pc.CreatePerson())
      break;

while(true)
   if(pc.AssignBasicTask())
      break;

This assumes that your methods return true to indicate success, false to indicate a timeoiut failure (and probably an exception for any other kind of failure). And while I didn't do it here, I would strongly recommend some sort of try counting to make sure it doesn't just loop forever and ever.

Upvotes: 2

driis
driis

Reputation: 164341

Of course, this can be done more or less elegantly, with different options for timing out or giving up - but an easy way to achieve what you want, would be to define a retry method which keeps retrying an action until it succeeds:

public static class RetryUtility 
{
    public T RetryUntilSuccess<T>(Func<T> action) 
    {
        while(true) 
        {
            try 
            {
                return action();
            }
            catch 
            {
                // Swallowing exceptions is BAD, BAD, BAD. You should AT LEAST log it.
            }
        }
    }

    public void RetryUntilSuccess(Action action) 
    {
        // Trick to allow a void method being passed in without duplicating the implementation.
        RetryUntilSuccess(() => { action(); return true; });
    }
}

Then do

    RetryUtility.RetryUntilSuccess(() => pc.CreatePerson());
    RetryUtility.RetryUntilSuccess(() => pc.AssignBasicTask());
    RetryUtility.RetryUntilSuccess(() => pc.ChangePersonsStatus());
    RetryUtility.RetryUntilSuccess(() => pc.CreateDefaultSettings());   

I must urge you to think about what to do if the method keeps failing, you could be creating an infinite loop - perhaps it should give up after N retries or back off with exponentially raising retry time - you will need to define that, since we cannot know enough about your problem domain to decide that.

Upvotes: 2

Dmitry Samuylov
Dmitry Samuylov

Reputation: 1564

Use a TransactionScope for to make sure everything is executed as a unit. More info here: Implementing an Implicit Transaction using Transaction Scope

You should never retry a timed out operation infinitely, you may end up hanging the server or with an infinite loop or both. There should always be a threshold of how many retries is acceptable to attempt before quitting.

Sample:

using(TransactionScope scope = new TransactionScope())
{
   try
   {
      // Your code here

      // If no errors were thrown commit your transaction
      scope.Complete();          
   }
   catch
   {
      // Some error handling
   }
}

Upvotes: 0

Related Questions