tags:

views:

89

answers:

6

Hi

I wondering would this work. I have a simple C# cmd line application. It sends out emails at a set time(through windows scheduler).

I am wondering if the smtp would say fail would this be a good idea?

In the smtpException I put thread that sleeps for say 15mins. When it wakes up it just calls that method again. This time hopefully the smtp would be back up. If not it would keep doing this until the smpt is back online.

Is some down side that I am missing about this? I would of course do some logging that this is happening.

+1  A: 

This is not a bad idea, in fact what you are effectively implementing is a simple variation of the Circuit-Breaker pattern.

The idea behind the pattern is the fact that if an external resource is down, it will probably not come back up a few milliseconds later. It might need some time to recover. Typically the circuit breaker pattern is used as a mean to fail fast - so that the user can get an error sooner; or in order not to consume more resources on the failing system. When you have stuff that can be put in a queue, and does not require instant delivery, like you do, it is perfectly reasonable to wait around for the resource to become available again.

Some things to note though: You might want to have a maximum count of retries, before failing completely, and you might want to start off with a delay less than 15 minutes.

driis
The Circuit-Breaker pattern is to stop an overload of an external service. What he has here is the "If it does not work try again later because somehow some external force might have fixed something pattern" -1
Romain Hippeau
@Romain, and that "external force" might actually have fixed the problem. The force being a network technician, or perhaps the SMTP was in fact down because it was overloaded. I agree that it shouldn't be an infinite loop - but rather retry the transaction at a later point in time.
driis
I'll remove the -1. I just hate people coming up with patterns everywhere and trying to show-horn them into every line of code. Edit your answer with something - required for counter to reset.
Romain Hippeau
A: 

Infinite loops are always a worry. You should set it up so that it will fail after N attempts, and you definitely should have some way to shut it down from the user console.

Failure is not such a bad thing when the failure isn't yours. Let it fail and report why it failed.

dthorpe
Ya I was thinking of a counter. How would I implement one? How would you shut it down from the console I would think they would just terminate the console.
chobo2
Counter would be fine, you can just put the sleep/call pair inside a loop and bail if the count is exceeded. You might also extend the wait time each time (exponential backoff), since if it isn't "fixed" in the first 5 minutes it probably won't be fixed in the next 5 minutes. This is common in Ethernet network collision detection and resend, for example. To support shutting down the long-waiting thread, add some code in the loop to check for console input, or check for a global boolean flag that says "Forget it, go home." Set the flag from your main thread in response to user input.
dthorpe
I don't get the sleep/call pair like if I call the method again won't it not be in the 4 loop anymore?
chobo2
pseudocode: function mysend() { for (int count = 4; count > 0; count--) { try { send(msg); break; } catch { logit(); sleep(n); } } }
dthorpe
A: 

Your choices are limited. Assuming that it is just a temporary condition and that it has worked at some point. The only thing you can do is notify of a problem, get somebody to fix it and then retry the operation later. The only thing you need to do is safeguard the messages so that you do not lose any.

Romain Hippeau
A: 

If you stick with what you got watchout for concurrency, perhaps a named mutex to ensure only a single process is running at a time.

I send out Notifications to all our developers in a similar fashion. Only, I store the message body and subject in the database. After a message has been successfully processed then I set a success flag in the database. This way its easy to track and report errors and retries are a cakewalk.

P.Brian.Mackey
+1  A: 

Exponential back-off is the common choice here I think. Like the strategy that TCP uses to try to make a connection: double the timeout on each failed attempt. Prevents your program from flooding the event log with repeated failure notifications before somebody notices that something is wrong. Which can take a while.

However, using the task scheduler certainly doesn't help. You really ought to reprogram it so your program isn't consuming machine resource needlessly. But using the ITaskService interface from .NET isn't that easy. Check out this project.

Hans Passant
A: 

Hi -

I would strongly recommend using a Windows Service. Long-running processes that run in the background, wait for long periods of time and need a controlled, logged, 'monitorable' lifetime: it's what Windows Services do.

Thread.Sleep would do the job, but if you want it to be interruptable from another thread or something else going on, I would recommend Monitor.Wait (MSDN ref). Then you can run your process in a thread created and managed by the Service, and if you need to stop/interrupt, you Monitor.Pulse on the same sync object and the thread will come back to life.

Also ref:

http://stackoverflow.com/questions/3198781/best-architecture-for-a-30-hour-query/3198817#3198817

Hope that helps!

Kieren Johnstone