Skip to content

Commit c3c3baa

Browse files
committed
CTR: Docs updates for strategies to reflect GValue awareness
1 parent d4a48be commit c3c3baa

File tree

2 files changed

+81
-4
lines changed

2 files changed

+81
-4
lines changed

docs/src/reference/the-traversal.asciidoc

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5861,7 +5861,7 @@ public final class TinkerGraphStepStrategy extends AbstractTraversalStrategy<Tra
58615861
if (TraversalHelper.onGraphComputer(traversal))
58625862
return;
58635863
5864-
for (GraphStep originalGraphStep : TraversalHelper.getStepsOfClass(GraphStep.class, traversal)) {
5864+
for (GraphStepContract originalGraphStep : TraversalHelper.getStepsOfAssignableClass(GraphStepContract.class, traversal)) {
58655865
TinkerGraphStep<?, ?> tinkerGraphStep = new TinkerGraphStep<>(originalGraphStep);
58665866
TraversalHelper.replaceStep(originalGraphStep, tinkerGraphStep, traversal);
58675867
Step<?, ?> currentStep = tinkerGraphStep.getNextStep();
@@ -5935,6 +5935,58 @@ g.V().hasLabel('person'). <1>
59355935
<8> `PathRetractionStrategy` will remove paths from the traversers and increase the likelihood of bulking as path data is not required after `select('b')`.
59365936
<9> `AdjacentToIncidentStrategy` will turn `out()` into `outE()` to increase data access locality.
59375937
5938+
==== A note on Traversal Parameters
5939+
5940+
Certain gremlin steps are able to accept parameterized arguments in the form of one of more `GValue` objects. Please see
5941+
the <<traversal-parameterization,parameterizable steps documentation>> for a complete listing of such steps.
5942+
5943+
When authoring strategies that interact with parameterizable steps, it's important to work with `StepContract` interfaces
5944+
rather than concrete step classes. Parameterizable steps can exist as either concrete implementations or as placeholder
5945+
steps that hold `GValue` objects (parameterized arguments). The placeholders are temporary proxies for the concrete
5946+
steps which exist during strategy execution, but must be "reduced" to concrete steps prior to traversal execution. Both
5947+
concrete and placeholder forms of a step implement the same contract interface, allowing strategies to work uniformly
5948+
with either representation.
5949+
5950+
[source,java]
5951+
----
5952+
// Use contract interfaces for parameterizable steps
5953+
for (GraphStepContract originalGraphStep : TraversalHelper.getStepsOfAssignableClass(GraphStepContract.class, traversal)) {
5954+
// Work with all matching instances of a step through its contract <1>
5955+
}
5956+
if (step instanceof GraphStepContract) {
5957+
GraphStepContract graphStep = (GraphStepContract) step;
5958+
// Work with the step through its contract
5959+
}
5960+
5961+
// Instead of checking concrete classes
5962+
if (step instanceof GraphStep) {
5963+
// This approach has the risk of missing instances of GraphStepPlaceholder
5964+
}
5965+
----
5966+
5967+
<1> Note that use of `TraversalHelper.getStepsOfAssignableClass(GraphStepContract.class, traversal))` will match all
5968+
instances of TinkerPop's reference implementations of `GraphStepContract`, ie `GraphStep` and `GraphStepPlaceholder`,
5969+
but will not match and provider specific implementations of the contract such as `TinkerGraphStep`. Similar rules apply
5970+
to matching any StepContract via this method.
5971+
5972+
The contract-based approach ensures strategies work correctly whether the step is in its concrete form or placeholder
5973+
form with `GValue` parameters. Common contract interfaces include:
5974+
5975+
* `AddVertexStepContract` - for `AddVertexStep` and `AddVertexStartStep`
5976+
* `AddEdgeStepContract` - for `AddEdgeStep` and `AddEdgeStartStep`
5977+
* `VertexStepContract` - for `VertexStep`
5978+
* `GraphStepContract` - for `GraphStep`
5979+
* `MergeStepContract` - for `MergeVertexStep` and `MergeEdgeStep`
5980+
5981+
Strategy authors should consult the `GValueReductionStrategy` to understand how placeholder steps are converted to
5982+
concrete steps, and consider whether their strategy should execute before or after this conversion based on whether
5983+
they need to work with `GValue` objects or concrete step implementations. As this is an `OptimizationStrategy`, any
5984+
`ProviderOptimizationStrategy` are excluded by default from the above considerations regarding parameterizable steps.
5985+
Any providers who wish to leverage `GValue` in a `ProviderOptimizationStrategy` should first remove
5986+
`GValueReductionStrategy`, and take ownership over ensuring all placeholder steps are reduced to concrete steps
5987+
afterward. `ProviderGValueReductionStrategy` is offered for such purposes.
5988+
----
5989+
59385990
=== EdgeLabelVerificationStrategy
59395991
59405992
`EdgeLabelVerificationStrategy` prevents traversals from writing traversals that do not explicitly specify and edge
@@ -6061,6 +6113,34 @@ new transaction immediately following the `commit()` that raises the events. The
60616113
may also not behave as "snapshots" at the time of their creation as they are "live" references to actual database
60626114
elements.
60636115
6116+
=== GValueReductionStrategy
6117+
6118+
`GValueReductionStrategy` converts placeholder steps that hold `GValue` objects to their concrete implementations.
6119+
While not an optimization in and of itself, the `GValue` functionality provides a mechanism for traversal optimization
6120+
and parameterization, so this strategy falls in the optimization category. Converting to concrete steps at this stage
6121+
also allows provider optimization strategies to execute on concrete steps rather than step interfaces, which are much
6122+
easier to reason about for the vast majority of providers.
6123+
6124+
This strategy is automatically applied and typically does not need to be explicitly configured by users. However,
6125+
providers hoping to do more advanced optimizations that require `GValue` objects to be present for their strategies
6126+
will need to remove `GValueReductionStrategy` and offer their own mechanism for converting step placeholders to
6127+
concrete steps. `ProviderGValueReductionStrategy` is a base class available to help with this need.
6128+
6129+
The strategy operates by calling the `reduce()` method on any step that implements `GValueHolder`:
6130+
6131+
[source,java]
6132+
----
6133+
@Override
6134+
public void apply(final Traversal.Admin<?, ?> traversal) {
6135+
final List<Step> steps = traversal.getSteps();
6136+
for (int i = 0; i < steps.size(); i++) {
6137+
if (steps.get(i) instanceof GValueHolder) {
6138+
((GValueHolder) steps.get(i)).reduce();
6139+
}
6140+
}
6141+
}
6142+
----
6143+
60646144
[[partitionstrategy]]
60656145
=== PartitionStrategy
60666146

gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/provider/ProviderGValueReductionStrategy.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,8 @@
2424
import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
2525
import org.apache.tinkerpop.gremlin.process.traversal.step.GValueHolder;
2626
import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
27-
import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
2827

29-
import java.util.Collections;
3028
import java.util.List;
31-
import java.util.Set;
3229

3330
/**
3431
* Converts placeholder steps that hold {@link GValue} objects to their concrete implementations. While not an

0 commit comments

Comments
 (0)