This is an automated email from the ASF dual-hosted git repository.
Cole-Greer pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
The following commit(s) were added to refs/heads/master by this push:
new 0ea801d036 CTR docs updates:
0ea801d036 is described below
commit 0ea801d036a711171e5dffdd012f8723d0e6216f
Author: Cole Greer <[email protected]>
AuthorDate: Sun Jul 19 14:48:23 2026 -0700
CTR docs updates:
- Fix dead and/or incorrect links
- Restructure HTTP streaming upgrade docs, simplifying and pushing context
to reference docs.
- Replace groovy script server examples with gremlin-lang
- Simplify Simplified Server Configuration section of upgrade docs.
- Amend introduction to the zoo graph and add GraphSON4 files for it.
---
data/tinkerpop-zoo.json | 13 ++
docs/src/dev/provider/index.asciidoc | 7 +-
docs/src/recipes/olap-spark-yarn.asciidoc | 3 -
docs/src/reference/gremlin-applications.asciidoc | 6 +-
docs/src/reference/gremlin-variants.asciidoc | 47 +++-
docs/src/reference/intro.asciidoc | 2 +-
docs/src/reference/the-graph.asciidoc | 5 +-
docs/src/reference/the-traversal.asciidoc | 4 +-
docs/src/upgrade/release-4.x.x.asciidoc | 253 +++++----------------
.../structure/IoDataGenerationTest.java | 11 +
10 files changed, 136 insertions(+), 215 deletions(-)
diff --git a/data/tinkerpop-zoo.json b/data/tinkerpop-zoo.json
new file mode 100644
index 0000000000..b86a868375
--- /dev/null
+++ b/data/tinkerpop-zoo.json
@@ -0,0 +1,13 @@
+{"id":{"@type":"g:Int32","@value":1},"label":["bird","endangered","animal","aquatic"],"inE":{"friendsWith":[{"id":{"@type":"g:Int32","@value":29},"outV":{"@type":"g:Int32","@value":3},"properties":{"since":{"@type":"g:Int32","@value":2020}}}]},"outE":{"livesIn":[{"id":{"@type":"g:Int32","@value":14},"inV":{"@type":"g:Int32","@value":11},"properties":{"since":{"@type":"g:Int32","@value":2020}}}],"friendsWith":[{"id":{"@type":"g:Int32","@value":28},"inV":{"@type":"g:Int32","@value":2},"pro
[...]
+{"id":{"@type":"g:Int32","@value":2},"label":["endangered","animal","reptile","aquatic"],"inE":{"friendsWith":[{"id":{"@type":"g:Int32","@value":28},"outV":{"@type":"g:Int32","@value":1},"properties":{"since":{"@type":"g:Int32","@value":2020}}}],"careFor":[{"id":{"@type":"g:Int32","@value":24},"outV":{"@type":"g:Int32","@value":13},"properties":{"specialty":"conservation"}}]},"outE":{"livesIn":[{"id":{"@type":"g:Int32","@value":15},"inV":{"@type":"g:Int32","@value":11},"properties":{"sin
[...]
+{"id":{"@type":"g:Int32","@value":3},"label":["mammal","animal","aquatic"],"outE":{"livesIn":[{"id":{"@type":"g:Int32","@value":16},"inV":{"@type":"g:Int32","@value":11},"properties":{"since":{"@type":"g:Int32","@value":2019}}}],"friendsWith":[{"id":{"@type":"g:Int32","@value":29},"inV":{"@type":"g:Int32","@value":1},"properties":{"since":{"@type":"g:Int32","@value":2020}}}]},"properties":{"species":[{"id":{"@type":"g:Int64","@value":16},"value":"bottlenose
dolphin"}],"name":[{"id":{"@ty [...]
+{"id":{"@type":"g:Int32","@value":4},"label":["nocturnal","animal","reptile"],"inE":{"eats":[{"id":{"@type":"g:Int32","@value":31},"outV":{"@type":"g:Int32","@value":10}}]},"outE":{"livesIn":[{"id":{"@type":"g:Int32","@value":18},"inV":{"@type":"g:Int32","@value":12},"properties":{"since":{"@type":"g:Int32","@value":2021}}}],"eats":[{"id":{"@type":"g:Int32","@value":32},"inV":{"@type":"g:Int32","@value":8}}]},"properties":{"venomous":[{"id":{"@type":"g:Int64","@value":27},"value":false}]
[...]
+{"id":{"@type":"g:Int32","@value":5},"label":["nocturnal","mammal","flying","animal"],"outE":{"livesIn":[{"id":{"@type":"g:Int32","@value":19},"inV":{"@type":"g:Int32","@value":12},"properties":{"since":{"@type":"g:Int32","@value":2022}}}],"avoids":[{"id":{"@type":"g:Int32","@value":33},"inV":{"@type":"g:Int32","@value":8}}]},"properties":{"species":[{"id":{"@type":"g:Int64","@value":31},"value":"fruit
bat"}],"name":[{"id":{"@type":"g:Int64","@value":30},"value":"echo"}],"weight":[{"id":
[...]
+{"id":{"@type":"g:Int32","@value":6},"label":["nocturnal","mammal","endangered","animal"],"inE":{"friendsWith":[{"id":{"@type":"g:Int32","@value":30},"outV":{"@type":"g:Int32","@value":7},"properties":{"since":{"@type":"g:Int32","@value":2022}}}],"careFor":[{"id":{"@type":"g:Int32","@value":25},"outV":{"@type":"g:Int32","@value":13},"properties":{"specialty":"conservation"}}]},"outE":{"livesIn":[{"id":{"@type":"g:Int32","@value":20},"inV":{"@type":"g:Int32","@value":12},"properties":{"si
[...]
+{"id":{"@type":"g:Int32","@value":7},"label":["mammal","endangered","animal"],"outE":{"livesIn":[{"id":{"@type":"g:Int32","@value":23},"inV":{"@type":"g:Int32","@value":12},"properties":{"since":{"@type":"g:Int32","@value":2019}}}],"friendsWith":[{"id":{"@type":"g:Int32","@value":30},"inV":{"@type":"g:Int32","@value":6},"properties":{"since":{"@type":"g:Int32","@value":2022}}}]},"properties":{"species":[{"id":{"@type":"g:Int64","@value":46},"value":"african
elephant"}],"name":[{"id":{"@t [...]
+{"id":{"@type":"g:Int32","@value":8},"label":["nocturnal","mammal","animal"],"inE":{"eats":[{"id":{"@type":"g:Int32","@value":32},"outV":{"@type":"g:Int32","@value":4}}],"avoids":[{"id":{"@type":"g:Int32","@value":33},"outV":{"@type":"g:Int32","@value":5}}]},"outE":{"livesIn":[{"id":{"@type":"g:Int32","@value":21},"inV":{"@type":"g:Int32","@value":12},"properties":{"since":{"@type":"g:Int32","@value":2024}}}]},"properties":{"species":[{"id":{"@type":"g:Int64","@value":54},"value":"harves
[...]
+{"id":{"@type":"g:Int32","@value":9},"label":["nocturnal","mammal","endangered","animal","aquatic"],"inE":{"careFor":[{"id":{"@type":"g:Int32","@value":26},"outV":{"@type":"g:Int32","@value":13},"properties":{"specialty":"conservation"}}]},"outE":{"livesIn":[{"id":{"@type":"g:Int32","@value":17},"inV":{"@type":"g:Int32","@value":11},"properties":{"since":{"@type":"g:Int32","@value":2023}}}]},"properties":{"species":[{"id":{"@type":"g:Int64","@value":61},"value":"fishing
cat"}],"name":[{" [...]
+{"id":{"@type":"g:Int32","@value":10},"label":["nocturnal","mammal","endangered","animal"],"inE":{"careFor":[{"id":{"@type":"g:Int32","@value":27},"outV":{"@type":"g:Int32","@value":13},"properties":{"specialty":"conservation"}}]},"outE":{"livesIn":[{"id":{"@type":"g:Int32","@value":22},"inV":{"@type":"g:Int32","@value":12},"properties":{"since":{"@type":"g:Int32","@value":2020}}}],"eats":[{"id":{"@type":"g:Int32","@value":31},"inV":{"@type":"g:Int32","@value":4}}]},"properties":{"specie
[...]
+{"id":{"@type":"g:Int32","@value":11},"label":["habitat","aquatic"],"inE":{"livesIn":[{"id":{"@type":"g:Int32","@value":16},"outV":{"@type":"g:Int32","@value":3},"properties":{"since":{"@type":"g:Int32","@value":2019}}},{"id":{"@type":"g:Int32","@value":17},"outV":{"@type":"g:Int32","@value":9},"properties":{"since":{"@type":"g:Int32","@value":2023}}},{"id":{"@type":"g:Int32","@value":14},"outV":{"@type":"g:Int32","@value":1},"properties":{"since":{"@type":"g:Int32","@value":2020}}},{"id
[...]
+{"id":{"@type":"g:Int32","@value":12},"label":["habitat"],"inE":{"livesIn":[{"id":{"@type":"g:Int32","@value":18},"outV":{"@type":"g:Int32","@value":4},"properties":{"since":{"@type":"g:Int32","@value":2021}}},{"id":{"@type":"g:Int32","@value":19},"outV":{"@type":"g:Int32","@value":5},"properties":{"since":{"@type":"g:Int32","@value":2022}}},{"id":{"@type":"g:Int32","@value":20},"outV":{"@type":"g:Int32","@value":6},"properties":{"since":{"@type":"g:Int32","@value":2023}}},{"id":{"@type"
[...]
+{"id":{"@type":"g:Int32","@value":13},"label":["person","veterinarian","keeper"],"outE":{"careFor":[{"id":{"@type":"g:Int32","@value":24},"inV":{"@type":"g:Int32","@value":2},"properties":{"specialty":"conservation"}},{"id":{"@type":"g:Int32","@value":25},"inV":{"@type":"g:Int32","@value":6},"properties":{"specialty":"conservation"}},{"id":{"@type":"g:Int32","@value":26},"inV":{"@type":"g:Int32","@value":9},"properties":{"specialty":"conservation"}},{"id":{"@type":"g:Int32","@value":27},
[...]
diff --git a/docs/src/dev/provider/index.asciidoc
b/docs/src/dev/provider/index.asciidoc
index 9262cb8191..3ef6ff585c 100644
--- a/docs/src/dev/provider/index.asciidoc
+++ b/docs/src/dev/provider/index.asciidoc
@@ -851,7 +851,7 @@ apply to embedded operations (i.e. running Gremlin in the
same JVM as the `Graph
==== JVM Test Suite
-IMPORTANT: 4.0.0-beta.2 Release - The final form of the TinkerPop test suite
for 4.0 is not wholly settled, but going
+IMPORTANT: 4.0.0-beta.3 Release - The final form of the TinkerPop test suite
for 4.0 is not wholly settled, but going
forward providers should focus on implementing the <<gherkin-tests-suite>> as
opposed to the JVM suite.
The JVM test suite is useful to graph system implementers who want to validate
that their `Graph` implementation is
@@ -1903,8 +1903,9 @@ With this in place, `Point` objects round-trip
transparently in both directions.
serialization, and the registry handles inbound reconstruction. The same
applies to any primitive type backed by a
registered `PrimitivePDTAdapter`.
-For driver users consuming PDTs, see the <<gremlin-variants,Gremlin Variants>>
reference documentation for
-each language driver.
+For driver users consuming PDTs, see the
+link:https://tinkerpop.apache.org/docs/x.y.z/reference/#gremlin-drivers-variants[Gremlin
Drivers and Variants]
+reference documentation for each language driver.
[[pdt-unregistered-values]]
==== Unregistered PDT Values
diff --git a/docs/src/recipes/olap-spark-yarn.asciidoc
b/docs/src/recipes/olap-spark-yarn.asciidoc
index 481054233b..12ea3c77d0 100644
--- a/docs/src/recipes/olap-spark-yarn.asciidoc
+++ b/docs/src/recipes/olap-spark-yarn.asciidoc
@@ -89,9 +89,6 @@ $ hdfs dfs -put data/tinkerpop-modern.kryo .
$ . bin/spark-yarn.sh
----
-WARNING: The Hadoop and Spark modules are not included in the 4.0.0-beta.2
distribution. This recipe will
-be restored in a future release.
-
[source,groovy]
----
gremlin> hadoop = System.getenv('HADOOP_HOME')
diff --git a/docs/src/reference/gremlin-applications.asciidoc
b/docs/src/reference/gremlin-applications.asciidoc
index 04e1d43e67..b2eb1435e6 100644
--- a/docs/src/reference/gremlin-applications.asciidoc
+++ b/docs/src/reference/gremlin-applications.asciidoc
@@ -781,7 +781,7 @@ bin/gremlin-server.sh conf/gremlin-server-modern.yaml
Once the server has started, issue a request. Here's an example with
link:http://curl.haxx.se/[cURL]:
[source,text]
-curl -X POST -d "{\"gremlin\":\"100-1\"}" "http://localhost:8182"
+curl -X POST -d "{\"gremlin\":\"g.inject(99)\"}" "http://localhost:8182"
returns:
@@ -808,7 +808,7 @@ returns:
It is also preferred that Gremlin scripts be parameterized when possible via
`parameters`:
[source,text]
-curl -X POST -d "{\"gremlin\":\"100-x\", \"parameters\":\"[x:1]\"}"
"http://localhost:8182"
+curl -X POST -d "{\"gremlin\":\"g.V(x)\", \"parameters\":\"[x:1]\"}"
"http://localhost:8182"
The `parameters` argument is a gremlin-lang string that encodes a map of
key/value pairs where the keys become available
as variables in the Gremlin script. Note that parameterization of requests is
critical to performance, as repeated
@@ -834,7 +834,7 @@ $ curl -H "Accept:text/plain" -X POST -d
"{\"gremlin\":\"g.V()\"}" "http://local
==>v[6]
----
-Finally, as Gremlin Server can host multiple `ScriptEngine` instances (e.g.
`gremlin-groovy`, `nashorn`), it is
+Finally, as Gremlin Server can host multiple `ScriptEngine` instances (e.g.
`gremlin-lang`, `gremlin-groovy`), it is
possible to define the language to utilize to process the request:
[source,text]
diff --git a/docs/src/reference/gremlin-variants.asciidoc
b/docs/src/reference/gremlin-variants.asciidoc
index c18d736f20..eab512a14f 100644
--- a/docs/src/reference/gremlin-variants.asciidoc
+++ b/docs/src/reference/gremlin-variants.asciidoc
@@ -1236,7 +1236,7 @@ serialized as JSON (`application/json`) and that behavior
is not configurable. T
controls only the `Accept` header sent with each request and the
deserialization of the response. For JVM-based
languages, there is a single option for response serialization: GraphBinary.
-IMPORTANT: 4.0.0-beta.2 Release - There is temporary support for GraphSON in
the Java driver which will help with
+IMPORTANT: 4.0.0-beta.3 Release - There is temporary support for GraphSON in
the Java driver which will help with
testing, but it is expected that the drivers will only support GraphBinary
when 4.0 is fully released.
It is important that the client and server have the same serializers
configured in the same way or else one or the
@@ -1260,6 +1260,11 @@ The `IoRegistry` tells the serializer what classes from
the graph provider to au
Gremlin Server roughly uses this same approach when it configures its
serializers, so using this same model will
ensure compatibility when making requests.
+[[gremlin-java-streaming]]
+The driver streams and deserializes a response incrementally as it arrives
only when `GraphBinaryMessageSerializerV4`
+is configured, which is the default. Any other `MessageSerializer`, such as a
GraphSON serializer, causes the driver to
+buffer the full response body before deserializing it.
+
[[gremlin-java-gvalue]]
=== GValue Parameterization
@@ -1915,6 +1920,7 @@ const g = traversal().with_(new
DriverRemoteConnection('http://localhost:8182/gr
Given that I/O operations in Node.js are asynchronous by default,
<<terminal-steps,Terminal Steps>> return a `Promise`:
+* `Traversal.hasNext()`: Returns a `Promise` with a `Boolean` indicating
whether a further result is available.
* `Traversal.toList()`: Returns a `Promise` with an `Array` as result value.
* `Traversal.next()`: Returns a `Promise` with a `{ value, done }` tuple as
result value, according to the
link:https://github.com/tc39/proposal-async-iteration[async iterator proposal].
@@ -2100,7 +2106,7 @@
link:https://github.com/apache/tinkerpop/blob/x.y.z/gremlin-js/gremlin-javascrip
[[gremlin-javascript-logging]]
=== Logging
-IMPORTANT: 4.0.0-beta.2 Release - Event-based logging is not yet implemented
for the HTTP driver. Listeners can be registered
+IMPORTANT: 4.0.0-beta.3 Release - Event-based logging is not yet implemented
for the HTTP driver. Listeners can be registered
but will not currently receive any events. This functionality is planned for a
future release.
The Gremlin-JavaScript driver emits connection events for logging and
monitoring, but these events are silently ignored unless a listener is
attached. Use the `addListener()` method to subscribe to events after creating
a `DriverRemoteConnection` or `Client`:
@@ -2302,6 +2308,7 @@ IMPORTANT: The preferred method for setting a per-request
timeout for scripts is
also use `g.with("timeoutMillis", 500)`. Scripts with multiple traversals and
multiple
timeouts will be interpreted as a sum of all timeouts identified in the script
for that request.
+[[gremlin-javascript-streaming]]
==== Streaming Results
`client.submit()` buffers the entire response before returning a `ResultSet`.
When working with larger result sets it
@@ -2967,6 +2974,42 @@
include::../../../gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Docs/Reference
The following options are allowed on a per-request basis in this fashion:
`batchSize`, `bulkResults`, `userAgent`, `materializeProperties`
and `timeoutMillis`. These options are available as constants on the
`Gremlin.Net.Driver.Tokens` class.
+[[gremlin-dotnet-streaming]]
+==== Streaming Results
+
+`GremlinClient.SubmitAsync<T>()` returns a `ResultSet<T>` that implements
`IAsyncEnumerable<T>`, backed by a channel
+that is filled as results are deserialized from the response. Results become
available to the caller incrementally
+as they are received. `ResultSet<T>` can be consumed directly with `await
foreach`, or materialized into a
+`List<T>` with `ToListAsync()` when that is more convenient:
+
+[source,csharp]
+----
+// consume incrementally
+var resultSet = await client.SubmitAsync<int>("g.inject(1,2,3)");
+await foreach (var item in resultSet) { }
+
+// or materialize into a list
+var otherResultSet = await client.SubmitAsync<int>("g.inject(1,2,3)");
+var list = await otherResultSet.ToListAsync();
+----
+
+Because results are consumed incrementally, a server-side error
(`ResponseException`) surfaces while the result
+set is being iterated rather than when `SubmitAsync()` is called. Error
handling should wrap the iteration or
+`ToListAsync()` call, not `SubmitAsync()` itself:
+
+[source,csharp]
+----
+var resultSet = await client.SubmitAsync<int>("invalid");
+try
+{
+ var list = await resultSet.ToListAsync();
+}
+catch (ResponseException ex) { }
+----
+
+The traversal API (`Next()`, `ToList()`, `HasNext()`, `ToSet()`, `Iterate()`)
blocks internally on the underlying
+async stream, so it throws `ResponseException` directly from those methods.
+
==== Request Interceptors
The `GremlinClient` supports request interceptors that can modify the HTTP
request before it is sent. Each interceptor
diff --git a/docs/src/reference/intro.asciidoc
b/docs/src/reference/intro.asciidoc
index 636faff8c2..f72e26ccbc 100644
--- a/docs/src/reference/intro.asciidoc
+++ b/docs/src/reference/intro.asciidoc
@@ -427,7 +427,7 @@ has two such formats that it uses with
link:https://tinkerpop.apache.org/docs/x.
link:https://tinkerpop.apache.org/docs/x.y.z/dev/io/#graphson[GraphSON]. Users
should prefer GraphBinary when available
in the programming language being used.
-IMPORTANT: 4.0.0-beta.2 Release - There is temporary support for GraphSON in
the Java driver which will help with
+IMPORTANT: 4.0.0-beta.3 Release - There is temporary support for GraphSON in
the Java driver which will help with
testing, but it is expected that the drivers will only support GraphBinary
when 4.0 is fully released.
A good example is the `subgraph()`-step which returns a `Graph` instance as
its result. The subgraph returned from
diff --git a/docs/src/reference/the-graph.asciidoc
b/docs/src/reference/the-graph.asciidoc
index 48fff3f219..5e7290af67 100644
--- a/docs/src/reference/the-graph.asciidoc
+++ b/docs/src/reference/the-graph.asciidoc
@@ -214,8 +214,9 @@ supported, what its default is or whether the choice is
left to the user to conf
[[the-zoo-toy-graph]]
TIP: A toy graph demonstrating multi-label vertices alongside a variety of
property types is available at
-`TinkerFactory.createTheZoo()` and `data/tinkerpop-zoo*`. "The Zoo" requires a
graph supporting a `LabelCardinality` of
-`ONE_OR_MORE` or `ZERO_OR_MORE`.
+`TinkerFactory.createTheZoo()` and `data/tinkerpop-zoo.json` (GraphSON 4.0).
"The Zoo" requires a graph supporting a
+`LabelCardinality` of `ONE_OR_MORE` or `ZERO_OR_MORE`. The dataset is subject
to change, so for now it is only
+available in this one format rather than the full complement of formats
provided for the other toy graphs.
.The Zoo
image::the-zoo-graph.png[width=685]
diff --git a/docs/src/reference/the-traversal.asciidoc
b/docs/src/reference/the-traversal.asciidoc
index 5a849914d9..5c56c9bba0 100644
--- a/docs/src/reference/the-traversal.asciidoc
+++ b/docs/src/reference/the-traversal.asciidoc
@@ -583,9 +583,9 @@ g.V().out('created').fill(results) <8>
g.addV('person').iterate() <9>
----
-<1> `hasNext()` determines whether there are available results (not supported
in `gremlin-javascript`).
+<1> `hasNext()` determines whether there are available results.
<2> `next()` will return the next result.
-<3> `next(n)` will return the next `n` results in a list (not supported in
`gremlin-javascript` or Gremlin.NET).
+<3> `next(n)` will return the next `n` results in a list.
<4> `tryNext()` will return an `Optional` and thus, is a composite of
`hasNext()`/`next()` (only supported for JVM languages).
<5> `toList()` will return all results in a list.
<6> `toSet()` will return all results in a set and thus, duplicates removed
(not supported in `gremlin-javascript`).
diff --git a/docs/src/upgrade/release-4.x.x.asciidoc
b/docs/src/upgrade/release-4.x.x.asciidoc
index dfae95e806..0c2d71dc6d 100644
--- a/docs/src/upgrade/release-4.x.x.asciidoc
+++ b/docs/src/upgrade/release-4.x.x.asciidoc
@@ -84,13 +84,13 @@ NOTE: The traversal-based form of `match` (e.g.
`g.V().match(as("a").out().as("b
TinkerPop 4.0.0 and will be removed in a future release. Users should migrate
to the new `match(String)` API.
TinkerPop ships a reference GQL engine for `match()` via the optional
`gql-gremlin` module. The engine implements the
-link:https://tinkerpop.apache.org/docs/4.0.0/reference/#tinkergql[TinkerGQL]
dialect — a deliberate minimal subset of
+link:https://tinkerpop.apache.org/docs/4.0.0-beta.3/reference/#tinkergql[TinkerGQL]
dialect — a deliberate minimal subset of
ISO GQL `MATCH` syntax — and works against any `Graph` implementation through
a thin set of default interface methods.
TinkerGraph uses it out of the box with no configuration required. Graph
providers that want to offer TinkerGQL support
can add the `gql-gremlin` dependency and register
`GqlDeclarativeMatchStrategy` as described in the
-link:https://tinkerpop.apache.org/docs/4.0.0/dev/provider/#tinkerpop-providers-tinkergql[provider
documentation].
+link:https://tinkerpop.apache.org/docs/4.0.0-beta.3/dev/provider/#tinkerpop-providers-tinkergql[provider
documentation].
-See:
link:https://tinkerpop.apache.org/docs/4.0.0/reference/#match-step[match()],
link:https://tinkerpop.apache.org/docs/4.0.0/reference/#tinkergql[TinkerGQL]
+See:
link:https://tinkerpop.apache.org/docs/4.0.0-beta.3/reference/#match-step[match()],
link:https://tinkerpop.apache.org/docs/4.0.0-beta.3/reference/#tinkergql[TinkerGQL]
==== Multi-Label Support
@@ -131,14 +131,14 @@ gremlin>
g.V().has('name','marko').dropLabel('employee').labels()
behaviors in detail.
See: link:https://issues.apache.org/jira/browse/TINKERPOP-3261[TINKERPOP-3261],
-link:https://tinkerpop.apache.org/docs/4.0.0/reference/#tinkergraph-multi-label[Multi-Label],
-link:https://tinkerpop.apache.org/docs/4.0.0/reference/#vertex-labels[Vertex
Labels],
-link:https://tinkerpop.apache.org/docs/4.0.0/reference/#labels-step[labels()],
-link:https://tinkerpop.apache.org/docs/4.0.0/reference/#addlabel-step[addLabel()],
-link:https://tinkerpop.apache.org/docs/4.0.0/reference/#elementmap-step[elementMap()],
-link:https://tinkerpop.apache.org/docs/4.0.0/reference/#valuemap-step[valueMap()],
-link:https://tinkerpop.apache.org/docs/4.0.0/reference/#mergevertex-step[mergeV()],
-link:https://tinkerpop.apache.org/docs/4.0.0/reference/#the-zoo-toy-graph[The
Zoo]
+link:https://tinkerpop.apache.org/docs/4.0.0-beta.3/reference/#tinkergraph-multi-label[Multi-Label],
+link:https://tinkerpop.apache.org/docs/4.0.0-beta.3/reference/#vertex-labels[Vertex
Labels],
+link:https://tinkerpop.apache.org/docs/4.0.0-beta.3/reference/#labels-step[labels()],
+link:https://tinkerpop.apache.org/docs/4.0.0-beta.3/reference/#addlabel-step[addLabel()],
+link:https://tinkerpop.apache.org/docs/4.0.0-beta.3/reference/#elementmap-step[elementMap()],
+link:https://tinkerpop.apache.org/docs/4.0.0-beta.3/reference/#valuemap-step[valueMap()],
+link:https://tinkerpop.apache.org/docs/4.0.0-beta.3/reference/#mergevertex-step[mergeV()],
+link:https://tinkerpop.apache.org/docs/4.0.0-beta.3/reference/#the-zoo-toy-graph[The
Zoo]
==== More Dynamic Arguments in Gremlin
@@ -262,7 +262,7 @@ and does not throw. Instead it returns a `TraversalSource`
bound to the existing
replaces the previous behavior where opening an already-open transaction threw
an exception, so review and remove any
code that catches or relies on a second open failing. For the semantics of
`begin()` and how it interacts with
`AUTO`/`MANUAL` transactions, see the
-link:https://tinkerpop.apache.org/docs/4.0.0/reference/#transactions[Traversal
Transactions] reference documentation.
+link:https://tinkerpop.apache.org/docs/4.0.0-beta.3/reference/#transactions[Traversal
Transactions] reference documentation.
See: link:https://issues.apache.org/jira/browse/TINKERPOP-3252[TINKERPOP-3252]
@@ -449,7 +449,7 @@ This is a breaking change with no backward-compatible
alias. The old `evaluation
Driver and server should be upgraded together. A driver sending the old
`evaluationTimeout` field to a 4.x server has
that field silently ignored and falls back to the server's default timeout, as
with any unrecognized request argument.
-See:
link:https://tinkerpop.apache.org/docs/4.0.0/reference/#gremlin-server[Gremlin
Server]
+See:
link:https://tinkerpop.apache.org/docs/4.0.0-beta.3/reference/#gremlin-server[Gremlin
Server]
==== Runtime Upgrades
@@ -497,12 +497,12 @@ that return interceptors and can be registered alongside
custom ones.
For full details on the interceptor API for each language variant, refer to
the RequestInterceptor section in
each GLV's documentation in the
-link:https://tinkerpop.apache.org/docs/4.0.0/reference/#gremlin-drivers-variants[Gremlin
Drivers and Variants]
+link:https://tinkerpop.apache.org/docs/4.0.0-beta.3/reference/#gremlin-drivers-variants[Gremlin
Drivers and Variants]
reference.
-See:
link:https://tinkerpop.apache.org/docs/4.0.0/reference/#gremlin-java-interceptors[Java],
link:https://tinkerpop.apache.org/docs/4.0.0/reference/#gremlin-python-interceptors[Python],
-link:https://tinkerpop.apache.org/docs/4.0.0/reference/#gremlin-javascript-interceptors[JavaScript],
link:https://tinkerpop.apache.org/docs/4.0.0/reference/#gremlin-dotnet-interceptors[.NET],
-link:https://tinkerpop.apache.org/docs/4.0.0/reference/#gremlin-go-interceptors[Go]
+See:
link:https://tinkerpop.apache.org/docs/4.0.0-beta.3/reference/#gremlin-java-interceptors[Java],
link:https://tinkerpop.apache.org/docs/4.0.0-beta.3/reference/#gremlin-python-interceptors[Python],
+link:https://tinkerpop.apache.org/docs/4.0.0-beta.3/reference/#gremlin-javascript-interceptors[JavaScript],
link:https://tinkerpop.apache.org/docs/4.0.0-beta.3/reference/#gremlin-dotnet-interceptors[.NET],
+link:https://tinkerpop.apache.org/docs/4.0.0-beta.3/reference/#gremlin-go-interceptors[Go]
==== Non-configurable Request Serialization
@@ -516,7 +516,7 @@ deserialization.
Applications that require a different request body encoding, such as
GraphBinary for a server that expects it, can
register a request interceptor that serializes the `RequestMessage` and
replaces the body and `Content-Type` header.
See the RequestInterceptor section for each GLV in the
-link:https://tinkerpop.apache.org/docs/4.0.0/reference/#gremlin-drivers-variants[Gremlin
Drivers and Variants]
+link:https://tinkerpop.apache.org/docs/4.0.0-beta.3/reference/#gremlin-drivers-variants[Gremlin
Drivers and Variants]
reference.
See: link:https://issues.apache.org/jira/browse/TINKERPOP-3250[TINKERPOP-3250]
@@ -641,102 +641,19 @@ See:
link:https://issues.apache.org/jira/browse/TINKERPOP-3249[TINKERPOP-3249]
==== HTTP Streaming Response Support
-With the move to HTTP, the drivers now deserialize responses incrementally,
delivering results to the caller as they
-arrive from the server rather than buffering the entire response before
processing. This reduces time-to-first-result
-and memory usage for large result sets. The runtime behavior and API impact
differ per language variant, as described
-below.
-
-===== Java
-
-Results are delivered to the `ResultSet` as they arrive. Streaming applies
only when using the default GraphBinary
-serializer, custom `MessageSerializer` implementations fall back to the
non-streaming pipeline that buffers the full
-response before deserialization. The `ResultSet` API is unchanged.
-
-===== Python
-
-The Python driver streams results through the configured `response_serializer`.
-
-Traversal API terminal steps (`next()`, `to_list()`, `has_next()`) are now
truly incremental. `next()` returns the
-first result as soon as it is deserialized from the wire, without waiting for
the full response. In 3.x, `next()`
-waited for all data to be buffered before returning.
-
-Note: `ResultSet` now yields individual items instead of lists when iterated.
Code that uses `results += result` to
-accumulate results from a `ResultSet` iterator must change to
`results.append(result)`. The `to_list()` and `all()` APIs
-are unaffected and remain the recommended way to collect results.
-
-===== JavaScript
-
-Traversal API terminal steps (`next()`, `toList()`, `hasNext()`) are now truly
incremental. `next()`
-returns the first result as soon as it is deserialized from the wire, without
waiting for the full response.
-In 3.x, `next()` waited for all WebSocket frames before returning.
-
-`Client.stream()` now returns an `AsyncGenerator` for direct incremental
consumption. This is a breaking change
-from 3.x where `stream()` returned a Node.js `Readable`. The new return type
works in both Node.js and browsers:
-
-[source,javascript]
-----
-// 3.x — Readable stream (no longer supported)
-const stream = client.stream('g.V()');
-stream.on('data', (resultSet) => { ... });
-
-// 4.0 — AsyncGenerator
-for await (const item of client.stream('g.V()', null)) {
- console.log(item);
- if (someCondition) break; // stops reading from the HTTP stream
-}
-----
-
-`Client.submit()` remains unchanged. It still buffers the full response and
returns `Promise<ResultSet>`.
-
-===== .NET
-
-The traversal API (`Next()`, `ToList()`, `HasNext()`, `ToSet()`, `Iterate()`)
in `Gremlin.Net` is unchanged. These
-methods block internally on the async stream, so existing traversal code works
without modification.
-
-`ResultSet<T>` no longer implements `IReadOnlyCollection<T>`. It now
implements `IAsyncEnumerable<T>`, backed by a
-`Channel<T>` that receives items from a background deserialization task. Users
who access `ResultSet<T>` directly
-via `GremlinClient.SubmitAsync<T>()` will need to update their code:
-
-[source,csharp]
-----
-// 3.x — ResultSet was IReadOnlyCollection<T>
-var resultSet = await client.SubmitAsync<int>("g.inject(1,2,3)");
-var count = resultSet.Count; // no longer available
-foreach (var item in resultSet) { } // no longer available
-
-// 4.0 — ResultSet is IAsyncEnumerable<T>
-var resultSet = await client.SubmitAsync<int>("g.inject(1,2,3)");
-var list = await resultSet.ToListAsync(); // materialize if you need Count
-await foreach (var item in resultSet) { } // async iteration
-----
-
-The `IMessageSerializer` interface has also changed: `DeserializeMessageAsync`
now accepts a `Stream` and returns
-`IAsyncEnumerable<object>` instead of accepting `byte[]` and returning
`Task<ResponseMessage<List<object>>>`.
-Custom serializer implementations will need to be updated. The
`ResponseMessage<T>` type has been removed.
-
-With streaming, server errors (`ResponseException`) are now thrown during
result iteration rather than during
-`SubmitAsync`. Code that catches `ResponseException` around `SubmitAsync`
should be updated to catch around the
-result consumption instead:
-
-[source,csharp]
-----
-// 3.x — exception thrown during SubmitAsync
-try {
- var resultSet = await client.SubmitAsync<int>("invalid");
-} catch (ResponseException ex) { ... }
-
-// 4.0 — exception thrown during iteration
-var resultSet = await client.SubmitAsync<int>("invalid");
-try {
- var list = await resultSet.ToListAsync();
-} catch (ResponseException ex) { ... }
-----
+The move to HTTP for TinkerPop 4 initially came with a tradeoff: Gremlin
Server's HTTP responses were buffered in
+full before the driver could begin deserializing them, so a request was not
usable by the caller until the server had
+finished producing every result. The drivers now deserialize an HTTP response
incrementally as it arrives, so a
+caller can begin working with the first results while the rest of the response
is still in transit. This reduces
+time-to-first-result and memory use for large result sets, and lets a caller
stop consuming and release the
+connection partway through a result set instead of waiting for it to complete.
-The traversal API is not affected — `Next()`, `ToList()`, etc. still throw
`ResponseException` directly since they
-block on the async stream internally.
+Streaming is active by default in all GLVs. The Reference Documentation covers
additional details and
+nuances for certain drivers specific to their implementation.
-See:
link:https://tinkerpop.apache.org/docs/4.0.0/reference/#connecting-via-http[Connecting
via HTTP],
-link:https://tinkerpop.apache.org/docs/4.0.0/reference/#gremlin-drivers-variants[Gremlin
Drivers and Variants]
+See:
link:https://tinkerpop.apache.org/docs/4.0.0-beta.3/reference/#gremlin-java-streaming[Java],
+link:https://tinkerpop.apache.org/docs/4.0.0-beta.3/reference/#gremlin-javascript-streaming[JavaScript],
+link:https://tinkerpop.apache.org/docs/4.0.0-beta.3/reference/#gremlin-dotnet-streaming[.NET]
==== More Secure Gremlin Server
@@ -756,92 +673,30 @@ release may remove Groovy as an installed option in the
server distribution alto
===== Simplified Server Configuration
-The most basic server setup, initializing a basic graph with a traversal
source, previously required a Groovy init
-script just to create the `g` binding. Now, any graph defined in the `graphs`
section automatically gets a
-`TraversalSource` according to these rules:
-
-* A graph named `graph` is implicitly bound to `g`
-* All others are bound to `g_<graph-name>` (e.g. `modern` gets `g_modern`)
-
-A fully functional minimal configuration is now simply:
-
-[source,yaml]
-----
-graphs: {
- graph: conf/tinkergraph-empty.properties}
-----
-
-===== Strategy Configuration via `traversalSources`
-
-For cases that require custom traversalSource naming or strategies on a
`TraversalSource` (e.g. `ReadOnlyStrategy`), the
-`traversalSources` list within a graph entry provides explicit control without
scripting:
+Basic server setup, such as initializing a graph with a traversal source or
loading sample data, previously required a
+Groovy init script just to create the `g` binding. That configuration is now
entirely declarative. A graph defined in
+the `graphs` section automatically gets a `TraversalSource` bound to it, and
the `traversalSources` list can define
+bindings explicitly, as well as optionally defining `with()`-configurations
and traversal strategies. Startup and
+shutdown logic that goes beyond configuration, such as loading a sample
dataset, is now handled by a Java-based
+`LifeCycleHook` referenced from the `lifecycleHooks` YAML section:
[source,yaml]
----
graphs: {
graph: {
configuration: conf/tinkergraph-empty.properties,
- traversalSources: [
- {name: g},
- {name: gReadOnly, gremlinExpression:
"g.withStrategies(ReadOnlyStrategy)"}]}}
-----
-
-Each entry specifies:
-
-- `name` (required): the binding name for the `TraversalSource`
-- `gremlinExpression` (optional): a Gremlin expression evaluated with a base
traversal source bound as `g`
-- `language` (optional): which `ScriptEngine` to use for the expression
(defaults to `gremlin-lang`, or the sole
-configured engine if only one is present)
-
-Graphs with explicit `traversalSources` entries are excluded from the
implicitly defined traversal sources described in
-the previous section.
-
-===== Java-Based Lifecycle Hooks
-
-For startup and shutdown logic that goes beyond declarative configuration such
as loading sample data, initializing
-caches, or custom setup, Java-based `LifeCycleHook` implementations can now
replace Groovy init scripts:
-
-[source,yaml]
-----
-lifecycleHooks:
- - className: org.apache.tinkerpop.gremlin.server.util.TinkerFactoryDataLoader
- config: {graph: graph, dataset: modern}
-----
-
-Each entry specifies a `className` implementing `LifeCycleHook` and an
optional `config` map passed to the hook's
-`init()` method. The built-in `TinkerFactoryDataLoader` supports datasets:
`airroutes`, `modern`, `classic`, `crew`,
-`grateful`, and `sink`.
-
-===== Migrating from Groovy Init Scripts
-
-Creating `TraversalSource` and `LifeCycleHook` instances via Groovy init
scripts is now deprecated. Existing scripts
-continue to work when `GremlinGroovyScriptEngine` is explicitly configured,
but a deprecation warning is logged at
-startup. Support for Groovy script initialization and customization may be
dropped in a future release.
-
-*Before (Groovy init script):*
-
-[source,groovy]
-----
-def globals = [:]
-globals << [hook : [
- onStartUp: { ctx ->
-
org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerFactory.generateModern(graph)
- }
-] as LifeCycleHook]
-globals << [g : traversal().withEmbedded(graph)]
-----
-
-*After (YAML only):*
-
-[source,yaml]
-----
-graphs: {
- graph: conf/tinkergraph-empty.properties}
+ traversalSources: [{name: g, gremlinExpression:
"g.withStrategies(ReadOnlyStrategy)"}]}}
lifecycleHooks:
- { className:
org.apache.tinkerpop.gremlin.server.util.TinkerFactoryDataLoader, config:
{graph: graph, dataset: modern}}
----
-The `g` binding is implicitly created from the `graph` entry. No
`scriptEngines` section is needed.
+Creating `TraversalSource` and `LifeCycleHook` instances via Groovy init
scripts is now deprecated in favor of this YAML
+configuration. Existing scripts continue to work when
`GremlinGroovyScriptEngine` is explicitly configured, but log a
+deprecation warning at startup, and support for them may be dropped in a
future release.
+
+See:
link:https://tinkerpop.apache.org/docs/4.0.0-beta.3/reference/#server-auto-traversal-sources[Auto-Created
TraversalSources],
+link:https://tinkerpop.apache.org/docs/4.0.0-beta.3/reference/#server-traversal-sources[Declarative
TraversalSources],
+link:https://tinkerpop.apache.org/docs/4.0.0-beta.3/reference/#server-lifecycle-hooks[LifeCycleHooks]
===== `ScriptEngine` Allowlist
@@ -910,9 +765,9 @@ The leading-underscore restriction on `GValue` names that
was present in 3.8.0 h
beginning with `_` are now accepted in Java and across all language variants.
The only remaining constraints are that
a `GValue` may not wrap another `GValue`, and (in the non-Java drivers) its
name may not be null.
-See:
link:https://tinkerpop.apache.org/docs/4.0.0/reference/#gremlin-java-gvalue[Java],
link:https://tinkerpop.apache.org/docs/4.0.0/reference/#gremlin-python-gvalue[Python],
-link:https://tinkerpop.apache.org/docs/4.0.0/reference/#gremlin-javascript-gvalue[JavaScript],
link:https://tinkerpop.apache.org/docs/4.0.0/reference/#gremlin-dotnet-gvalue[.NET],
-link:https://tinkerpop.apache.org/docs/4.0.0/reference/#gremlin-go-gvalue[Go]
+See:
link:https://tinkerpop.apache.org/docs/4.0.0-beta.3/reference/#gremlin-java-gvalue[Java],
link:https://tinkerpop.apache.org/docs/4.0.0-beta.3/reference/#gremlin-python-gvalue[Python],
+link:https://tinkerpop.apache.org/docs/4.0.0-beta.3/reference/#gremlin-javascript-gvalue[JavaScript],
link:https://tinkerpop.apache.org/docs/4.0.0-beta.3/reference/#gremlin-dotnet-gvalue[.NET],
+link:https://tinkerpop.apache.org/docs/4.0.0-beta.3/reference/#gremlin-go-gvalue[Go]
==== JavaScript Typed Numeric Wrappers
@@ -961,7 +816,7 @@ unwrap(toInt(29)); // 29
unwrap('hello'); // 'hello'
----
-See:
link:https://tinkerpop.apache.org/docs/4.0.0/reference/#gremlin-javascript-numeric-types[Numeric
Types]
+See:
link:https://tinkerpop.apache.org/docs/4.0.0-beta.3/reference/#gremlin-javascript-numeric-types[Numeric
Types]
==== Provider Defined Types
@@ -982,8 +837,8 @@ PDTs come in two flavors: *Composite* (a type name plus a
map of fields, for str
name plus a single opaque string value, for types expressible as a single
stringified value). The gremlin-lang grammar
supports both forms via the `PDT("name",[map])` and `PDT("name","value")`
literals respectively.
-See:
link:https://tinkerpop.apache.org/docs/4.0.0/dev/provider/#provider-defined-types[Provider
Defined Types],
-link:https://tinkerpop.apache.org/docs/4.0.0/dev/provider/#primitive-provider-defined-types[Primitive
Provider Defined Types]
+See:
link:https://tinkerpop.apache.org/docs/4.0.0-beta.3/dev/provider/#provider-defined-types[Provider
Defined Types],
+link:https://tinkerpop.apache.org/docs/4.0.0-beta.3/dev/provider/#primitive-provider-defined-types[Primitive
Provider Defined Types]
==== Tree No Longer Extends HashMap
@@ -1078,7 +933,7 @@ into either of these behaviors. The reference
implementation of `elementMap()` a
"singlelabel" semantics for an unconfigured traversal. All providers must
either skip the `@SingleLabelDefault` or the
`@MultiLabelDefault` tagged feature tests depending on their choice of default
behavior.
-See the
link:https://tinkerpop.apache.org/docs/4.0.0/reference/#vertex-labels[vertex
labels] reference docs more details
+See the
link:https://tinkerpop.apache.org/docs/4.0.0-beta.3/reference/#vertex-labels[vertex
labels] reference docs more details
regarding the new vertex label cardinalities.
===== Traversal-Accepting Steps - HasContainer Guard
@@ -1128,7 +983,7 @@ GLVs: interceptors receive a mutable HTTP request object,
can modify headers/bod
the request body to JSON after all interceptors have run.
For the full specification of how interceptors should behave, see the
-link:https://tinkerpop.apache.org/docs/4.0.0/dev/provider/#_http_request_interceptor[HTTP
Request Interceptor]
+link:https://tinkerpop.apache.org/docs/4.0.0-beta.3/dev/provider/#_http_request_interceptor[HTTP
Request Interceptor]
section in the provider documentation.
===== match() Support
@@ -1162,7 +1017,7 @@ first use and caches them for the lifetime of the graph,
sharing the planner's q
traversals. Optional performance hints are available via
`countVerticesByLabel()`, `countEdgesByLabel()`,
and `Graph.Index`. See `GqlMatchStep` and `GqlDeclarativeMatchStrategy` in
`gql-gremlin` for the complete
reference implementation, and the
-link:https://tinkerpop.apache.org/docs/4.0.0/dev/provider/#tinkerpop-providers-tinkergql[provider
documentation]
+link:https://tinkerpop.apache.org/docs/4.0.0-beta.3/dev/provider/#tinkerpop-providers-tinkergql[provider
documentation]
for wiring instructions.
== TinkerPop 4.0.0-beta.2
@@ -2067,7 +1922,7 @@ Server, you have to implement your own `Channelizer`.
If you are a provider that makes use of the Gremlin Server, you may need to
update server configuration YAML files that
you provide to your users. With the change from WebSockets to HTTP, some of
the previous default values are invalid and
-some of the fields no longer exist. See
link:https://tinkerpop.apache.org/docs/4.0.0/reference/#_configuring_2[options]
+some of the fields no longer exist. See
link:https://tinkerpop.apache.org/docs/4.0.0-beta.1/reference/#_configuring_2[options]
for an updated list. One of the most important changes is to the `Channelizer`
configuration as only the
`HttpChannelizer` remains and the rest have been removed.
@@ -2083,7 +1938,7 @@ required.
HTTP/1.1 is now the only supported application-layer protocol and WebSockets
support is dropped. Please follow the
instructions in the
-link:https://tinkerpop.apache.org/docs/4.0.0/dev/provider/#_graph_driver_provider_requirements[provider
documentation]
+link:https://tinkerpop.apache.org/docs/4.0.0-beta.1/dev/provider/#_graph_driver_provider_requirements[provider
documentation]
for more detailed information. The subprotocol remains fairly similar but has
been adjusted to work better with HTTP.
Also, the move to HTTP means that SASL has been removed as an authentication
mechanism and only HTTP basic remains.
diff --git
a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/IoDataGenerationTest.java
b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/IoDataGenerationTest.java
index a30caa0717..ce6f7e84f7 100644
---
a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/IoDataGenerationTest.java
+++
b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/IoDataGenerationTest.java
@@ -537,6 +537,17 @@ public class IoDataGenerationTest {
os.close();
}
+ /**
+ * No assertions. Just write out the graph for convenience.
+ */
+ @Test
+ public void shouldWriteDEFAULTTheZooGraphAsGraphSONV4() throws IOException
{
+ final OutputStream os = new FileOutputStream(new File(tempPath,
"tinkerpop-zoo.json"));
+
GraphSONWriter.build().mapper(GraphSONMapper.build().version(GraphSONVersion.V4_0).create()).create()
+ .writeGraph(os, TinkerFactory.createTheZoo());
+ os.close();
+ }
+
@Test
public void shouldWriteSampleForGremlinServer() throws IOException {
final Graph g = TinkerGraph.open();