We have a somewhat complex and long-running action method for which we'd like to show a progress bar. The javascript grid that we're using requires that saving and loading data be done in a single request (save first then load), and also requires us saving data to session.
Our initial thought was to just use an AsyncController, but the method obviously failed since it accesses (and saves to) session state. Since we cannot split up the action due to the javascript grid, is there any other option?
You could use a service bus and send a message to this. Granted this might be overkill for what you are doing but could be worth a look.
Search SO for rhinobus, masstransit or nservicebus. These would allow you to send a message asynchronously but you have to setup the application that subscribes to this message.
Related
When the client calls a Controller, a new Thread is created, which takes a long time. The View is intimidatingly returned to the user. The user should stay informed over the progress of the work, so SignalR is used.
How can send updates only to the user which called the Controller.
If I create a new Thread the HTTP Context get's lost, so I don't know how I can tell SignalR to which client it should send the information.
When you spawn your thread you should pass to it a user identifier, and then from the thread get a hub context and call something like:
var context = GlobalHost.ConnectionManager.GetHubContext<YourHub>();
context.Clients.User(userId).whatever();
on it. By default the user id would match the user name you get from your principal before calling the thread (so your HTTP context is still valid), but you can also check the IUserIdProvider interface for alternate ways of handling it.
If nature of long running operation allows it (ie you don't need to render any view or something specific to MVC), you can just implement your "long running work" inside the hub method (always use Task<T> and await to do that) and report progress back to client as shown here. Sample code is missing client side part. For that, take a look at this SO question.
This approach has another benefit. If your controller\action performing long running operation is using ASP.NET Session (which is default behavior), no other MVC actions\requests can run on server until the long running request finishes because of the Session lock - take a look here for more details. SignalR on the other side do not use Session by default so there is one less problem to worry about...
Oh BTW: Do not create your own Threads - its very inefficient. Use ThreadPool.QueueUserWorkItem or better Task<T> API...
I am working in a Rails application and below is the scenario requiring a solution.
I'm doing some time consuming processes in the background using Sidekiq and saves the related information in the database. Now when each of the process gets completed, we would like to show notifications in a separate area saying that the process has been completed.
So, the notifications area really need to pull things from the back-end (This notification area will be available in every page) and show it dynamically. So, I thought Ajax must be an option. But, I don't know how to trigger it for a particular area only. Or is there any other option by which Client can fetch dynamic content from the server efficiently without creating much traffic.
I know it would be a broad topic to say about. But any relevant info would be greatly appreciated. Thanks :)
You're looking at a perpetual connection (either using SSE's or Websockets), something Rails has started to look at with ActionController::Live
Live
You're looking for "live" connectivity:
"Live" functionality works by keeping a connection open
between your app and the server. Rails is an HTTP request-based
framework, meaning it only sends responses to requests. The way to
send live data is to keep the response open (using a perpetual connection), which allows you to send updated data to your page on its
own timescale
The way to do this is to use a front-end method to keep the connection "live", and a back-end stack to serve the updates. The front-end will need either SSE's or a websocket, which you'll connect with use of JS
The SEE's and websockets basically give you access to the server out of the scope of "normal" requests (they use text/event-stream content / mime type)
Recommendation
We use a service called pusher
This basically creates a third-party websocket service, to which you can push updates. Once the service receives the updates, it will send it to any channels which are connected to it. You can split the channels it broadcasts to using the pub/sub pattern
I'd recommend using this service directly (they have a Rails gem) (I'm not affiliated with them), as well as providing a super simple API
Other than that, you should look at the ActionController::Live functionality of Rails
The answer suggested in the comment by #h0lyalg0rithm is an option to go.
However, primitive options are.
Use setinterval in javascript to perform a task every x seconds. Say polling.
Use jQuery or native ajax to poll for information to a controller/action via route and have the controller push data as JSON.
Use document.getElementById or jQuery to update data on the page.
I am designing a Rails app that takes in requests, uses data within the request to call a 3rd party web service, process the reply and then sends out a response to the original requestor and also issues a PUT request to yet another service.
I am trying to wrap my head around how to design this Rails app as it's different from the canonical Rails structure.
The objects are Lists and Tasks. Each List has many Tasks, and each Task belongs to a List.
The request I would get is something like:
http://myrailsapp.heroku.com/v1/lists?id=1&from=2012-02-12&to=2012-02-14&priority=high
In this example I am requesting tasks from 2/12/2012 to 2/14/2012 with a high priority in List #1
I would then issue a 3rd party web service call like this:
http://thirdpartywebservice.com/v1/lists?id=4128&from=2012-02-12&to=2012-02-14&priority=high
As you can see some processing was done on the data (id was changed in this case)
The results are then sent back to the requestor and to another web service via PUT.
My question is, how do I set up the Rails app to handle these types of behaviors? How does the controller structure change? This looks like a good use case for queues, how do I distribute multiple concurrent requests among queues?
For one thing I don't need data persistence (data can be discarded after the response is sent out) and also data structure design is simplified. (I don't think I need ruby objects, simply dictionaries or hashes representing these would be lighter weight and quicker to implement)
Edit
So I broke down the work flow of the app into these components
Parse incoming request
Construct 3rd part web service request
Send 3rd party request
Enqueue a worker to process the expected response
Process the response once it arrives
Send the parsed result back as a response
Which of the standard ruby controllers handle each of these steps? What are the models needed besides Lists and Tasks?
You should still use a database because passing data to Resque is messy. Rather, you should store it in the database and then pass the id to the workers, fetch the data, commit any new data or delete the record. It's really up to you but this method is cleaner. You can also use a push service like faye to let the user know when the processing is complete.
If you expect to have many concurrent requests, I would recommend Sidekiq as it's less of a memory hog. Having 4-5 resque workers can already suck up about 512 MB. The controller structure should not change. Please comment on anything you need clarified and I'll be happy to update my answer.
EDIT
You would want to use a separate database store, such as Postgres. Not sure if it's important what models you need, but essentially this is what should be happening.
In your controller, create a Request object which contains the query params you want to query this 3rd party service with. Then enqueue a job to be handled by Sidekiq/Resque, let's call this ThirdPartyRequest and pass in the id of the Request object you just created as an argument. Then render a view here showing the Request object. Let's say that Request#response is still empty cause it hasn't been processed yet, so let the user know it's still processing.
A worker then handles your job ThirdPartyRequest. ThirdPartyRequest should then fetch the Request object and obtain the query params needed to contact the third party service. It does that then gets a Request. Update the Request object with this Request then save it.
class ThirdPartyRequest
def self.perform(request_id)
request = Request.find(request_id)
# contact third party service
request.response = ...
request.save
end
end
The user can continually refresh his page to check on his/her Request object. Once it gets updated with the response, they will know its completed. If you want the page to refresh automatically, look into faye/juggernaut/private_pub or a SaaS solution like Pusher.
I will build an Asp.net MVC 3 web page.
View: The view (web page) invoke about five Ajax(jQuery) calls against the methods, which return JsonResult, in a controller and render the results on the web page.
Control: The controller methods read a SQL Server 2008 database using EF4. Two of the SQL statements may take half a minute to execute depending on the server load.
I wish the users can at least see the contents returned from the quick controller/database calls as soon as possible. The page will not have a lot of users (maybe up to 15). Will the long run controller method calls block others if they are not asynchronous? Or is it irrelevant as long as the thread pool is big enough to handle the peak requests of the users?
From the user's view, loading the initial web page is synchronous, i.e. he has to wait until the server delivers the page. The Ajax requests however look asynchronous to him because he can already see part of the page.
From the server's view, everything is synchronous. There is an HTTP request that needs to be processed and the answer is either HTML, JSON or whatever. The client will wait until it receives the answer. And several requests can be processed in parallel.
So unless you implement some special locking (either on the web server or in the database) that blocks some of the requests, nothing will be blocked.
The proposed approach seems just fine to me.
Update:
There's one thing I forgot: ASP.NET contains a locking mechanism to synchronize access to the session data that can get into the way if you have several concurrent requests from the same user. Have a look at the SessionState attribute for a way to work around that problem.
Update 2:
And for an asynchronous behavior from the user's point of view, there's no need to use the AsyncController class. They where built for something else, which is not relevant in your case since only have 15 users.
Will the long run controller method calls block others if they are not asynchronous?
The first important thing to note is that all those controller actions should not have write access to the Session. If they write to the session whether they are sync or async they will always execute sequentially and never in parallel. That's due to the fact that ASP.NET Session is not thread safe and if multiple requests from the same session arrive they will be queued. If you are only reading from the Session it is OK.
Now, the slow controller actions will not block the fast controller actions. No matter whether they are synchronous or not. For long controller actions it could make sense to make them asynchronous only if you are using the asynchronous ADO.NET methods to access the database and thus benefit from the I/O Completion Ports. They allow you to not consume any threads during I/O operations such as database access. If you use standard blocking calls to the database you get no benefit from async actions.
I would recommend you the following article for getting deeper understanding of when asynchronous actions could be beneficial.
Trying to figure out a way where I can pass some data/fields from a web page back into my application. This needs to works on Windows/Linux/Mac so I can't use a DLL or ActiveX. Any ideas?
Here's the flow:
1. Application gathers some data and then sends it to a web page using POST that is either imbedded in the app or pops up a new IE window.
2. The web page does some services and then needs to relay the results back to the application.
The only way to do this that I can think of is writing the results locally from the page in a cookie or something like that and have the application monitor for a specific file in that folder.
Alternatively, make a web service that the application hits after passing control to the page and when the page is done the web service will return the data. This sounds like it might have some performance drawbacks.
Can anyone suggest any better solutions for this?
Thanks
My suggestion:
Break the processing logic out of the Web Page into a seperate assembly. You can then create a Web Service that handles all of the processing without needing to pass control over to a page.
Your application can then call the Web Service directly and then serialize the results and work with the data quite easily.
Update
Since the page is supplied by a third party, you obviously can't break anything out. The next best thing would be to handle the entire web request internal to your application (rather than popping a new Window).
With this method, you can get the raw HTTP response (and page markup) and work with it directly. You can then parse the Response stream and gather the required data from it.
During performing an HTTP request you should be able to retrieve the text returned by the page. For instance, if your HTTP POST was to hit a Java servlet, the doPost() method would be fired and you would then perform your actions, you could then use the PrintWriter object from the Response object (PrintWriter out = response.getWriter();) and write text back to the calling application. I'm not sure this helps?
The fact that
web page is hosted by a third party
and they need to be doing the
processing on their servers.
is important to this question.
I like your idea of having the app call a webservice after it passes the data to the third-paty web page. You can always call the webservice asynchronously if you're worried about blocking your application while waiting for results from this webservice.
Another option is that your application implements an XML-RPC server that can be called from the web page using PHP, Python or whatever you use to build the website
A REST server will do the job also...