How to wait 24hrs before completing an async task? - c#

I'm making an MVC app with the .NET Framework and in one of my controllers I call an async task that sends an e-mail to the signed in user.
This task is called upon when the user clicks a specific checkbox and the e-mail is meant to work as sort of reminder.
The entire task works as intended (the user gets an e-mail when the checkbox is checked), but I need it to wait 24 hours before actually sending the e-mail, as it is a reminder.
Currently the e-mail is sent right away, how can I delay the completion of my "e-mail task", while the code continues?

Use a library like Hangfire which lets you schedule background jobs and backs them with persistent storage.
You can then easily schedule a job like:
BackgroundJob.Schedule(
() => SendEmail("user#domain"),
TimeSpan.FromDays(1));

This is a classic X Y Problem. While it may be possible to make your system wait 24 hours you are creating a very fragile system that can be affected by app pool resets and server reboots.
Putting aside the possibility of an unexpected reboot, what happens when your maintenance cycle comes around and a scheduled reboot is going to happen? How many queued email reminders will you have that you can't do anything with?
The best approach for systems that don't immediately use their data is to buffer it through some form of storage scheme. It could be as simple as writing queued emails to files on the system, or something more robust like a database with a dedicated email sending service.
I have used a LOT of email sending systems over the years, and even for immediate sends we have used a database intermediary, with one dedicated email sending Windows service to produce and send the actual email. By centralizing the email production you not only get one place to maintain your email sending code, but you can also increase the durability of the whole system.
Bonus points if your database is part of a high availability cluster, as in this kind of system the database becomes the critical point. If it is then you're protected from any form of downtime other than a total network outage.

Let the Task wait for 24 hours before sending the mail.
await Task.delay(TimeSpan.FromHours(24));
Add this line in your async function bfore sending the email

Related

Bot Framework - Prevent GatewayTimeout for Long Operation

I've built a bot using botframework V4 for .Net that replies to user for both email and directline channels.
However, some of the request takes more than 15 seconds to complete, therefore I'd receive a GatewayTimeout error:
These requests are heavy (fetch some data from the database, fetch other data from another server via API calls, process the data, generate HTML and send them back to the user...) therefore nothing can be done to shorten the process.
I am aware that the gateway timeout delay is by design (the 15 seconds), but the problem is that the channel automatically retries the request after a small period of time and I end up receiving multiple emails for the same query (approx. 1 minute apart each).
I noticed as well that the directline replies are much faster than email ones (websocket vs SMTP), therefore this is mainly occurring with the email channel only. Noting that the emails are kept under 300KB as per this comment but can easily have a size close to this limit.
Therefore, is there a way to:
Increase the timeout delay?
Disable the automatic retries?
Or perhaps a certain workaround to prevent this issue?
Remember that your bot is a web app that exposes an HTTP endpoint, and every activity sent to your bot is an API call. Long-running API calls should be designed to return a response immediately and do their processing asynchronously. For example, consider the Recognize Text Computer Vision API. It just returns an Operation-Location where the actual result will become available later.
For bot Framework bots, all you have to do to send a message to the channel after the turn already ended is to send a proactive message. It's often also a good idea to design your bot to give the user an indication that the result is coming, such as by sending a preliminary "processing" message or a typing indicator, but that's probably unwanted in the case of the email channel. Eric Dahlvang explained this in the issue you linked to:
If the developer knows the response will take longer than 15 seconds, it is possible, depending on the channel, to start a separate thread to handle the long running process, return a valid status code on the receiving thread, and when the process finishes, send a proactive message from the background thread.

How to send email with delay?

I have ASP.NET MVC application and I need to send email in "X" minutes(for each user time is different) to user after he leaves the page.
How can I do it?
Http is stateless and the time response is sent execution of page is finished. You need an application that will be sending mail even when website is not accessed by some body for a significant time interval. You can put the mails that need to be send after an interval of time in the database. Another application could be a Windows service that will pool the database after fixed interval of time let's say 30 seconds and send the mails which have reached the send time.
The solution I would choose depends on the needed scale and reliability of the system you're building.
If it's a low scale (i.e. 1 server with not too many users at the same time), non mission-critical system (i.e. it's OK if from time to time some emails are not actually sent, for example if your server crashes), then the solution can be as simple as managing a queue in memory with a thread that would wake periodically to send emails to the users that recently left the page.
If you need to build something that would be very reliable and potentially have to send a very large number of emails in a short time, and if your system has to scale to a lot of machines, then you would want to build a solution based on a queue in some storage, where as many machines as needed would pick items and handle them. An API such as Windows Azure Queue Service can be a good fit for this if you need a really high scale and reliability.

Sending Email Notifications Immediately/On-Demand Versus Sending them Via Scheduler/Cron

In your opinion (hopefully one that is formed based on fact, as opposed to emotion) what is the better way to send out email notifications from a website?
For example, say User A on your site requests a friendship with User B, at which point you would generate an email to send to User B.
The question is - when is the best time to send the email? Immediately, as part of the same execution path, or scheduling the email as part of a batch?
Like I said, my question is rather generalized, so you can assume different architectures - one server dedicated to hosting, another dedicated to emailing, a single server, cloud hosting, etc... I'm curious about all answers, really.
As I see it:
With immediate emails, you get timely emails, but you can potentially bog down your server by sending too many emails should your website receive a lot of traffic. That being said, because you're not sending a batch of emails, they are all one-offs.
If you batch your emails and have a scheduled task or cron job pick them up and send them, your emails are not as immediate - so assume you decrease the interval so that batches are sent every 1 minute. The issue, as I see it is concurrency - if another batch kicks off before the first one completes, you could risk sending double emails if you don't appropriately flag or lock what you're sending.
In my personal experience, when I've had emails sent off immediately on a high traffic site, performance wasn't impacted too much, though a number of emails failed to send out.
Thoughts?
I would say definitely schedule them. There has to be a tollerance in terms of user request and server action on it, as if someone is able to make someone other a friend, it also (I hope) is able to refuse a friendship with the same person. If so, what if I make fast accept and refuse clicks on your website. ?
You have 2 options in this case, imo:
like a SO does, add some timing on user clicks (you can not accept and refuse in 2 seconds)
or you can, but at this point final message to the person whom friendship was accepted/requested is scheduled on the server and will send, say, after 30 minutes (or less, matter of architect choice)
Hope this helps.

Should I use thread.sleep or timer in my code?

I have the following code which send out SMS to the subscribers. However, some SMS were rejected from the SMSGateway because I'm sending too many SMS at one time. So I'm thinking to make a delay in between.
Sending out the SMS like this -
foreach (DataRow row in dt.Rows)
{
//Gets Subscriber number
smsSender.destinationNum = Convert.ToInt64(row["callerID"]);
foreach (DataRow articleRow in dtArticle.Rows)
{
//Gets SMS content
smsSender.smsMessage = articleRow["news"].ToString();
//Then send out the SMS
smsSendder.sendSMS();
}
}
Please advice because I have no experience with the threads and timers
It would depend on the architecture of the application.
Assuming this is a service-style app, with no user interface, that simply gets data out of the database and sends it to SMS, then Thread.Sleep(...) is fine.
If this app has a user interface, and you're running this SMS sending code on the UI thread, then Thread.Sleep(...) will block your UI. Actually, smsSender.sendSMS is probably already blocking your UI in this case!
Refactoring so that this code is off the UI thread is the answer. And you can do that simply by using a timer, although you will have to refactor the code so that the result set is cached in a local object and the timer iterates through the set sending one SMS out at a time.
In either case, I hope you don't have a lock on the database while you're sending SMSes.
Your question is tagged [asp.net] so I assume that you have a webpage that when requested will send a number of SMS messages (e.g. when a user presses a "submit" button or something similar in a HTML form).
In that case you can have multiple users requesting the webpage simultaneously. Also, you don't want to sleep in the thread serving the web page to the user. If you do that then there will be a delay where the user waits for the web page to respond while the SMS messages are sent.
I would suggest something like this:
When you need to send SMS messages you store the messages in a table in your database.
After storing new messages in the database you start a task (Task.Factory.StartNew) to process the SMS messages in the database.
You need to make sure that no more than one task is running in the ASP.NET application. Storing new messages in the database involves checking if the task is running and if not starting it.
The task will process all remaining messages in the database and send them using the appropriate delay (done by Thread.Sleeep).
When the task has sent an SMS message it is removed from the database.
This solution offloads the sending of messages to a background task that can be as slow as required and introduces persistence using the database to avoid loosing messages even if say the application pool is recycled.
Thread.Sleep is more appropriate, because it models better the waiting aspect.
Thread.Sleep() should be a good choice to delay calling to SMS gateway to prevent server reject your request.
I don't think it's Thread.Sleep() that's tying up the CPU.
Thread.Sleep seems bad design. Please refer http://blogs.msmvps.com/peterritchie/2007/04/26/thread-sleep-is-a-sign-of-a-poorly-designed-program/ about why Thread.sleep is a bad.
Timer are more accurate, Thread.Sleep is only guaranteed to wait at LEAST as long as the amount of time you specify (the OS may put it to sleep for much longer). .

