runAsync from the executor plugin hangs if I try to save() a domain object that was retrieved outside the closure

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

runAsync from the executor plugin hangs if I try to save() a domain object that was retrieved outside the closure

Martin Jones-2
Hi,

I am using the excellent exectuor plugin to run long-running tasks in
background threads. However, I am getting some strange behaviour. If I
have the following code, all is well:

class myController{
    def myMethod = {
         runAsync {

             def b = Book.get(123)
             b.name = 'foo'
             b.save()
             println "done!"
        }
        redirect(action: 'list')
    }
}

but if I move the call to Book.get() outside the closure, thus:

class myController{
    def myMethod = {

         def b = Book.get(123)
         runAsync {
             b.name = 'foo'
             b.save()
             println "done!"  // this line is never reached
        }
        redirect(action: 'list')
    }
}


then the closure simply hangs when it gets to the b.save() line. This
is not necessarily a problem - can easily make sure that all my code
looks like the first example - but is this the expected behaviour?
Normally when I try to save an object in the wrong place I get a stack
trace which allows me to figure out what the error is, but the fact
that the thread just hangs is making debugging difficult!

Martin

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

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: runAsync from the executor plugin hangs if I try to save() a domain object that was retrieved outside the closure

basejump (Josh)
how do you know its hanging? Is it throwing an exception there instead? what version of grails?
Do you get any output when you turn on sql logging for hibernate?
Would it be possible to put together a small app that demonstrates the problem and put it up on a either a github project or zip and emailed?

On Mar 28, 2012, at 9:11 AM, Martin Jones wrote:

> Hi,
>
> I am using the excellent exectuor plugin to run long-running tasks in
> background threads. However, I am getting some strange behaviour. If I
> have the following code, all is well:
>
> class myController{
>    def myMethod = {
>         runAsync {
>
>             def b = Book.get(123)
>             b.name = 'foo'
>             b.save()
>             println "done!"
>        }
>        redirect(action: 'list')
>    }
> }
>
> but if I move the call to Book.get() outside the closure, thus:
>
> class myController{
>    def myMethod = {
>
>         def b = Book.get(123)
>         runAsync {
>             b.name = 'foo'
>             b.save()
>             println "done!"  // this line is never reached
>        }
>        redirect(action: 'list')
>    }
> }
>
>
> then the closure simply hangs when it gets to the b.save() line. This
> is not necessarily a problem - can easily make sure that all my code
> looks like the first example - but is this the expected behaviour?
> Normally when I try to save an object in the wrong place I get a stack
> trace which allows me to figure out what the error is, but the fact
> that the thread just hangs is making debugging difficult!
>
> Martin
>
> ---------------------------------------------------------------------
> To unsubscribe from this list, please visit:
>
>    http://xircles.codehaus.org/manage_email
>
>


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

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: runAsync from the executor plugin hangs if I try to save() a domain object that was retrieved outside the closure

Ingo Wiarda
In reply to this post by Martin Jones-2
Hi,

from working with background threads in gpars, I have learned that they
can terminate silently (there is no default mechanism to "throw an
exception back to the originating code" if the async code just exits
because of one, though one could use actors to do so).
So, it always helps to make sure that the async code runs under normal
circumstances, before trying to move it into the background thread.

