Skip to content

Commit a4ae684

Browse files
committed
Reorganize 4.x upgrade notes
Moves the dynamic-arguments section up near the multi-label content and groups the Java and .NET runtime upgrades under a single Runtime Upgrades heading. Nests the evaluationTimeout rename under connection options, fixes the Inconfigurable/Non-configurable heading, and trims redundant notes.
1 parent f2865aa commit a4ae684

1 file changed

Lines changed: 69 additions & 82 deletions

File tree

docs/src/upgrade/release-4.x.x.asciidoc

Lines changed: 69 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,63 @@ See: link:https://issues.apache.org/jira/browse/TINKERPOP-3261[TINKERPOP-3261],
163163
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/#labels-step[labels()],
164164
link:https://tinkerpop.apache.org/docs/4.0.0/reference/#the-zoo-toy-graph[The Zoo]
165165
166+
==== More Dynamic Arguments in Gremlin
167+
168+
Prior to 4.0, comparing a traverser's value against a dynamically computed reference required several coordinated
169+
step labels and `where()` comparison. For example, finding all people older than "marko" previously required:
170+
171+
[source,groovy]
172+
----
173+
// Old way: label marko's age, compare via where()
174+
gremlin> g.V(1).values("age").as("markosAge").
175+
......1> V().hasLabel("person").as("p").
176+
......2> values("age").as("otherAge").
177+
......3> where("otherAge", gt("markosAge")).
178+
......4> select("p").values("name")
179+
==>josh
180+
==>peter
181+
----
182+
183+
This pattern required several coordinated step labels and could not easily compose with other predicates. With
184+
traversal-accepting arguments, the same query becomes a single, readable step:
185+
186+
[source,groovy]
187+
----
188+
// New way: traversal inside the predicate
189+
gremlin> g.V().has("age", P.gt(__.V(1).values("age"))).values("name")
190+
==>josh
191+
==>peter
192+
----
193+
194+
Steps and predicates that previously only accepted literal values now accept child traversals resolved per-traverser
195+
at runtime. Affected steps: `has()`, `hasId()`, `hasKey()`, `hasLabel()`, `hasValue()`, `V()`, `E()`, `property()`,
196+
`is()`, `where(P)`, and all `P` and `TextP` predicates.
197+
198+
[source,groovy]
199+
----
200+
// Multi-source filtering with within() - combine sources in one traversal with union().fold()
201+
gremlin> g.V().has("name", P.within(__.union(__.V(1).out("knows").values("name"), __.constant("peter")).fold()))
202+
==>v[2]
203+
==>v[4]
204+
==>v[6]
205+
206+
// Set multiple properties from a computed Map
207+
gremlin> g.V(4).property(__.V(1).project("friendCount").by(__.out("knows").count()))
208+
==>v[4]
209+
----
210+
211+
Users should look to simplify existing traversals that use `as()`/`where()`/`select()` patterns solely to compare
212+
a traverser against a dynamically computed value. In particular, patterns of the form
213+
`__.as("x")...where("x", P.gt("y"))` can often be replaced with a single `has()` or `is()` step containing
214+
a traversal predicate.
215+
216+
See: <<has-step,has()>>, <<v-step,V()>>, <<property-step,property()>>, <<is-step,is()>>,
217+
<<where-step,where()>>,
218+
link:https://issues.apache.org/jira/browse/TINKERPOP-2586[TINKERPOP-2586],
219+
link:https://issues.apache.org/jira/browse/TINKERPOP-2777[TINKERPOP-2777],
220+
link:https://issues.apache.org/jira/browse/TINKERPOP-3005[TINKERPOP-3005],
221+
link:https://issues.apache.org/jira/browse/TINKERPOP-1463[TINKERPOP-1463]
222+
166223
==== Transactions
167224
168225
TinkerPop 4.0 brings a set of related transaction changes across the drivers and embedded graphs: explicit remote
@@ -180,13 +237,6 @@ Each GLV provides two entry points:
180237
* **Traversal API**: `g.tx().begin()` returns a transaction-bound `GraphTraversalSource`
181238
* **Driver API**: `client.transact()` (or `client.Transact()` in .NET) returns a `Transaction` with `submit()` methods
182239
183-
Key behaviors consistent across all GLVs:
184-
185-
* Transactions are not thread-safe. All operations must be sequential.
186-
* The default close behavior is rollback (partial work discarded if commit is not called explicitly).
187-
* Transactions are single-use. After commit or rollback, a new transaction must be created.
188-
* `gtx.tx()` returns the same transaction object (enabling `gtx.tx().commit()` pattern from the Traversal API).
189-
190240
See the <<gremlin-drivers-variants,Gremlin Drivers and Variants>> reference documentation for language-specific
191241
syntax and examples.
192242
@@ -245,7 +295,7 @@ configuring close behavior and always rollback.
245295
All GLVs now support the `subgraph()` step. Previously, calling `subgraph()` from a GLV produced an unknown-type error
246296
because the variant could not interpret the `Graph` payload that the server returned. Applications can now extract a
247297
portion of a remote graph as part of a normal traversal and inspect its vertices and edges directly from the client,
248-
without having to re-issue queries to reconstruct the result. See: <<subgraph-step>>.
298+
without having to re-issue queries to reconstruct the result.
249299
250300
In the GLVs, the result is a detached snapshot of the captured vertices and edges, not a traversable `Graph` instance.
251301
It cannot be passed to `traversal().with(...)`, and mutating its collections has no effect on the source graph. To
@@ -257,9 +307,9 @@ re-query elements against the original graph, extract their ids and call `g.V(id
257307
link:https://gremlator.com[Gremlator] has been rebuilt entirely in JavaScript as a browser-based single-page
258308
application and is now an official part of the Apache TinkerPop project. It translates Gremlin queries into
259309
equivalent representations in all supported language variants: Groovy, Java, Python, JavaScript, Go, .NET, and an
260-
anonymized form. The original gremlator.com was a prototype built by TinkerPop committer Dave Bechberger; the
261-
previous implementation required Java and a running Gremlin Server, whereas the new version runs entirely in the
262-
browser with no server infrastructure needed.
310+
anonymized form. The original gremlator.com was a prototype built by TinkerPop committer Dave Bechberger. This previous
311+
implementation required Java and a running Gremlin Server, whereas the new version runs entirely in the browser with
312+
no server infrastructure needed.
263313
264314
==== Bindings are now Parameters
265315
@@ -327,11 +377,6 @@ TinkerPop 4.x standardizes connection option names and defaults across all five
327377
.NET, Go, and JavaScript). Each driver using its language-idiomatic casing (`camelCase`, `PascalCase`, or `snake_case`).
328378
These renames are breaking, the old option names have been removed.
329379
330-
NOTE: Timeouts use a millisecond-suffixed canonical name (`connectTimeoutMillis`, `readTimeoutMillis`,
331-
`idleTimeoutMillis`, `keepAliveTimeMillis`, and the `_millis` form in Python). Java, Go, .NET, and Python also accept an
332-
idiomatic duration companion for the same setting (Java `Duration`, Go `time.Duration`, .NET `TimeSpan`, Python seconds);
333-
set only one form per option. JavaScript exposes only the millisecond form.
334-
335380
===== Standardized options (cross-GLV)
336381
337382
The table lists each standardized option by driver. Defaults are shown in parentheses; "n/a" means the driver does not
@@ -396,7 +441,7 @@ These change runtime behavior on upgrade even if you do not change your configur
396441
397442
See: link:https://lists.apache.org/thread/yqtr2wnb1kq2pqqq4002cz511q5o0bkg[[DISCUSS] Standardizing GLV connection options in TinkerPop 4].
398443
399-
==== Renaming `evaluationTimeout` to `timeoutMillis`
444+
===== Renaming `evaluationTimeout` to `timeoutMillis`
400445
401446
The per-request execution timeout is now referred to by a single name, `timeoutMillis`, everywhere. `timeoutMillis` is
402447
the maximum time in milliseconds that a request is allowed to execute on the server before it times out. It can be
@@ -421,7 +466,11 @@ that field silently ignored and falls back to the server's default timeout, as w
421466
422467
See: link:https://tinkerpop.apache.org/docs/4.0.0/reference/#gremlin-server[Gremlin Server]
423468
424-
==== Java Runtime Upgrade
469+
==== Runtime Upgrades
470+
471+
TinkerPop 4.0 introduces major upgrades to its various runtimes.
472+
473+
===== Java Runtime Upgrade
425474
426475
TinkerPop 4.0 raises the minimum Java version from 11 to 17 for both building and running, and adds support for running
427476
on Java 21 and Java 25. Supporting Java 25 required upgrading Groovy to 4.0.32, Hadoop to 3.4.3, Spark to 4.1.x, and
@@ -431,7 +480,7 @@ As with the earlier JDK 17 support, some libraries still rely on deep reflection
431480
library used with OLAP), so it may be necessary to `--add-opens` or `--add-exports` certain modules at runtime. The set
432481
of options used by TinkerPop's own tests is unchanged.
433482
434-
==== .NET Runtime Upgrade
483+
===== .NET Runtime Upgrade
435484
436485
The minimum target framework is now `net8.0` (previously `netstandard2.0;net6.0`).
437486
@@ -470,7 +519,7 @@ See: link:https://tinkerpop.apache.org/docs/4.0.0/reference/#gremlin-java-interc
470519
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],
471520
link:https://tinkerpop.apache.org/docs/4.0.0/reference/#gremlin-go-interceptors[Go]
472521
473-
==== Inconfigurable Request Serialization
522+
==== Non-configurable Request Serialization
474523
475524
TinkerPop 3.x drivers used a single serializer configuration (for example, `serializer` in the Java driver or
476525
`message_serializer` in Python) that controlled both how a `RequestMessage` was serialized on the way to the server
@@ -487,63 +536,6 @@ reference.
487536
488537
See: link:https://issues.apache.org/jira/browse/TINKERPOP-3250[TINKERPOP-3250]
489538
490-
==== Expanding Dynamic Arguments to Additional Steps
491-
492-
Prior to 4.0, comparing a traverser's value against a dynamically computed reference required several coordinated
493-
step labels and `where()` comparison. For example, finding all people older than "marko" previously required:
494-
495-
[source,groovy]
496-
----
497-
// Old way: label marko's age, compare via where()
498-
gremlin> g.V(1).values("age").as("markosAge").
499-
......1> V().hasLabel("person").as("p").
500-
......2> values("age").as("otherAge").
501-
......3> where("otherAge", gt("markosAge")).
502-
......4> select("p").values("name")
503-
==>josh
504-
==>peter
505-
----
506-
507-
This pattern required several coordinated step labels and could not easily compose with other predicates. With
508-
traversal-accepting arguments, the same query becomes a single, readable step:
509-
510-
[source,groovy]
511-
----
512-
// New way: traversal inside the predicate
513-
gremlin> g.V().has("age", P.gt(__.V(1).values("age"))).values("name")
514-
==>josh
515-
==>peter
516-
----
517-
518-
Steps and predicates that previously only accepted literal values now accept child traversals resolved per-traverser
519-
at runtime. Affected steps: `has()`, `hasId()`, `hasKey()`, `hasLabel()`, `hasValue()`, `V()`, `E()`, `property()`,
520-
`is()`, `where(P)`, and all `P` and `TextP` predicates.
521-
522-
[source,groovy]
523-
----
524-
// Multi-source filtering with within() - combine sources in one traversal with union().fold()
525-
gremlin> g.V().has("name", P.within(__.union(__.V(1).out("knows").values("name"), __.constant("peter")).fold()))
526-
==>v[2]
527-
==>v[4]
528-
==>v[6]
529-
530-
// Set multiple properties from a computed Map
531-
gremlin> g.V(4).property(__.V(1).project("friendCount").by(__.out("knows").count()))
532-
==>v[4]
533-
----
534-
535-
Users should look to simplify existing traversals that use `as()`/`where()`/`select()` patterns solely to compare
536-
a traverser against a dynamically computed value. In particular, patterns of the form
537-
`__.as("x")...where("x", P.gt("y"))` can often be replaced with a single `has()` or `is()` step containing
538-
a traversal predicate.
539-
540-
See: <<has-step,has()>>, <<v-step,V()>>, <<property-step,property()>>, <<is-step,is()>>,
541-
<<where-step,where()>>,
542-
link:https://issues.apache.org/jira/browse/TINKERPOP-2586[TINKERPOP-2586],
543-
link:https://issues.apache.org/jira/browse/TINKERPOP-2777[TINKERPOP-2777],
544-
link:https://issues.apache.org/jira/browse/TINKERPOP-3005[TINKERPOP-3005],
545-
link:https://issues.apache.org/jira/browse/TINKERPOP-1463[TINKERPOP-1463]
546-
547539
==== New Gremlin-Lang Literals
548540
549541
The canonical Gremlin grammar now includes literal syntax for `Character`, `Duration`, and `Binary` types. These
@@ -579,11 +571,6 @@ negative durations.
579571
g.V().has("length",P.gt(Duration(3600,0)))
580572
----
581573
582-
NOTE: Python's `timedelta` has microsecond resolution, so sub-microsecond nanosecond values are truncated.
583-
.NET's `TimeSpan` has 100-nanosecond tick resolution, so sub-100ns values are truncated.
584-
585-
NOTE: Duration is not supported in gremlin-javascript.
586-
587574
===== Binary
588575
589576
A binary literal wraps a base64-encoded string:

0 commit comments

Comments
 (0)