Uploaded image for project: 'Confluence Data Center'
  1. Confluence Data Center
  2. CONFSERVER-65136

Introduce Transaction Rollback handling in core and provide plugin API

XMLWordPrintable

    • Icon: Suggestion Suggestion
    • Resolution: Unresolved
    • None
    • Content - Page
    • 4
    • We collect Confluence feedback from various sources, and we evaluate what we've collected when planning our product roadmap. To understand how this piece of feedback will be reviewed, see our Implementation of New Features Policy.

      Confluence doesn't have generic retry mechanism for handling Transaction rollbacks caused by HibernateOptimisticLockingFailureException or StaleObjectStateException.

      When there is a race condition, one thread is bound to see such exceptions, Confluence should try again to perform the operation instead of throwing this error to user. We need some level of guidelines and handling on UserActions.

      One other example could be a job with modifying 100s of page and in parallel if some user alters a page, one of job/user can see Optimistic Lock exceptions.
      This is similar to AllPage delete operation in a space which currently doesn't have batching.
      Ideally, for there cases the jobs should have batching and thats a programmer's choice.
      But, a user action shouldn't be rolled-back instead it should be retried or handled in a graceful manner.

      Example trace:

      Caused by: org.springframework.orm.hibernate5.HibernateOptimisticLockingFailureException: Object of class [com.atlassian.confluence.pages.Page] with identifier [6947404]: optimistic locking failed; nested exception is org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [com.atlassian.confluence.pages.Page#6947404]
      	at org.springframework.orm.hibernate5.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:284)
      	at org.springframework.orm.hibernate5.HibernateTemplate.doExecute(HibernateTemplate.java:392)
      	at org.springframework.orm.hibernate5.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:351)
      	at com.atlassian.confluence.core.persistence.hibernate.HibernateObjectDao.findNamedQueryStringParams(HibernateObjectDao.java:486)
      	at com.atlassian.confluence.core.persistence.hibernate.HibernateObjectDao.findNamedQueryStringParam(HibernateObjectDao.java:426)
      	at com.atlassian.confluence.pages.persistence.dao.hibernate.AbstractHibernateAttachmentDao.getLatestVersionsOfAttachmentsWithAnyStatus(AbstractHibernateAttachmentDao.java:163)
      	at com.atlassian.confluence.pages.attachments.AbstractDelegatingAttachmentDao.getLatestVersionsOfAttachmentsWithAnyStatus(AbstractDelegatingAttachmentDao.java:90)
      	at com.atlassian.confluence.pages.DefaultAttachmentManager.getLatestVersionsOfAttachmentsWithAnyStatus(DefaultAttachmentManager.java:399)
      	at com.atlassian.confluence.pages.DelegatorAttachmentManager.getLatestVersionsOfAttachmentsWithAnyStatus(DelegatorAttachmentManager.java:71)
      	at com.atlassian.confluence.impl.pages.attachments.ReadThroughCachingAttachmentManager.getLatestVersionsOfAttachmentsWithAnyStatus(ReadThroughCachingAttachmentManager.java:71)
      	at sun.reflect.GeneratedMethodAccessor1698.invoke(Unknown Source)
      	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      	at java.lang.reflect.Method.invoke(Method.java:498)
      	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343)
      	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
      	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
      	at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:295)
      	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
      	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
      	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
      	at com.sun.proxy.$Proxy249.getLatestVersionsOfAttachmentsWithAnyStatus(Unknown Source)
      	at com.atlassian.confluence.pages.AbstractPage.getSearchableDependants(AbstractPage.java:75)
      	at com.atlassian.confluence.search.lucene.QueuingConfluenceIndexer$InternalConfluenceIndexer.unIndexIncludingDependents(QueuingConfluenceIndexer.java:161)
      	at com.atlassian.confluence.search.lucene.QueuingConfluenceIndexer.unIndexIncludingDependents(QueuingConfluenceIndexer.java:81)
      	at com.atlassian.confluence.pages.DefaultPageManager.lambda$trashPage$11(DefaultPageManager.java:960)
      	at com.atlassian.confluence.impl.search.IndexerEventPublisher.lambda$publishCallbackEvent$0(IndexerEventPublisher.java:29)
      	at com.atlassian.confluence.impl.search.IndexerEventListener.onEvent(IndexerEventListener.java:42)
      	at sun.reflect.GeneratedMethodAccessor1709.invoke(Unknown Source)
      	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      	at java.lang.reflect.Method.invoke(Method.java:498)
      	at com.atlassian.event.internal.SingleParameterMethodListenerInvoker.invoke(SingleParameterMethodListenerInvoker.java:42)
      	... 349 more
      

      Workaround

      While the problem cannot be entirely avoided with certainty, there are a few options to reduce the risk of concurrent updates:

      • If you have control over the code, introduce batched processing of the requests (e.g. perform the operation by space, on a list of pages)
      • For one off tasks, run them during low traffic times (e.g. outside of business hours)

              Unassigned Unassigned
              ggautam Ganesh Gautam
              Votes:
              40 Vote for this issue
              Watchers:
              14 Start watching this issue

                Created:
                Updated: