Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper way to schedule a task daily in C# .NET web application

I have an ASP.NET MVC app that let users store media like videos and photos.

The application also lets the users delete those media stored in the server. To do so i want to implement a "two steps" process in which first (when the media is selected to be deleted), the media entry at the database will get a timestamp that indicates that the entry has to be deleted in some time (a month for example); if that timestamp is not removed in that time, there should be a scheduled method that executes daily and checks if a media entry has a timestamp old enough to be deleted.

My question is about the scheduler: I've readed that there are some frameworks like FluentScheduler or Quartz.NET to implement that kind of jobs. Since the application is a web application deployed in IIS, i'm afraid to not use the proper way, framework or method to implement it. Since IIS could shutdown my application at any time and since the scheduled method would execute writes to DB and to the IO File system to delete the db entries and the physical files, it is vital to me that the method executes completely or does not execute at all, to keep the db consistent with the files stored at hd.

My first bet is for FluentScheduler, but i need to know if using frameworks like that is the best solution.

I know that this kind of questions are not welcome in StackOverflow. It is not an opinion question, i just want to read the solutions and select the one that best fits my requirements.

Here is some kind of pseudo-code of what would be inside the scheduled method:

using(ViewMediaDBUnitOfWork uw = new ViewMediaDBUnitOfWork())
        {
            var today = DateTime.Now.Date;

            List<Media> mediaToDelete = uw.MediaRepository.Get(m => (m.ToDelete - today).value.Days > 30);
            mediaToDelete.ForEach(m =>
            {
                try
                {
                    //Deletes from DB
                    uw.MediaRepository.Delete(m);
                    //Deletes the file
                    File.Delete(m.Path);
                    //If everything is ok, savechanges
                    uw.MediaRepository.SaveChanges();
                }
                catch(Exception e)
                {
                    LogManager.GetCurrentClassLogger().Error("Error deleting. " + m.Path, e);
                }                    
            });
        }
like image 256
MorgoZ Avatar asked Jul 18 '16 15:07

MorgoZ


1 Answers

If you are going to schedule a task, at a minimum you’d want to at least do it within the context of HostingEnvironment.QueueBackgroundWorkItem. This will register your work with the ASP.NET runtime. Though there are caveats. When ASP.NET recycles for whatever reason, it will notify the background work (by setting a CancellationToken) and it will then wait up to a specified period of time (I think 30 seconds) for the work to complete. If the background work doesn’t complete in that time frame, the work will be gone.

FluentScheduler and Quartz are good frameworks, but you should avoid scheduling work within the context of your ASP.NET application if you can avoid it (for the reasons stated above). You could create a service that that uses these frameworks to schedule jobs / recurring tasks outside of your application.

However, a more robust choice is to use a technology / framework like Hangfire which works in conjunction with some kind of reliable storage such as SQL Server, Redis, or MSMQ.

Hangfire is an open-source framework that helps you to create, process and manage your background jobs, i.e. operations you don't want to put in your request processing pipeline.

like image 155
William Xifaras Avatar answered Oct 17 '22 02:10

William Xifaras