Also, did the code actually save the changes? Could be some session
trouble (main thread completes before async thread is run, and commits /
closes the db session, while the async code tries and fails to save the
Book object to a closed db connection (and fails silently).

Ingo


On 28.03.2012 16:11, Martin Jones wrote:

> Hi,
>
> I am using the excellent exectuor plugin to run long-running tasks in
> background threads. However, I am getting some strange behaviour. If I
> have the following code, all is well:
>
> class myController{
>      def myMethod = {
>           runAsync {
>
>               def b = Book.get(123)
>               b.name = 'foo'
>               b.save()
>               println "done!"
>          }
>          redirect(action: 'list')
>      }
> }
>
> but if I move the call to Book.get() outside the closure, thus:
>
> class myController{
>      def myMethod = {
>
>           def b = Book.get(123)
>           runAsync {
>               b.name = 'foo'
>               b.save()
>               println "done!"  // this line is never reached
>          }
>          redirect(action: 'list')
>      }
> }
>
>
> then the closure simply hangs when it gets to the b.save() line. This
> is not necessarily a problem - can easily make sure that all my code
> looks like the first example - but is this the expected behaviour?
> Normally when I try to save an object in the wrong place I get a stack
> trace which allows me to figure out what the error is, but the fact
> that the thread just hangs is making debugging difficult!
>
> Martin
>
> ---------------------------------------------------------------------
> To unsubscribe from this list, please visit:
>
>      http://xircles.codehaus.org/manage_email
>
>


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

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: runAsync from the executor plugin hangs if I try to save() a domain object that was retrieved outside the closure

Martin Jones-2
In reply to this post by basejump (Josh)
Hi,



On 28 March 2012 20:19, Josh (basejump) <[hidden email]> wrote:
> how do you know its hanging?

The println statement is never reached, even thought the save() only
takes less than a second if I run it outside the runAsync block. There
is no other output.

> Is it throwing an exception there instead?

No, that is what I find unexpected.

> what version of grails?

2.0.1

> Do you get any output when you turn on sql logging for hibernate?

Yes, the UPDATE seems to be issued normally

> Would it be possible to put together a small app that demonstrates the problem and put it up on a either a github project or zip and emailed?

I will see if I can reproduce the problem in a small app and email
back. I am not necessarily considering this a bug - just trying to
figure out if it's the expected behaviour.

M




>
> On Mar 28, 2012, at 9:11 AM, Martin Jones wrote:
>
>> Hi,
>>
>> I am using the excellent exectuor plugin to run long-running tasks in
>> background threads. However, I am getting some strange behaviour. If I
>> have the following code, all is well:
>>
>> class myController{
>>    def myMethod = {
>>         runAsync {
>>
>>             def b = Book.get(123)
>>             b.name = 'foo'
>>             b.save()
>>             println "done!"
>>        }
>>        redirect(action: 'list')
>>    }
>> }
>>
>> but if I move the call to Book.get() outside the closure, thus:
>>
>> class myController{
>>    def myMethod = {
>>
>>         def b = Book.get(123)
>>         runAsync {
>>             b.name = 'foo'
>>             b.save()
>>             println "done!"  // this line is never reached
>>        }
>>        redirect(action: 'list')
>>    }
>> }
>>
>>
>> then the closure simply hangs when it gets to the b.save() line. This
>> is not necessarily a problem - can easily make sure that all my code
>> looks like the first example - but is this the expected behaviour?
>> Normally when I try to save an object in the wrong place I get a stack
>> trace which allows me to figure out what the error is, but the fact
>> that the thread just hangs is making debugging difficult!
>>
>> Martin
>>
>> ---------------------------------------------------------------------
>> To unsubscribe from this list, please visit:
>>
>>    http://xircles.codehaus.org/manage_email
>>
>>
>
>
> ---------------------------------------------------------------------
> To unsubscribe from this list, please visit:
>
>    http://xircles.codehaus.org/manage_email
>
>

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

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: runAsync from the executor plugin hangs if I try to save() a domain object that was retrieved outside the closure

Martin Jones-2
In reply to this post by Ingo Wiarda
On 28 March 2012 23:14, Ingo Wiarda <[hidden email]> wrote:

> Hi,
>
> from working with background threads in gpars, I have learned that they can
> terminate silently (there is no default mechanism to "throw an exception
> back to the originating code" if the async code just exits because of one,
> though one could use actors to do so).
> So, it always helps to make sure that the async code runs under normal
> circumstances, before trying to move it into the background thread.
>
> Also, did the code actually save the changes? Could be some session trouble
> (main thread completes before async thread is run, and commits / closes the
> db session, while the async code tries and fails to save the Book object to
> a closed db connection (and fails silently).

Hmm, that is an intriguing idea. I was under the impression that the
executor plugin took care of making sure that the async block got it's
own db session to run in - otherwise, wouldn't the main thread have to
wait for the background thread to complete, thus making it pointless?
Or do you mean that the main thread simply completes before the async
block is started (but not necessarily finished?)

M






>
> Ingo
>
>
>
> On 28.03.2012 16:11, Martin Jones wrote:
>>
>> Hi,
>>
>> I am using the excellent exectuor plugin to run long-running tasks in
>> background threads. However, I am getting some strange behaviour. If I
>> have the following code, all is well:
>>
>> class myController{
>>     def myMethod = {
>>          runAsync {
>>
>>              def b = Book.get(123)
>>              b.name = 'foo'
>>              b.save()
>>              println "done!"
>>         }
>>         redirect(action: 'list')
>>     }
>> }
>>
>> but if I move the call to Book.get() outside the closure, thus:
>>
>> class myController{
>>     def myMethod = {
>>
>>          def b = Book.get(123)
>>          runAsync {
>>              b.name = 'foo'
>>              b.save()
>>              println "done!"  // this line is never reached
>>         }
>>         redirect(action: 'list')
>>     }
>> }
>>
>>
>> then the closure simply hangs when it gets to the b.save() line. This
>> is not necessarily a problem - can easily make sure that all my code
>> looks like the first example - but is this the expected behaviour?
>> Normally when I try to save an object in the wrong place I get a stack
>> trace which allows me to figure out what the error is, but the fact
>> that the thread just hangs is making debugging difficult!
>>
>> Martin
>>
>> ---------------------------------------------------------------------
>> To unsubscribe from this list, please visit:
>>
>>     http://xircles.codehaus.org/manage_email
>>
>>
>
>
> ---------------------------------------------------------------------
> To unsubscribe from this list, please visit:
>
>   http://xircles.codehaus.org/manage_email
>
>

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

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: runAsync from the executor plugin hangs if I try to save() a domain object that was retrieved outside the closure

Martin Jones-2
I think you may be on to something here!  Adding a Thread.sleep(1000)
to the end of the main thread restores the normal behaviour. So I
think you may be right. Not sure what the fix is though... maybe add
an "after" filter to all my methods that use async blocks to make sure
they wait before completing?

M



On 29 March 2012 11:55, Martin Jones <[hidden email]> wrote:

> On 28 March 2012 23:14, Ingo Wiarda <[hidden email]> wrote:
>> Hi,
>>
>> from working with background threads in gpars, I have learned that they can
>> terminate silently (there is no default mechanism to "throw an exception
>> back to the originating code" if the async code just exits because of one,
>> though one could use actors to do so).
>> So, it always helps to make sure that the async code runs under normal
>> circumstances, before trying to move it into the background thread.
>>
>> Also, did the code actually save the changes? Could be some session trouble
>> (main thread completes before async thread is run, and commits / closes the
>> db session, while the async code tries and fails to save the Book object to
>> a closed db connection (and fails silently).
>
> Hmm, that is an intriguing idea. I was under the impression that the
> executor plugin took care of making sure that the async block got it's
> own db session to run in - otherwise, wouldn't the main thread have to
> wait for the background thread to complete, thus making it pointless?
> Or do you mean that the main thread simply completes before the async
> block is started (but not necessarily finished?)
>
> M
>
>
>
>
>
>
>>
>> Ingo
>>
>>
>>
>> On 28.03.2012 16:11, Martin Jones wrote:
>>>
>>> Hi,
>>>
>>> I am using the excellent exectuor plugin to run long-running tasks in
>>> background threads. However, I am getting some strange behaviour. If I
>>> have the following code, all is well:
>>>
>>> class myController{
>>>     def myMethod = {
>>>          runAsync {
>>>
>>>              def b = Book.get(123)
>>>              b.name = 'foo'
>>>              b.save()
>>>              println "done!"
>>>         }
>>>         redirect(action: 'list')
>>>     }
>>> }
>>>
>>> but if I move the call to Book.get() outside the closure, thus:
>>>
>>> class myController{
>>>     def myMethod = {
>>>
>>>          def b = Book.get(123)
>>>          runAsync {
>>>              b.name = 'foo'
>>>              b.save()
>>>              println "done!"  // this line is never reached
>>>         }
>>>         redirect(action: 'list')
>>>     }
>>> }
>>>
>>>
>>> then the closure simply hangs when it gets to the b.save() line. This
>>> is not necessarily a problem - can easily make sure that all my code
>>> looks like the first example - but is this the expected behaviour?
>>> Normally when I try to save an object in the wrong place I get a stack
>>> trace which allows me to figure out what the error is, but the fact
>>> that the thread just hangs is making debugging difficult!
>>>
>>> Martin
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe from this list, please visit:
>>>
>>>     http://xircles.codehaus.org/manage_email
>>>
>>>
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe from this list, please visit:
>>
>>   http://xircles.codehaus.org/manage_email
>>
>>

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

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: runAsync from the executor plugin hangs if I try to save() a domain object that was retrieved outside the closure

basejump (Josh)
In reply to this post by Martin Jones-2
if the update is happening normally then it could be an issue with the println itself not making it to the console but thats weird. do you get the same results using a log? You are testing via run-app right?
i would be happy to take a look at the sample app. The thread should not be getting killed and an after filter should not be necessary. running via "test-app" is a whole other story as in that case it can stop before done.

On Mar 29, 2012, at 5:52 AM, Martin Jones wrote:

I will see if I can reproduce the problem in a small app and email
back. I am not necessarily considering this a bug - just trying to
figure out if it's the expected behaviour.

Reply | Threaded
Open this post in threaded view
|

Re: runAsync from the executor plugin hangs if I try to save() a domain object that was retrieved outside the closure

Martin Jones-2
Hi,

yes, I'm doing run-app. There's no difference if I use a log, so I
think it's just the thread getting killed. As a temporary fix I have
added an after filter that sleeps for 1 sec which has fixed all the
problems.

Feel free to take a look at the app:

https://github.com/mojones/AfterParty2

The controller method that was causing the problem was /run/attachReads .

I can't reproduce the problem with a smaller app, I'm afraid.

Thanks for all your help

Martin




On 29 March 2012 16:06, Josh (basejump) <[hidden email]> wrote:

> if the update is happening normally then it could be an issue with the
> println itself not making it to the console but thats weird. do you get the
> same results using a log? You are testing via run-app right?
> i would be happy to take a look at the sample app. The thread should not be
> getting killed and an after filter should not be necessary. running via
> "test-app" is a whole other story as in that case it can stop before done.
>
> On Mar 29, 2012, at 5:52 AM, Martin Jones wrote:
>
>
> I will see if I can reproduce the problem in a small app and email
> back. I am not necessarily considering this a bug - just trying to
> figure out if it's the expected behaviour.
>
>

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

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: runAsync from the executor plugin hangs if I try to save() a domain object that was retrieved outside the closure

basejump (Josh)
Thanks for the heads up. I can't easily isolate and debug the app you sent.
If you can't reproduce it in a smaller test app then it must be something else that is contributing to it. I tried as well in a test app and the I see the println.

On Mar 29, 2012, at 10:16 AM, Martin Jones wrote:

> Hi,
>
> yes, I'm doing run-app. There's no difference if I use a log, so I
> think it's just the thread getting killed. As a temporary fix I have
> added an after filter that sleeps for 1 sec which has fixed all the
> problems.
>
> Feel free to take a look at the app:
>
> https://github.com/mojones/AfterParty2
>
> The controller method that was causing the problem was /run/attachReads .
>
> I can't reproduce the problem with a smaller app, I'm afraid.
>
> Thanks for all your help
>
> Martin
>
>
>
>
> On 29 March 2012 16:06, Josh (basejump) <[hidden email]> wrote:
>> if the update is happening normally then it could be an issue with the
>> println itself not making it to the console but thats weird. do you get the
>> same results using a log? You are testing via run-app right?
>> i would be happy to take a look at the sample app. The thread should not be
>> getting killed and an after filter should not be necessary. running via
>> "test-app" is a whole other story as in that case it can stop before done.
>>
>> On Mar 29, 2012, at 5:52 AM, Martin Jones wrote:
>>
>>
>> I will see if I can reproduce the problem in a small app and email
>> back. I am not necessarily considering this a bug - just trying to
>> figure out if it's the expected behaviour.
>>
>>
>
> ---------------------------------------------------------------------
> To unsubscribe from this list, please visit:
>
>    http://xircles.codehaus.org/manage_email
>
>


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

    http://xircles.codehaus.org/manage_email