Grails async processing with Promise

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

Grails async processing with Promise

Tamás Hauer-2
Hi,

In my grails app, a certain user action would start a task which should not be blocking. I am enclosing this task in a Promise, making use of grails' async feature. It seems to me though, that the onPromise or onError callbacks don't work as I think they should. Consider a freshly created grails application with a single controller:

package grailstest
import static grails.async.Promises.*

class AsyncController {
    def promise(long id) {
        def promise = task {
            println "promise start ${new Date().format("hh:mm:ss")}"
            if(id) sleep id
            println "promise finish ${new Date().format("hh:mm:ss")}"
        }
        promise.onComplete { result ->
            println "promise onComplete ${new Date().format("hh:mm:ss")}\n"
        }
        render "AsyncController ${new Date().format("hh:mm:ss")}\n"
    }   
}

Once this is running (grails run-app), I am calling the grails app:
  • with a typical timeout of 2s ($ curl http://localhost:8080/grails-start/async/promise/2000) which results in:
    promise start 05:08:17
    promise finish 05:08:19
    i.e. no sign of onComplete reached
  • with a very small timeout I often get an error:
    | Error 2014-02-05 17:09:27,665 [Actor Thread 16] ERROR gpars.LoggingPoolFactory  - Async execution error: null
    Message: null
        Line | Method
    ->>   61 | doCall    in org.grails.async.factory.gpars.GparsPromise$_onComplete_closure1
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    |     62 | run       in groovyx.gpars.dataflow.DataCallback$1
    |   1145 | runWorker in java.util.concurrent.ThreadPoolExecutor
    |    615 | run       in java.util.concurrent.ThreadPoolExecutor$Worker
    ^    724 | run . . . in java.lang.Thread
  • When I delete the line with sleep, it mostly works:
    promise start 05:10:29
    promise finish 05:10:29
    promise onComplete 05:10:29
  • Finally, of course, when I add a promise.get() to wait for completion before the controller returns, then onComplete works as expected (but the request is blocked, of course). For tiny timeouts I occasionally see the error above.

Could you give some advice if Promises are a viable/suggested route here and if I am doing anything wrong,

Cheers,

Tamás

-- 
Tamás Hauer
Genève, Switzerland 

smime.p7s (5K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Grails async processing with Promise

Graeme Rocher-2
With controllers you need to return the promise to the framework which
will execute it. You're not doing this here and instead returning a
synchronous response with the render method

On Wed, Feb 5, 2014 at 5:14 PM, Tamás Hauer <[hidden email]> wrote:

> Hi,
>
> In my grails app, a certain user action would start a task which should not
> be blocking. I am enclosing this task in a Promise, making use of grails'
> async feature. It seems to me though, that the onPromise or onError
> callbacks don't work as I think they should. Consider a freshly created
> grails application with a single controller:
>
> package grailstest
> import static grails.async.Promises.*
>
> class AsyncController {
>     def promise(long id) {
>         def promise = task {
>             println "promise start ${new Date().format("hh:mm:ss")}"
>             if(id) sleep id
>             println "promise finish ${new Date().format("hh:mm:ss")}"
>         }
>         promise.onComplete { result ->
>             println "promise onComplete ${new Date().format("hh:mm:ss")}\n"
>         }
>         render "AsyncController ${new Date().format("hh:mm:ss")}\n"
>     }
> }
>
> Once this is running (grails run-app), I am calling the grails app:
>
> with a typical timeout of 2s ($ curl
> http://localhost:8080/grails-start/async/promise/2000) which results in:
> promise start 05:08:17
> promise finish 05:08:19
> i.e. no sign of onComplete reached
> with a very small timeout I often get an error:
> | Error 2014-02-05 17:09:27,665 [Actor Thread 16] ERROR
> gpars.LoggingPoolFactory  - Async execution error: null
> Message: null
>     Line | Method
> ->>   61 | doCall    in
> org.grails.async.factory.gpars.GparsPromise$_onComplete_closure1
> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
> |     62 | run       in groovyx.gpars.dataflow.DataCallback$1
> |   1145 | runWorker in java.util.concurrent.ThreadPoolExecutor
> |    615 | run       in java.util.concurrent.ThreadPoolExecutor$Worker
> ^    724 | run . . . in java.lang.Thread
> When I delete the line with sleep, it mostly works:
> promise start 05:10:29
> promise finish 05:10:29
> promise onComplete 05:10:29
> Finally, of course, when I add a promise.get() to wait for completion before
> the controller returns, then onComplete works as expected (but the request
> is blocked, of course). For tiny timeouts I occasionally see the error
> above.
>
> Could you give some advice if Promises are a viable/suggested route here and
> if I am doing anything wrong,
>
> Cheers,
>
> Tamás
>
> --
> Tamás Hauer
> Genève, Switzerland



--
Graeme Rocher
Grails Project Lead
SpringSource

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: Grails async processing with Promise

Tamás Hauer-2
Hi Graeme,

Thanks a lot for the reply.

Yes, from the controller I am returning a synchronous response with the
render method: I don't want/expect the promise task to contribute to the
response. I don't, however, understand how I should return the promise
to the framework. Could you show that, please?

Also, I am using a controller here to provide an example which is
easiest to demonstrate. I found the same behaviour when this code is in
a service. (I.e. Promise gets executed asynchronously as expected, but
onComplete/onError are not called unless there is a promise.get()).

Cheers,

Tamás


On 02/10/2014 11:12 AM, Graeme Rocher wrote:

> With controllers you need to return the promise to the framework which
> will execute it. You're not doing this here and instead returning a
> synchronous response with the render method
>
> On Wed, Feb 5, 2014 at 5:14 PM, Tamás Hauer <[hidden email]> wrote:
>> Hi,
>>
>> In my grails app, a certain user action would start a task which should not
>> be blocking. I am enclosing this task in a Promise, making use of grails'
>> async feature. It seems to me though, that the onPromise or onError
>> callbacks don't work as I think they should. Consider a freshly created
>> grails application with a single controller:
>>
>> package grailstest
>> import static grails.async.Promises.*
>>
>> class AsyncController {
>>     def promise(long id) {
>>         def promise = task {
>>             println "promise start ${new Date().format("hh:mm:ss")}"
>>             if(id) sleep id
>>             println "promise finish ${new Date().format("hh:mm:ss")}"
>>         }
>>         promise.onComplete { result ->
>>             println "promise onComplete ${new Date().format("hh:mm:ss")}\n"
>>         }
>>         render "AsyncController ${new Date().format("hh:mm:ss")}\n"
>>     }
>> }
>>
>> Once this is running (grails run-app), I am calling the grails app:
>>
>> with a typical timeout of 2s ($ curl
>> http://localhost:8080/grails-start/async/promise/2000) which results in:
>> promise start 05:08:17
>> promise finish 05:08:19
>> i.e. no sign of onComplete reached
>> with a very small timeout I often get an error:
>> | Error 2014-02-05 17:09:27,665 [Actor Thread 16] ERROR
>> gpars.LoggingPoolFactory  - Async execution error: null
>> Message: null
>>     Line | Method
>> ->>   61 | doCall    in
>> org.grails.async.factory.gpars.GparsPromise$_onComplete_closure1
>> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
>> |     62 | run       in groovyx.gpars.dataflow.DataCallback$1
>> |   1145 | runWorker in java.util.concurrent.ThreadPoolExecutor
>> |    615 | run       in java.util.concurrent.ThreadPoolExecutor$Worker
>> ^    724 | run . . . in java.lang.Thread
>> When I delete the line with sleep, it mostly works:
>> promise start 05:10:29
>> promise finish 05:10:29
>> promise onComplete 05:10:29
>> Finally, of course, when I add a promise.get() to wait for completion before
>> the controller returns, then onComplete works as expected (but the request
>> is blocked, of course). For tiny timeouts I occasionally see the error
>> above.
>>
>> Could you give some advice if Promises are a viable/suggested route here and
>> if I am doing anything wrong,
>>
>> Cheers,
>>
>> Tamás
>>
>> --
>> Tamás Hauer
>> Genève, Switzerland
>
>

--
Tamás Hauer
Genève, Switzerland



smime.p7s (5K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Grails async processing with Promise

SyedAli
In reply to this post by Graeme Rocher-2
How to return the promise to the framework?
Reply | Threaded
Open this post in threaded view
|

Re: Grails async processing with Promise

jstorq
This post was updated on .
Did anyone ever get an answer to what "send the promise to the framework which
will execute it" actually looks like?

Thanks!
Reply | Threaded
Open this post in threaded view
|

Re: Grails async processing with Promise

AllLangsDevel
I think he meant to do this...

import static grails.async.Promises.task

class AsynchTestController {
        def noteService
        def quick(){
                def promise = task {
                       log.debug "promise start ${new Date().format("hh:mm:ss")}"
                       if(params.id) sleep params.id
                       log.debug "promise finish ${new Date().format("hh:mm:ss")}"
                }
                promise.onComplete { result ->
                       log.debug "promise onComplete ${new Date().format("hh:mm:ss")}\n"
                        render "Test"
                }
                log.debug "AsyncController ${new Date().format("hh:mm:ss")}\n"
                return promise
        }
}
Reply | Threaded
Open this post in threaded view
|

Re: Grails async processing with Promise

agusluc
In reply to this post by Tamás Hauer-2
I had to do something similar, if you want to return the response to the user without waiting the async process to finish and being able of pick up the result of that process, you need to use the executor framework. I did some experiments using the executor plugin for grails (the latest version of the plugin is 0.3, but i pick some PR from the plugin github and compiled a new version as .jas, i know that is not ideal but it was only for experimental purposes)

https://github.com/agusl88/grails-async-job-queuqe