What's the best way to send large amounts of email via C# Web page?

I have part of a project whereby I need to send 1 to up to 2000 emails from a webpage. One open source bug tracker used a Thread to send emails but it was riddled with bugs.
So just want to know if anyone has any ideas of how I can create a procedure that send up to 2000 emails a go?
I was told by one of my colleagues to leave it as one process (normal routine sending one email at a time) as it won't take long to process all the emails anyway. Doesn't seem right and I want to use threading... maybe I like complex routines?
[Extra]
I have something like:
foreach(string email in emailAddresses)
{
MailMessage mailMessage = new MailMessage();
mailMessage.To.Add(...)
...
SmtpClient client = new SmtpClient();
client.Send(mailMessage);
}
Use System.Net.Mail to send the messages; however you should use .NET 4 to avoid any connection issues, as there was a bug filed on the Connect website that will cause your messages to not get sent.
Don't use threading for three reasons:
Reason 1: A MTA is made to handle message retries and can handle failures. Your code may not be robust enough to handle this. System.Net.Mail is not able to do this out of the box.
Reason 2: If you do use threading, you will overwhelm the target SMTP server and it will block you. Most Windows SMTP relays have a default block of more than 15 (or 25?) concurrent connections.
If you're dealing with Exchange 2010, or 2007, then there is a throttling feature that gets activated if you send more than x messages per minute. This is a per MTA setting that will need to be adjusted to permit your situation.
Reason 3: The preferred way to do this is to have a dedicated IIS SMTP server (or Exchange...) that allows concurrent connections at high volume. Just use Sys.Net.Mail to hand the delivery task to the mail infrastructure. Not much is needed for a mail infrastructure. Just have a MTA that allows you to relay and it will "smart host" on your behalf out to the internet.
More questions on how to set up the MTA can be answered # serverfault.
However
You may want to use threading if your sending an email from an ASP.NET webpage... or will otherwise block the UI. Other than that, I don't see a need to run concurrent threads for the email generation task.
Lastly, if you're sending the same message to many recipients, you can either use a distribution list or append many target recipients to the same message.
You probably don't want to send 2000 emails on a thread that is servicing http requests. The user that submitted the request will be waiting for the server to respond until the emails send, and that's one less thread available for processing requests from other users. If you have many such requests it could drag down server performance.
Instead, I would post the request to a message queue, and have a seperate service process items from the queue and send emails.
Creating background threads in the asp.net app is another possibility, but then you end up in a situation where either:
You have to have your own task queue , separate from the one used by the normal thread pool.
Your email tasks are competing with, and potentially starving, the tasks for serving http requests.
That being said, there are deployment scenarios (a shared server, customer deployments) where the introduction of a second process is not desirable. If you don't have those constraints, however, I would go with the "separate process" because it's easier to scale your web site if it's focused on serving UI requests and leaves "fulfillment" tasks to a different service.
I think 2000 will take a long time (if it's a web page and the user is waiting for the page). It depends on your implementation, but you're doing this frequently you might want to have a "email thread" that's already been created. If there are no emails to send, then the thread can be suspended and not be consuming any resources. Then when the emails need to be sent you fill up an email queue with those emails and wake up the thread to start sending (if it is not already doing so).
If you're sending more than about 50 at a time, you need to contract out to a service that does this for you. Otherwise your messages will end up in people's spam folders.

Categories