ASP MVC 3: run cron jobs without affecting the user - asp.net-mvc

For my site I need to have:
logging of the action & render time
log the visit of a certain product
from time to time agregate votes
from time to time send newsletter
from time to time post on social networks
My approach to this was to create a global filter and OnResultExecuted I do the check and the action that are needed.
I have some questions:
when OnResultExecuted is running did the user received the rendered page and basically is not waiting for anything else? Am I blocking it?
it is a good idea in OnResultExecuted to start a new thread for this
jobs?
is this approach ok in ASP MVC 4

According to MSDN this method is called after the response is written (http://msdn.microsoft.com/en-us/library/system.web.mvc.controller.onresultexecuted(v=vs.108).aspx) so you will not be blocking the response.
Apart from the first two points (logging of actions and logging of visits), the others may take considerable resources based on the size of the task.
My advice is to override OnResultExecuted for the first two tasks and use a windows service (can easily be written in C#) to do the others in the background. This way you can use less costly clr threads instead of iis worker threads.
Running the time/resource consuming tasks in the background will add scalability to your web application
Hope this helps

Related

Background task / job / process, in asp.net MVC 3

I don't know where to start or what to use to solve this 2 problems:
I have a User model and a Event model (football match, karts race, etc). And I want that when a user creates a new Event send and email to other users.
I need "something" that checks let's say every 15 minutes, delete all the Events that are already over (Example: Events from yesterday) from the database.
I know that in Ruby on Rails, there are Observers and Background Workers, there is something like that in MVC3 ? or there are other ways of accomplish that ?
Those kind of tasks are better suited to be done from a separate process such as a Windows service. You should avoid using background tasks in your web applications.
I would suggest using Quartz.net as a robust solution because of being full-featured, open source job scheduling system that can be used from smallest apps to large scale enterprise systems.
More Info: Job Scheduler with asp.net mvc
It's true that there are risks. But sometimes we have to take this option, especially when we are on a tight schedule to implement a job queue. If you are not familier with windows services, you need to learn about those things.
Following worked for me, (.NET 4.5.2). Once I invoke InitiateLongRunningProcess controller, it initiate a longrunning process and return to view without waiting for the longrunning job.
public ActionResult InitiateLongRunningProcess(Emails emails)
{
if (ModelState.IsValid)
{
HostingEnvironment.QueueBackgroundWorkItem(ct => LongRunningProcessAsync(emails.Email));
return RedirectToAction("Index", "Home");
}
return View(user);
}
Read this great article from Hanselman HowToRunBackgroundTasksInASPNET
Pretty late but you should consider lookint at http://hangfire.io/. Its an amazing library and provides a full fletched UI to manage jobs :)

Logging large volumes of actions in a production MVC/SQL application

We are happy users of the ASP.NET MVC framework and SQL Server, currently using LINQ-to-SQL. It serves our needs well with a consumer-facing application with about 1.4 million users and 2+ million active uniques per month.
We are long overdue to start logging all user actions (views of articles, searches on our site, etc.) and we're trying to scope out the right architecture to do so.
We'd like the archiving system to be its own entity, and not part of the main SQL cluster that stores the production articles and search engine. We'd like it to be its own SQL cluster, starting out with just one box initially.
To simplify the problem, let's say we just want to log the search terms that these millions of users enter into our site for the month, and we want to do so in the least cycle-intensive-way possible.
My questions:
(1) Is there an asynchronous way to dump the search terms to a remote box? Does LINQ support async for this?
(2) Would you recommend building up a cache of say 1,000 (userId, searchTerm, date) logging items in a RAM cache, and then flushing those at intervals to the database? I assume this method would cut down on open/close connections.
Or am I thinking about this entirely wrong? We'd like to strike a balance between ease of implementation and robustness.
1)Sure you can, there are different solution to achieve it. Linq is not the instrument you need.
2)There should not be any major improvement by doing it, the "logging" will be triggered only when a search is performed. You will end up with two calls instead of one, not a big deal.
A suggestion is to use AOP
You can create a clean and separate layer for logging using Postsharp (there are other alternatives though). You will then decorate your actions with the required logging attribute only when you need to trace what is passed to the action.
Main advantages with this approch are :
Logging logic doesn't reside inside your code (you don't need to change your methods code) but is executed before/after your method.
Clean separation of the Aspect from the target method.
You can easily switch on/off the aspects
AOP is a common practice specially when it comes to behavior that can be added to more than one method, like logging, authentication and so on. And yes it can be used in an async way.
1)I would suggest you to create an HttpModule that "catch" all the search terms used by the users. How and where you will dump those information(you said you will use a SQL box) it's another matter which is outside the scope of the module which should just catch the Search tems.
Then you can create a component that contains the login to store those information using Async call(or even a third part component like Log4Net )
2) if you want create a kind of batch insert caching all the information you need to store and at some point dump them on SQL I would use MSMQ or any other technology that support the Reliability: I think you want loose all those information in the case of a system-crash,etc

Struts2 and multiple active wizards / workflows

