You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by co...@apache.org on 2025/10/27 04:40:42 UTC
(tinkerpop) 02/03: add docs
This is an automated email from the ASF dual-hosted git repository.
colegreer pushed a commit to branch sideEffectBarrier
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit 7fdc024bd6790b1855841f39917dc0b520db0218
Author: Cole-Greer <Co...@improving.com>
AuthorDate: Sun Oct 26 21:36:52 2025 -0700
add docs
---
docs/src/dev/provider/gremlin-semantics.asciidoc | 3 +-
docs/src/reference/the-traversal.asciidoc | 9 +++--
docs/src/upgrade/release-3.8.x.asciidoc | 43 ++++++++++++++++++++++++
3 files changed, 49 insertions(+), 6 deletions(-)
diff --git a/docs/src/dev/provider/gremlin-semantics.asciidoc b/docs/src/dev/provider/gremlin-semantics.asciidoc
index 8ac0f17449..a0e6aad47d 100644
--- a/docs/src/dev/provider/gremlin-semantics.asciidoc
+++ b/docs/src/dev/provider/gremlin-semantics.asciidoc
@@ -1549,7 +1549,8 @@ key.
The `groupCount()` step can be used as both a map step and a side-effect step. As a map step, it returns a `Map` with
the counted objects as keys and their counts as values. As a side-effect step, it stores the counts in a side-effect and
-passes the traverser to the next step unchanged.
+passes the traverser to the next step unchanged. Note that both the map and side-effect forms of this step are barriers
+must fully iterate the traversal before returning any results.
*Exceptions*
diff --git a/docs/src/reference/the-traversal.asciidoc b/docs/src/reference/the-traversal.asciidoc
index a4a241b927..1f7e2df933 100644
--- a/docs/src/reference/the-traversal.asciidoc
+++ b/docs/src/reference/the-traversal.asciidoc
@@ -5043,20 +5043,19 @@ g.V().has('name','josh').out('created').values('name').
<1> When the `tree()` is created, vertex 3 and 5 are unique and thus, form unique branches in the tree structure.
<2> When the `tree()` is `by()`-modulated by `label`, then vertex 3 and 5 are both "software" and thus are merged to a single node in the tree.
-The `tree()` step can also take a side-effect key as an argument. When using this form, the `Tree` is constructed
-lazily, such that it becomes possible to assess its contents as each traverser passes through.
+The `tree()` step can also take a side-effect key as an argument. When using this form, the `Tree` is is built up in a
+side-effect as each traverser passes through. The `Tree` can later be accessed by either `select()` or `cap()`.
[gremlin-groovy,modern]
----
g.V().has('name','josh').out('created').values('name').tree('x').select('x')
----
-You can use `cap()` step to force `tree()` to consume the traversal stream eagerly and output results similar to prior
-examples.
+It is possible to force lazy construction of the tree by embedding inside a `local()` step.
[gremlin-groovy,modern]
----
-g.V().has('name','josh').out('created').values('name').tree('x').cap('x')
+g.V().has('name','josh').out('created').values('name').local(tree('x')).select('x')
----
*Additional References*
diff --git a/docs/src/upgrade/release-3.8.x.asciidoc b/docs/src/upgrade/release-3.8.x.asciidoc
index 38f366c2f0..ad8c7c3e1e 100644
--- a/docs/src/upgrade/release-3.8.x.asciidoc
+++ b/docs/src/upgrade/release-3.8.x.asciidoc
@@ -637,6 +637,49 @@ g.with_strategies(OptionsStrategy(options=myOptions))
g.with_strategies(OptionsStrategy(**myOptions))
----
+==== Add barrier to most SideEffect steps
+
+Prior to 3.8.0, the `group(String)`, `groupCount(String)`, `tree(String)` and `subgraph(String)` steps were non-blocking,
+in that they allowed traversers to pass through without fully iterating the traversal and fully computing the side
+effect. Consider the following example:
+
+[source, groovy]
+----
+// 3.7.4
+gremlin> g.V().groupCount("x").select("x")
+==>[v[1]:1]
+==>[v[1]:1,v[2]:1]
+==>[v[1]:1,v[2]:1,v[3]:1]
+==>[v[1]:1,v[2]:1,v[3]:1,v[4]:1]
+==>[v[1]:1,v[2]:1,v[3]:1,v[4]:1,v[5]:1]
+==>[v[1]:1,v[2]:1,v[3]:1,v[4]:1,v[5]:1,v[6]:1]
+----
+
+As of 3.8.0, all of these steps now implement `LocalBarrier`, meaning that the traversal is fully iterated before any
+results are passed. This guarantees that a traversal will produce the same results regardless of it is evaluated in a
+lazy (DFS) or eager (BFS) fashion. Any usages which are reliant on the previous "one-at-a-time" accumulation of results
+can still achieve this by embedding the side effect step inside a `local()` step.
+
+[source, groovy]
+----
+// 3.8.0
+gremlin> g.V().groupCount("x").select("x")
+==>[v[1]:1,v[2]:1,v[3]:1,v[4]:1,v[5]:1,v[6]:1]
+==>[v[1]:1,v[2]:1,v[3]:1,v[4]:1,v[5]:1,v[6]:1]
+==>[v[1]:1,v[2]:1,v[3]:1,v[4]:1,v[5]:1,v[6]:1]
+==>[v[1]:1,v[2]:1,v[3]:1,v[4]:1,v[5]:1,v[6]:1]
+==>[v[1]:1,v[2]:1,v[3]:1,v[4]:1,v[5]:1,v[6]:1]
+==>[v[1]:1,v[2]:1,v[3]:1,v[4]:1,v[5]:1,v[6]:1]
+
+gremlin> g.V().local(groupCount("x")).select("x")
+==>[v[1]:1]
+==>[v[1]:1,v[2]:1]
+==>[v[1]:1,v[2]:1,v[3]:1]
+==>[v[1]:1,v[2]:1,v[3]:1,v[4]:1]
+==>[v[1]:1,v[2]:1,v[3]:1,v[4]:1,v[5]:1]
+==>[v[1]:1,v[2]:1,v[3]:1,v[4]:1,v[5]:1,v[6]:1]
+----
+
==== choose() Semantics
Several enhancements and clarifications have been made to the `choose()` step in TinkerPop 3.8.0 to improve its behavior