[ https://issues.apache.org/jira/browse/SLING-5261?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Joerg Hoh closed SLING-5261. ---------------------------- > Background servlets: use a separate session for captured output > --------------------------------------------------------------- > > Key: SLING-5261 > URL: https://issues.apache.org/jira/browse/SLING-5261 > Project: Sling > Issue Type: Bug > Components: Extensions > Affects Versions: Background Servlets 1.0.0 > Reporter: Joerg Hoh > Assignee: Bertrand Delacretaz > Priority: Major > Fix For: Background Servlets 1.0.2 > > > We use the bgservlet to perform batch actions on content in the background, > decoupling it from the user request. We saw a case where these batch actions > failed and also no log was written. We have lots of exceptions like this in > the log: > {noformat} > 02.11.2015 23:50:32.264 *ERROR* [pool-5743-thread-3] > com.day.cq.wcm.msm.impl.commands.RolloutCommand Trying to commit status > change: {} > java.io.IOException: RepositoryException in flush() > at > org.apache.sling.bgservlets.impl.nodestream.NodeOutputStream.flush(NodeOutputStream.java:103) > at > org.apache.sling.bgservlets.impl.nodestream.NodeOutputStream.flushIfNeeded(NodeOutputStream.java:110) > at > org.apache.sling.bgservlets.impl.nodestream.NodeOutputStream.write(NodeOutputStream.java:129) > at java.io.FilterOutputStream.write(FilterOutputStream.java:71) > at > org.apache.sling.bgservlets.impl.SuspendableOutputStream.write(SuspendableOutputStream.java:65) > at > org.apache.sling.bgservlets.BackgroundHttpServletResponse$ServletOutputStreamWrapper.write(BackgroundHttpServletResponse.java:47) > at > javax.servlet.ServletOutputStream.print(ServletOutputStream.java:101) > at > javax.servlet.ServletOutputStream.println(ServletOutputStream.java:252) > ... > Caused by: javax.jcr.InvalidItemStateException: OakState0001: Unresolved > conflicts in /content/foo/bar/jcr:content > at > org.apache.jackrabbit.oak.api.CommitFailedException.asRepositoryException(CommitFailedException.java:237) > at > org.apache.jackrabbit.oak.api.CommitFailedException.asRepositoryException(CommitFailedException.java:212) > at > org.apache.jackrabbit.oak.jcr.delegate.SessionDelegate.newRepositoryException(SessionDelegate.java:664) > at > org.apache.jackrabbit.oak.jcr.delegate.SessionDelegate.save(SessionDelegate.java:489) > at > org.apache.jackrabbit.oak.jcr.session.SessionImpl$8.performVoid(SessionImpl.java:406) > at > org.apache.jackrabbit.oak.jcr.delegate.SessionDelegate.performVoid(SessionDelegate.java:268) > at > org.apache.jackrabbit.oak.jcr.session.SessionImpl.save(SessionImpl.java:403) > at > org.apache.sling.bgservlets.impl.DeepNodeCreator.deepCreateNode(DeepNodeCreator.java:60) > at > org.apache.sling.bgservlets.impl.nodestream.NodeOutputStream.flush(NodeOutputStream.java:92) > ... 134 common frames omitted > Caused by: org.apache.jackrabbit.oak.api.CommitFailedException: OakState0001: > Unresolved conflicts in /content/foo/bar/jcr:content > at > org.apache.jackrabbit.oak.plugins.commit.ConflictValidator.failOnMergeConflict(ConflictValidator.java:115) > at > org.apache.jackrabbit.oak.plugins.commit.ConflictValidator.propertyChanged(ConflictValidator.java:90) > at > org.apache.jackrabbit.oak.spi.commit.CompositeEditor.propertyChanged(CompositeEditor.java:91) > at > org.apache.jackrabbit.oak.spi.commit.EditorDiff.propertyChanged(EditorDiff.java:93) > at > org.apache.jackrabbit.oak.spi.state.AbstractNodeState.comparePropertiesAgainstBaseState(AbstractNodeState.java:181) > at > org.apache.jackrabbit.oak.plugins.document.DocumentNodeStore.compare(DocumentNodeStore.java:1394) > at > org.apache.jackrabbit.oak.plugins.document.DocumentNodeState.compareAgainstBaseState(DocumentNodeState.java:344) > at > org.apache.jackrabbit.oak.spi.commit.EditorDiff.childNodeChanged(EditorDiff.java:148) > at > org.apache.jackrabbit.oak.plugins.document.DocumentNodeStore.dispatch(DocumentNodeStore.java:2108) > ... > {noformat} > The exception happens when writing to the output stream (which is redirected > to write to the repo somewhere below /var/bg), but it logs a conflict in > /content. > For me it looks like that the session which is attached to the user request > is used for 2 different aspects: > * processing the actions on the content > * logging the output to the repository > check the BackgroundRequestExecutionJob class, where the „resource resolver“ > is used for both constructing the „response“ object and as parameter into the > slingRequestProcessor.processRequest() call. > For me it looks like if an repository exception happens on on the processing > side, this effectively prevents the writing to the output stream as well (as > seen by the path where this OakState0001 exception is being reported). I > think, that the action doesn’t clear the JCR transient space after an > exception which will cause any subsequent session.save() to fail as well. > While we could consider this as a problematic case in the handling of the > request itself, the bgservlets should at least be capable to store any issue > written to the output stream successfully in the repository. So a dedicated > session to write the output would be very good to have. > But there is also a different problem with the current implementation: When > the request fills the transient space and does call session.save() yet, but > rather writes to the outpustream, it might be case that the bgservlets do the > session.save(), thus saving the transient space created by the regular > execution as well. > So I suggest this patch: > {noformat} > Index: BackgroundRequestExecutionJob.java > =================================================================== > --- BackgroundRequestExecutionJob.java (revision 1710381) > +++ BackgroundRequestExecutionJob.java (working copy) > @@ -50,6 +50,7 @@ > private final BackgroundHttpServletResponse response; > private final SuspendableOutputStream stream; > private final ResourceResolver resourceResolver; > + private final ResourceResolver bgResponseResolver; > private final SlingRequestProcessor slingRequestProcessor; > private final String path; > private final String streamPath; > @@ -72,8 +73,11 @@ > // current request, for the background request. > resourceResolver = request.getResourceResolver().clone(null); > + // create a dedicated session for the response object > + bgResponseResolver = request.getResourceResolver().clone(null); > + > // Get JobData, defines path and used to save servlet output to the > repository > - final Session s = resourceResolver.adaptTo(Session.class); > + final Session s = bgResponseResolver.adaptTo(Session.class); > if(s == null) { > throw new IOException("Unable to get Session from > ResourceResolver " + resourceResolver); > } > @@ -110,6 +114,8 @@ > // cleanup the resource resolver > resourceResolver.close(); > + bgResponseResolver.close(); > + > } > } > {noformat} -- This message was sent by Atlassian Jira (v8.20.1#820001)