Jörg Hoh created SLING-5261:
-------------------------------
Summary: bgservlets use user session for both execution of the
command and storing the 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
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)