New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JENKINS-48820# Fix for stack overflow in flownode sse event generation #1667
Conversation
@svanoort I think I am picking up right API to get immediate parent node. PTAL. |
@@ -203,6 +204,9 @@ public void setBlockErrorAction(ErrorAction blockErrorAction) { | |||
* Filters by class to mimic Item.getActions(class). | |||
*/ | |||
public <T extends Action> Collection<T> getPipelineActions(Class<T> clazz) { | |||
if(pipelineActions == null){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixes NPE happening in cases where there are no actions added.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cheers!
6910306
to
e7e49af
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not 100% sure where this fits in the bigger picture (there may be a way to simplify overall) but I think much of this can be done with just a single API call using the new APIs.
} | ||
|
||
private String toPath(List<String> branch) { | ||
private String toPath(Iterator<String> branch) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐜 Seems like we could just pass an Iterable
rather than a one-shot iterator?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or a collection.
@@ -164,7 +149,7 @@ private static Message newMessage(PipelineEventChannel.Event event, FlowExecutio | |||
return message; | |||
} | |||
|
|||
private Message newMessage(PipelineEventChannel.Event event, FlowNode flowNode, List<String> branch) { | |||
private Message newMessage(PipelineEventChannel.Event event, FlowNode flowNode, Iterator<String> branch) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐜 Again, perhaps we can do an Iterable or collection rather than an Iterator?
if (parent instanceof StepStartNode) { | ||
if (parent.getAction(BodyInvocationAction.class) != null) { | ||
return parent; | ||
while (parentBlockId != null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think what you want is myFlowNode.getEnclosingBlocks()
which returns a list of blocks -- perhaps combined with Guava or Java 8 stream/filter APIs, perhaps via new NodeStepTypePredicate('parallel'))
or FlowScanningUtils.hasActionPredicate(SomeAction.class))
-- it'll do all these goodies for you.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@svanoort I looked at myFlowNode.getEnclosingBlocks()
, it doesn't return blocks in order. This code was not written to me and I want to keep changes to minimum as it might break UI. Previous code was making sure preserving certain order, so I would prefer leaving the code with fixing SOF problem with minor enhancements.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@vivek Could we just do a Lists.reverse
, to maintain the order? It's iterating in inside-out order here so I think you want to simply invert that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@svanoort Right. I was not planning to use was due to this javadoc of GraphLookupView.findAllEnclosingBlockStarts()
, https://github.com/jenkinsci/workflow-api-plugin/blob/a20f21fddc6831f51c3ceeefd3ed1b744b899e98/src/main/java/org/jenkinsci/plugins/workflow/graph/GraphLookupView.java#L55 that says order is not guaranteed. After clarification offline with you, I am fine using it. Please open a PR to fix the Javadoc to make it clear that inside-out order will be maintained.
Was this SO due to an infinite loop, or just by a complicated pipeline? |
@sophistifunk caused by large number of steps in pipelines about 4600+ as reported in https://issues.jenkins-ci.org/browse/JENKINS-48820. |
@svanoort PTAL |
return null; | ||
/* package: so that we can unit test it */ List<String> getBranch(FlowNode flowNode) { | ||
return Lists.reverse(flowNode.getEnclosingBlocks().stream() | ||
.map(FlowNode::getId).collect(Collectors.toList())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh hey, if you just wanted the IDs there's node.getAllEnclosingIds()
Please don't kill me :) I've got APIs to do pretty much all the things you'd want to do with FlowNodes at this point...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ha ha. This is great. Let me make this change.
StringBuilder builder = new StringBuilder(); | ||
for (String leaf : branch) { | ||
for(String leaf: branch){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐜 Can this path creation with just branch.stream().collect(Collectors.joining("/"))
if you're feeling all Streams-y :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, there are many places in the code we need to change to adopt java 8, keeping the scope limited to just this fix, so be making such changes some other time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's close enough -- can be tuned by use of Java 8 features and an API that gives you things in the same format but ::shrug::
Description
Fix for stack overflow error during pipeline execution SSE event generation, has other minor improvements.
See JENKINS-48820.
Submitter checklist
Reviewer checklist