Skip to content
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

Generified Flow Search Algorithms #2

Merged
merged 108 commits into from
Aug 25, 2016
Merged

Generified Flow Search Algorithms #2

merged 108 commits into from
Aug 25, 2016

Conversation

svanoort
Copy link
Member

@svanoort svanoort commented Apr 14, 2016

Provides a bundle of search and iteration APIs to simplify working with pipeline flow graphs (DAGs).

These are intended to be extensible for custom use cases, but provide a general API that covers what is needed.

For a rundown of the core APIs and how to work with them, see: https://github.com/jenkinsci/workflow-api-plugin/pull/2/files#diff-f8537b8acb35b350992eb264d4f9f207R43

In gist, we're offering some core primitives for working with the flow graph that are needed to do more involved work with the flow graph:

  • The visitor pattern is the starting point for SAX-like analysis of a flowgraph (and may be extended to provide a block-aware or marker-aware, i.e. stage/milestone-aware visitor)
  • ForkScanner is needed to effectively handle blocks in the flowgraph (since blocks are seen in a logical linear order). It is the primitive needed for block-based use in a DOM-like tree analysis, or block-aware SAX-like analysis
  • LinearBlockHoppingFlowScanner is the primitive that allows for quickly ignoring sibling blocks (helpful if you only care about preceding or enclosing nodes, similar to the FlowNodeSerialWalker).

Notes:

  • Parallel blocks have their own LabelAction for each branch, a ParallelLabelAction on the StepStartNode beginning each branch, with displayname branch + displayname, and getThreadName that returns the label given to the branch, StepEndNode gives the timing too (and final state)

General use cases:

Pipeline Stage View:

  • Stage/node labels - the BlockJumpingScanner allows us to solve JENKINS-33290

@svanoort
Copy link
Member Author

@jglick When you get a chance, can you give this a peek? It's intended to offer the more general APIs discussed in #1, but also allow for incremental caching of flow graph analysis due to the option to supply StopNodes (so you only analyze up to the last heads).

Probably still a bit rough owing to late-night coding in some cases. But it gives the 3 basic iteration approaches, makes it fairly easy to plug in more (there's one case where we need depth-first-first, and an option to only operate on the enclosing block scopes only would be helpful).

Key points:

  • we use general-purpose algorithms that can be plugged in with different flow graph walking algorithms
  • state variables are exposed internally. This is intentional, so we can use and extend this this when plugging this back into the pipeline stage view codebase for more complex stateful analysis.
  • we can extend the FlowScanners to track more information while walking the graph. For example, storing last node when we iterate, to allow calculating the timings.

Apologies if the above is rambling and/or slightly incoherent. Check the timestamp and you'll see why, I can clarify/explain tomorrow.

@jglick jglick changed the title [WIP] Generified Flow Search + Start of Incrementally Updated Flow Stats Generified Flow Search + Start of Incrementally Updated Flow Stats Apr 19, 2016
@jglick
Copy link
Member

jglick commented Apr 19, 2016

Intended as a substitute for #1 IIUC.

@svanoort
Copy link
Member Author

svanoort commented Apr 19, 2016

@jglick Correct, for that and more. I think it probably could use some convenience methods to make it more friendly for that sort of usage, but wanted to solicit input about how that could look.

It may actually be easier for some of these cases (for example, the nested stage/label + excecutor node name combo) to use the visit method, and use its boolean returnVal to control search termination.

@jglick
Copy link
Member

jglick commented Apr 19, 2016

Another use case is WorkflowRun.getLogPrefix.

@svanoort
Copy link
Member Author

Yes, I think so... and, er we don't have to worry about a stack overflow with this mechanism in that case.
Although in that case, I have to wonder if there's a way to simplify the overall log copying.


scanner = new FlowScanner.DepthFirstScanner();
matches = scanner.findAllMatches(heads, null, matchEchoStep);
Assert.assertTrue(matches.size() == 5);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assertEquals(5, matches.size());

@svanoort svanoort mentioned this pull request Apr 26, 2016
4 tasks
if (parents == null || parents.size() == 0) {
// welp done with this node, guess we consult the queue?
if (parents.isEmpty()) {
// welp, we're done with this node, guess we consult the queue?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jglick
Copy link
Member

jglick commented Aug 24, 2016

re:bee:

<<<<<<< HEAD
/** If true, we are walking from the flow end node and have a complete view of the flow
* Needed because there are implications when not walking from a finished flow (blocks without a {@link BlockEndNode})*/
=======
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐛 merge conflicts here and elsewhere

@@ -33,7 +33,7 @@
</parent>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-api</artifactId>
<version>2.2-SNAPSHOT</version>
<version>2.2-blockapis-SNAPSHOT</version>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please revert before merging.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jglick Done.

@jglick
Copy link
Member

jglick commented Aug 24, 2016

re:bee:

NodeType nextType = null;

public ForkScanner() {

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment has not been addressed 🐜

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@oleg-nenashev I believe it was (check back at the original) -- you can invoke methods on a ForkScanner with no nodes feeding it, they'll return null, empty, or an exception as appropriate.

@oleg-nenashev
Copy link
Member

So 🐛 for missing myNext reset in /DepthFirstScanner#reset(). I also have serious concerns regarding ForkScanner#setHeads()

Other code looks good to me

@svanoort
Copy link
Member Author

svanoort commented Aug 25, 2016

@oleg-nenashev That covers the issue with the submitting the Parallel Branch Starts for only an incomplete flow as the heads -- in a fairly straightforward fashion. I guess re-bee potential for @jglick too if he likes

@jglick
Copy link
Member

jglick commented Aug 25, 2016

re:bee: (do not understand the recent changes but…there is more test code, fine)

@oleg-nenashev
Copy link
Member

That covers the issue with the submitting the Parallel Branch Starts for only an incomplete flow as the heads -- in a fairly straightforward fashion

Would be useful to have some protective code in setHeads() as well.
But 🐝 , because it seems to address the issue

@svanoort
Copy link
Member Author

Final bees, merging for release

@svanoort
Copy link
Member Author

@reviewbybees done

@svanoort svanoort merged commit 1d7b255 into master Aug 25, 2016
@jglick jglick deleted the generic-flow-analyzer branch February 1, 2017 22:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants