views:

332

answers:

4

I have a Grails app that has some computationally intensive optimizations with a running time of ~5 minutes (perhaps more). Currently, I'm doing these in the main request thread, i.e. it takes 5 minutes for the request to return. It works, but is of course horrible from a usability perspective.

So what's the best way to implement this in an asynchronous way? I assume a ThreadPoolExecutor would have to be involved, but how do I start and access it? Can I model it as a Grails Service? Or a Job (seems that those are only meant for recurring jobs though)?

Also, what's the best way to handle job status? Via a a flag or perhaps an entire new class in the DB? Have the browser show a spinner and keep polling until the status changes?

+2  A: 

There is a grails plugin background-thread which might be just what you are looking for.

Of course it would be possible to roll your own thread pooling or use existing Java stuff.

Sean A.O. Harney
+2  A: 

I'd use the grails JMS Plugin for this.

Then you can create a service with an "onMessage" method that interacts automatically with an underlying jms provider (like OpenMQ or ActiveMQ.

It makes this kind of thing pretty easy.

Ted Naleid
What would be the benefit compared to simply using a ThreadPoolExecutor? It sounds a lot more complex than that.
Michael Borgwardt
It is definitely more complex. The main benefits would be around some of the monitoring and polling capabilities that your question alluded to some requirements around. Lots of this kind of stuff is solved in the JMS world, but there is more setup/maintenance around it. It really depends on how "enterprisey" your requirements are. If you don't care much about monitoring or what happens if your container goes down while it's processing, then I'd do something simpler. Just one potential option.
Ted Naleid
Ah, I see. Well, the only monitoring I need is for a user waiting for a specific job to complete. I don't need transactional safety either, so I'll go for a simpler approach.
Michael Borgwardt
A: 

In the spirit of the "simplest thing that could possibly work" I have done something like this as a simple service. (Of course it might be too simple, criticism is welcomed).

I used Groovy's feature that Thread has a static start method that takes a closure. See http://groovy.codehaus.org/groovy-jdk/java/lang/Thread.html

I implemented a method on a service that looked like:

synchronized def runThreadedTask() {
  if(taskRunning) { 
    // taskRunning is defined as a service level flag to monitor job status
    // if we are already running the task just return
    return;
  }

  Thread.start {
    taskRunning = true
    // do job processing here
    taskRunning = false
  }
}
Alex Stoddard
+1  A: 

grails install-plugin background-thread

def backgroundService

backgroundService.execute("doing my thing", {

// do work here

});