I'm currently working on a Struts2 application that integrates a wizard / workflow in order to produce the desired results. To make it more clear, there is a business object that is changed on three different pages (mostly with AJAX calls). At the moment I'm using a ModelDriven action (that's extended by all the actions working with the same business object) coupled with the Scope interceptor. While this works okay if the user is handling data for only one business object at a time, if the user opens the wizard for different objects in multiple tabs (and we all do this when we want to finish things faster) everything will get messy, mostly due to the fact that I have only one business object stored in the session.
I have read a few articles about using a Conversation Scope Interceptor (main article) and about using the Scope plug-in (here). However, both approaches seem to have problems:
the Conversation Scope Interceptor doesn't auto-expire the conversations, nor does it integrate properly with Struts2;
the Scope plug-in lacks proper documentation and the last build was made in 2007 (and actually includes some of the ideas written by Mark Menard when he defines his Conversation Scope Interceptor, though it doesn't use the same code).
Spring's WebFlow plug-in seems a bit too complex to be used at the moment. I'm currently looking for something that can be implemented in a few hours time, though I don't mind if you can suggest something that works as needed, even if it requires more time than I'd currently want to spend on this now.
So, seasoned Struts2 developers, what do you suggest? How should I implement this?
Okay this isn't a fully baked idea. But seeing as no else has provided anything, here is what I would start with.
1) See if you can move the whole flow into a single page. I'm a big believer in the less pages is better approach. It doesn't reduce complexity for the application at all, but the user generally finds the interface a lot more intuitive. One of the easiest ways to go about this is by using the json plugin and a lot of ajax calls to your json services.
2) If you must transition between pages (or simply think it is too much client side work to implement #1) then I'd look to the s:token tag. The very first page to kick off a flow will use this tag, which will create a unique value each invocation. You will store a map in your session of model objects. An action will need to be provided with a model by looking it up from the session.
There are a couple challenges with #2. One how do you keep the session from getting too many domain objects? a) Well it might not matter, if the session is set to say six hours you can be rather sure that over night they will get cleared up. b) provided a self management interface which can get/set/list objects in the session. It might be what you thought of at first but it would let a worker do a certain amount and then stop and work on another. If the unit of work has some meaningful name (an invoice number or whatever) it could be quite useful.
A little more sophistication would be to move the model objects out of the session and into the service layer. At which point when inserted you would set an insertion time. You would probably need a manager to hold each type of model object and each manager would have a daemon thread that would periodically scan the map of domain objects and clean out expired ones.
You can figure out more complicated system by kicking a flow off with a token and then using another token on each page. "flowId" and "currentPageId" respectively, then you can graph allowable transitions.
Mind you at this point spring web flow is starting to look pretty good.
There is now a conversation plugin for Struts2 that achieves all these goals with very little work required by the developer: http://code.google.com/p/struts2-conversation/
It has:
-nested conversations
-cleanup of dead conversations
-convention over configuration with annotations and naming conventions
-inherited conversations
-fully integrated with Struts2
-the conversation scope can also be used by Spring IoC container-managed beans
Hope it helps somebody.

Using Grails/Spring Web Flows in Rails

What's the best way to handle a conversation-based web flow in Rails? I'm wondering if there is anything similar to http://grails.org/doc/1.0.x/guide/single.html#6.5%20Web%20Flow
A web flow is a conversation that spans multiple requests and retains state for the scope of the flow. A web flow also has a defined start and end state.
Web flows don't require an HTTP session, but instead store their state in a serialized form, which is then restored using a flow execution key that Grails passes around as a request parameter. This makes flows far more scalable than other forms of stateful application that use the HttpSession and its inherit memory and clustering concerns.
Web flow is essentially an advanced state machine that manages the "flow" of execution from one state to the next. Since the state is managed for you, you don't have to be concerned with ensuring that users enter an action in the middle of some multi step flow, as web flow manages that for you. This makes web flow perfect for use cases such as shopping carts, hotel booking and any application that has multi page work flows.
I just started looking into this question myself, but from the perspective of DRYing up view code. Not finding much, but there is:
https://github.com/jcoglan/action_flow which may take some rejigging for newer Rails
http://rubyforge.org/frs/?group_id=2769 which has no docs and looks alpha
The age and activity levels on each project lead me to believe they've been abandoned.
Wiring up flows as point-to-point links of imperative calls with routes/controllers/actions/views that make fixed assumptions about where they fall in the chain (or worse, entrain lots of conditionals to deal with different flows), is certainly one way I've seen it done. Still wondering if that is the preferred stock in trade in the Rails world, or if there are other idioms that supplant it that I just don't know about.

ASP.NET MVC Repeating Task

I need to run a task repeatedly on an ASP.NET MVC site; it needs to run every time interval (Interval doesn't matter).
I achieved this by setting a background thread from the Global.asax.cs Application_Start which runs the task, sleeps for time interval and then runs again....and again.
While this works it doesn't seem like the right way to do this, seems a bit hacky.
So then I replaced it with a Timer object, this doesn't work reliably - seems others have had problems with it as well - so I'm not going to use this.
This needs to run in the MVC site, it is used for pulling jobs from a queue and rendering them from the Views ready for emailing.
I thought about using the ThreadPool and getting the previous job to leave another job on it's way out but because these can be long running jobs I've read that this can end up not leaving enough threads to deal with web requests through starvation.
Before sticking with the original thread method I thought I'd ask if anyone else knows a better way of doing this.
I hope this makes sense. Effectively what I'm trying to achieve is a heartbeat. Something to act as the consumer part of the producer/consumer pattern in an MVC site.
Stackoverflow itself uses (or at least used to use) a cunning way of doing this. See here: https://blog.stackoverflow.com/2008/07/easy-background-tasks-in-aspnet/
In brief, you do this:
At startup, add an item to the HttpRuntime.Cache with a fixed
expiration.
When cache item expires, do your work, such as WebRequest or what have
you.
Re-add the item to the cache with a fixed expiration.
I know you've stated that:
This needs to run in the MVC site
However I think this is the wrong place for doing what you're trying to acheive.
Personally I'd set this up as a Windows Service and have the service check the database, compile the email as required, and add the email to a queueing service. The email service would then be seperate from this and would dispatch the emails at some interval.
What's stopping you at present from using another method than embedding this in your MVC site?

Resources