Grails-Plugin-Consortium / grails-jesque

1 stars 5 forks source link

hibernate session is not closed if flush fails #32

Open bp-FLN opened 4 years ago

bp-FLN commented 4 years ago

In WorkerPersistenceListener, if the flush fails (e.g. due to an ValidationException), we don't call persistenceInterceptor.destroy() and hence the hibernate session leaks through to the next job.

this is the stacktrace from the failing flush:

00:54:03.878 [Worker-0 Jesque-2.1.1:Processing Job] ERROR n.g.j.worker.WorkerListenerDelegate - Failure executing listener grails.plugins.jesque.WorkerPersistenceListener@36e2afeb for event JOB_SUCCESS from queue genericQueue on worker resque:worker:florian.langenhahn:29589-0:JAVA_DYNAMIC_QUEUES,genericQueue
grails.validation.ValidationException: Validation error whilst flushing entity [Domain]:
- Field error in object 'Domain' on field 'foo': ...
    at org.grails.datastore.mapping.validation.ValidationException.newInstance(ValidationException.java:81) [11 skipped]
    at org.grails.orm.hibernate.support.ClosureEventListener.doValidate(ClosureEventListener.java:375)
    at org.grails.orm.hibernate.support.ClosureEventListener$7.call(ClosureEventListener.java:323)
    at org.grails.orm.hibernate.support.ClosureEventListener$7.call(ClosureEventListener.java:312)
    at org.grails.orm.hibernate.support.ClosureEventListener.doWithManualSession(ClosureEventListener.java:337)
    at org.grails.orm.hibernate.support.ClosureEventListener.onPreUpdate(ClosureEventListener.java:312)
    at org.grails.orm.hibernate.EventTriggeringInterceptor.onPreUpdate(EventTriggeringInterceptor.java:166)
    at org.grails.orm.hibernate.EventTriggeringInterceptor.onPersistenceEvent(EventTriggeringInterceptor.java:91)
    at org.grails.datastore.mapping.engine.event.AbstractPersistenceEventListener.onApplicationEvent(AbstractPersistenceEventListener.java:47)
    at org.grails.orm.hibernate.support.ClosureEventTriggeringInterceptor.publishEvent(ClosureEventTriggeringInterceptor.java:165) [4 skipped]
    at org.grails.orm.hibernate.support.ClosureEventTriggeringInterceptor.onPreUpdate(ClosureEventTriggeringInterceptor.java:138)
    at org.hibernate.action.internal.EntityUpdateAction.preUpdate(EntityUpdateAction.java:257)
    at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:134)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:465)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:351)
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:350)
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:56)
    at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1258)
    at org.grails.orm.hibernate4.support.HibernatePersistenceContextInterceptor.flush(HibernatePersistenceContextInterceptor.java:143)
    at org.grails.orm.hibernate.support.AbstractMultipleDataSourceAggregatePersistenceContextInterceptor.flush(AbstractMultipleDataSourceAggregatePersistenceContextInterceptor.java:97)
    at grails.persistence.support.PersistenceContextInterceptor$flush$0.call(Unknown Source)
    at grails.plugins.jesque.WorkerPersistenceListener.unbindSession(WorkerPersistenceListener.groovy:37)
    at grails.plugins.jesque.WorkerPersistenceListener.onEvent(WorkerPersistenceListener.groovy:52)

and this stacktrace is from the following job:

00:54:03.981 [Worker-0 Jesque-2.1.1:Processing Job] ERROR n.g.j.worker.WorkerListenerDelegate - Failure executing listener grails.plugins.jesque.WorkerPersistenceListener@36e2afeb for event JOB_SUCCESS from queue genericQueue on worker resque:worker:florian.langenhahn:29589-0:JAVA_DYNAMIC_QUEUES,genericQueue
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [Domain#864010]
    at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:2541)
    at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3285)
    at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:3183)
    at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3525)
    at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:159)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:465)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:351)
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:350)
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:56)
    at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1258)
    at org.grails.orm.hibernate4.support.HibernatePersistenceContextInterceptor.flush(HibernatePersistenceContextInterceptor.java:143)
    at org.grails.orm.hibernate.support.AbstractMultipleDataSourceAggregatePersistenceContextInterceptor.flush(AbstractMultipleDataSourceAggregatePersistenceContextInterceptor.java:97)
    at grails.persistence.support.PersistenceContextInterceptor$flush$0.call(Unknown Source)
    at grails.plugins.jesque.WorkerPersistenceListener.unbindSession(WorkerPersistenceListener.groovy:37)
    at grails.plugins.jesque.WorkerPersistenceListener.onEvent(WorkerPersistenceListener.groovy:52)

I guess a fix would be to simply put a try/catch around the flush.