[
https://issues.apache.org/jira/browse/SLING-5261?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Bertrand Delacretaz resolved SLING-5261.
----------------------------------------
Resolution: Fixed
> 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: Jörg Hoh
> Assignee: Bertrand Delacretaz
> 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
(v6.3.4#6332)