This is an automated email from the ASF dual-hosted git repository.
spmallette pushed a commit to branch travis-fix
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
The following commit(s) were added to refs/heads/travis-fix by this push:
new 7d1770c merge 3.4-dev
7d1770c is described below
commit 7d1770c766583a33ba0b52ea58330341651ebc06
Author: Stephen Mallette <[email protected]>
AuthorDate: Tue Oct 13 15:06:13 2020 -0400
merge 3.4-dev
---
CHANGELOG.asciidoc | 2 +-
docs/src/reference/gremlin-variants.asciidoc | 40 ++++++++++++++++++----
docs/src/upgrade/release-3.4.x.asciidoc | 32 +++++++++++++++++
.../Driver/Remote/DriverRemoteConnection.cs | 30 ++++++++++++++--
gremlin-dotnet/src/Gremlin.Net/Driver/Tokens.cs | 28 ++++++++++-----
.../Process/Traversal/GraphTraversalSource.cs | 26 +++++++++-----
.../Docs/Reference/GremlinVariantsTests.cs | 18 ++++++++++
.../DriverRemoteConnection/GraphTraversalTests.cs | 15 ++++----
.../apache/tinkerpop/gremlin/driver/Tokens.java | 39 +++++++++++++++++++++
9 files changed, 196 insertions(+), 34 deletions(-)
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 22b3ed1..660a1f8 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -98,7 +98,7 @@
image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
* Removed `Connection` from `Connection Pool` when server closes a connection
with no pending requests in Java Driver.
* Improved initialization time of Java Driver if the default serializer is
replaced.
* Deprecated `withGraph()` in favor of `withEmbedded()` on
`AnonymousTraversalSource`.
-* Added support for per-request level configurations, like timeouts, in Python
and Javascript.
+* Added support for per-request level configurations, like timeouts, in .NET,
Python and Javascript.
* Fixed bug in Javascript `Translator` that wasn't handling child traversals
well.
* Implemented `AutoCloseable` on `MultiIterator`.
* Fixed an iterator leak in `HasContainer`.
diff --git a/docs/src/reference/gremlin-variants.asciidoc
b/docs/src/reference/gremlin-variants.asciidoc
index 0852d5d..bb2bfc7 100644
--- a/docs/src/reference/gremlin-variants.asciidoc
+++ b/docs/src/reference/gremlin-variants.asciidoc
@@ -216,7 +216,7 @@ List<Vertex> vertices = g.with(Tokens.ARGS_EVAL_TIMEOUT,
500L).V().out("knows").
----
The following options are allowed on a per-request basis in this fashion:
`batchSize`, `requestId`, `userAgent` and
-`evaluationTimeout` (formerly 'scriptEvaluationTimeout' which is also
supported but now deprecated). Use of `Tokens`
+`evaluationTimeout` (formerly `scriptEvaluationTimeout` which is also
supported but now deprecated). Use of `Tokens`
to reference these options is preferred.
anchor:java-imports[]
@@ -714,11 +714,11 @@ Some connection options can also be set on individual
requests made through the
[source,python]
----
-vertices = g.with_('evaluationTimeout', 500L).V().out('knows').toList()
+vertices = g.with_('evaluationTimeout', 500).V().out('knows').toList()
----
The following options are allowed on a per-request basis in this fashion:
`batchSize`, `requestId`, `userAgent` and
-`evaluationTimeout` (formerly 'scriptEvaluationTimeout' which is also
supported but now deprecated).
+`evaluationTimeout` (formerly `scriptEvaluationTimeout` which is also
supported but now deprecated).
anchor:python-imports[]
[[gremlin-python-imports]]
@@ -941,7 +941,7 @@ result_set =
client.submit('g.V().repeat(both()).times(100)', result_options={'e
----
The following options are allowed on a per-request basis in this fashion:
`batchSize`, `requestId`, `userAgent` and
-`evaluationTimeout` (formerly 'scriptEvaluationTimeout' which is also
supported but now deprecated).
+`evaluationTimeout` (formerly `scriptEvaluationTimeout` which is also
supported but now deprecated).
[[gremlin-python-dsl]]
=== Domain Specific Languages
@@ -1102,6 +1102,18 @@ the remote end.
include::../../../gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Docs/Reference/GremlinVariantsTests.cs[tags=connecting]
----
+Some connection options can also be set on individual requests using the
`With()` step on the `TraversalSource`.
+For instance to set request timeout to 500 milliseconds:
+
+[source,csharp]
+----
+var l = g.With(Tokens.ArgsEvalTimeout, 500).V().Out("knows").Count().ToList();
+----
+
+The following options are allowed on a per-request basis in this fashion:
`batchSize`, `requestId`, `userAgent` and
+`evaluationTimeout` (formerly `scriptEvaluationTimeout` which is also
supported but now deprecated). These options are
+available as constants on the `Gremlin.Net.Driver.Tokens` class.
+
[[gremlin-dotnet-imports]]
=== Common Imports
@@ -1227,6 +1239,20 @@ var gremlinServer = new GremlinServer("localhost", 8182);
var client = new GremlinClient(gremlinServer, sessionId:
Guid.NewGuid().ToString()))
----
+==== Per Request Settings
+
+The `GremlinClient.Submit()` functions accept an option to build a raw
`RequestMessage`. A good use-case for this
+feature is to set a per-request override to the `evaluationTimeout` so that it
only applies to the current request.
+
+[source,csharp]
+----
+include::../../../gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Docs/Reference/GremlinVariantsTests.cs[tags=submittingScriptsWithTimeout]
+----
+
+The following options are allowed on a per-request basis in this fashion:
`batchSize`, `requestId`, `userAgent` and
+`evaluationTimeout` (formerly `scriptEvaluationTimeout` which is also
supported but now deprecated). These options are
+available as constants on the `Gremlin.Net.Driver.Tokens` class.
+
anchor:gremlin-net-dsl[]
[[gremlin-dotnet-dsl]]
=== Domain Specific Languages
@@ -1418,11 +1444,11 @@ Some connection options can also be set on individual
requests made through the
[source,javascript]
----
-const vertices = await g.with_('evaluationTimeout',
500L).V().out('knows').toList()
+const vertices = await g.with_('evaluationTimeout',
500).V().out('knows').toList()
----
The following options are allowed on a per-request basis in this fashion:
`batchSize`, `requestId`, `userAgent` and
-`evaluationTimeout` (formerly 'scriptEvaluationTimeout' which is also
supported but now deprecated).
+`evaluationTimeout` (formerly `scriptEvaluationTimeout` which is also
supported but now deprecated).
[[gremlin-javascript-imports]]
=== Common Imports
@@ -1504,7 +1530,7 @@ const result = await
client.submit("g.V().repeat(both()).times(100)", null, { ev
----
The following options are allowed on a per-request basis in this fashion:
`batchSize`, `requestId`, `userAgent` and
-`evaluationTimeout` (formerly 'scriptEvaluationTimeout' which is also
supported but now deprecated).
+`evaluationTimeout` (formerly `scriptEvaluationTimeout` which is also
supported but now deprecated).
[[gremlin-javascript-dsl]]
=== Domain Specific Languages
diff --git a/docs/src/upgrade/release-3.4.x.asciidoc
b/docs/src/upgrade/release-3.4.x.asciidoc
index d647d0a..7c688aa 100644
--- a/docs/src/upgrade/release-3.4.x.asciidoc
+++ b/docs/src/upgrade/release-3.4.x.asciidoc
@@ -79,6 +79,38 @@ const sg = g.withStrategies(
See: link:https://issues.apache.org/jira/browse/TINKERPOP-2054[TINKERPOP-2054]
+==== Per Request Options
+
+With Java it has been possible to pass per-request settings for both scripts
and bytecode. While Javascript, Python,
+and .NET allowed this in various ways, it wasn't quite as convenient as Java,
nor was it well documented. In this
+release, the approach for making this sort of per-request configurations is
now much more consistent across languages.
+We see this most evident in bytecode based requests:
+
+[source,java,tab]
+----
+g.with(Tokens.ARGS_EVAL_TIMEOUT, 500L).V().out("knows");
+----
+[source,csharp]
+----
+g.With(Tokens.ArgsEvalTimeout, 500).V().Out("knows").Count();
+----
+[source,javascript]
+----
+g.with_('evaluationTimeout', 500).V().out('knows');
+----
+[source,python]
+----
+g.with_('evaluationTimeout', 500).V().out('knows')
+----
+
+Please see the new "Per Request Settings" sections for each language in the
+<<gremlin-drivers-variants, Gremlin Drivers and Variants>> section for
information on how to send scripts with specific
+request configurations.
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-2296[TINKERPOP-2296],
+link:https://issues.apache.org/jira/browse/TINKERPOP-2420[TINKERPOP-2420],
+link:https://issues.apache.org/jira/browse/TINKERPOP-2421[TINKERPOP-2421]
+
=== Upgrading for Providers
==== Graph System Providers
diff --git
a/gremlin-dotnet/src/Gremlin.Net/Driver/Remote/DriverRemoteConnection.cs
b/gremlin-dotnet/src/Gremlin.Net/Driver/Remote/DriverRemoteConnection.cs
index a52cb87..510a2f4 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/Remote/DriverRemoteConnection.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/Remote/DriverRemoteConnection.cs
@@ -27,6 +27,7 @@ using System.Threading.Tasks;
using Gremlin.Net.Driver.Messages;
using Gremlin.Net.Process.Remote;
using Gremlin.Net.Process.Traversal;
+using Gremlin.Net.Process.Traversal.Strategy.Decoration;
namespace Gremlin.Net.Driver.Remote
{
@@ -37,6 +38,15 @@ namespace Gremlin.Net.Driver.Remote
{
private readonly IGremlinClient _client;
private readonly string _traversalSource;
+
+ /// <summary>
+ /// Filter on these keys provided to OptionsStrategy and apply them to
the request. Note that
+ /// "scriptEvaluationTimeout" was deprecated in 3.3.9 but still
supported in server implementations and will
+ /// be removed in later versions.
+ /// </summary>
+ private readonly List<String> _allowedKeys = new List<string>
+ {Tokens.ArgsEvalTimeout, "scriptEvaluationTimeout",
Tokens.ArgsBatchSize,
+ Tokens.RequestId, Tokens.ArgsUserAgent};
/// <summary>
/// Initializes a new <see cref="IRemoteConnection" /> using "g"
as the default remote TraversalSource name.
@@ -78,9 +88,23 @@ namespace Gremlin.Net.Driver.Remote
.Processor(Tokens.ProcessorTraversal)
.OverrideRequestId(requestid)
.AddArgument(Tokens.ArgsGremlin, bytecode)
- .AddArgument(Tokens.ArgsAliases, new Dictionary<string,
string> {{"g", _traversalSource}})
- .Create();
- return await
_client.SubmitAsync<Traverser>(requestMsg).ConfigureAwait(false);
+ .AddArgument(Tokens.ArgsAliases, new Dictionary<string,
string> {{"g", _traversalSource}});
+
+ var optionsStrategyInst = bytecode.SourceInstructions.Find(
+ s => s.OperatorName == "withStrategies" && s.Arguments[0] is
OptionsStrategy);
+ if (optionsStrategyInst != null)
+ {
+ OptionsStrategy optionsStrategy =
optionsStrategyInst.Arguments[0];
+ foreach (KeyValuePair<string,dynamic> pair in
optionsStrategy.Configuration)
+ {
+ if (_allowedKeys.Contains(pair.Key))
+ {
+ requestMsg.AddArgument(pair.Key, pair.Value);
+ }
+ }
+ }
+
+ return await
_client.SubmitAsync<Traverser>(requestMsg.Create()).ConfigureAwait(false);
}
/// <inheritdoc />
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/Tokens.cs
b/gremlin-dotnet/src/Gremlin.Net/Driver/Tokens.cs
index f8d0140..f35b128 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/Tokens.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/Tokens.cs
@@ -32,6 +32,11 @@ namespace Gremlin.Net.Driver
public class Tokens
{
/// <summary>
+ /// The key for the unique identifier of the request.
+ /// </summary>
+ public static string RequestId = "requestId";
+
+ /// <summary>
/// Operation used by the client to authenticate itself.
/// </summary>
public static string OpsAuthentication = "authentication";
@@ -62,24 +67,25 @@ namespace Gremlin.Net.Driver
public static string ProcessorSession = "session";
/// <summary>
- /// Argument name that allows to defines the number of iterations
each ResponseMessage should contain - overrides the
- /// resultIterationBatchSize server setting.
+ /// Argument name that allows the definition of the number of
items each ResponseMessage should
+ /// contain from a particular result - overrides the
resultIterationBatchSize server setting.
/// </summary>
public static string ArgsBatchSize = "batchSize";
/// <summary>
- /// Argument name that allows to provide a map of key/value pairs
to apply as variables in the context of the Gremlin
- /// script.
+ /// Argument name that allows definition of a map of key/value
pairs to apply as variables in the
+ /// context of the Gremlin request sent to the server.
/// </summary>
public static string ArgsBindings = "bindings";
/// <summary>
- /// Argument name that allows to define aliases that represent
globally bound Graph and TraversalSource objects.
+ /// Argument name that allows definition of alias names for Graph
and TraversalSource objects on the
+ /// remote system.
/// </summary>
public static string ArgsAliases = "aliases";
/// <summary>
- /// Argument name that corresponds to the Traversal to evaluate.
+ /// Argument name that corresponds to the Gremlin to evaluate.
/// </summary>
public static string ArgsGremlin = "gremlin";
@@ -89,12 +95,18 @@ namespace Gremlin.Net.Driver
public static string ArgsSession = "session";
/// <summary>
- /// Argument name that allows to change the flavor of Gremlin used
(e.g. gremlin-groovy).
+ /// Argument name that allows a value that is a custom string that
the user can pass to a server that
+ /// might accept it for purpose of identifying the kind of client
it came from.
+ /// </summary>
+ public static string ArgsUserAgent = "userAgent";
+
+ /// <summary>
+ /// Argument name that allows definition of the flavor of Gremlin
used (e.g. gremlin-groovy) to process the request.
/// </summary>
public static string ArgsLanguage = "language";
/// <summary>
- /// Argument name that allows to override the server setting that
determines the maximum time to wait for a
+ /// Argument name that allows the override of the server setting
that determines the maximum time to wait for a
/// request to execute on the server.
/// </summary>
public static string ArgsEvalTimeout = "evaluationTimeout";
diff --git
a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversalSource.cs
b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversalSource.cs
index 920d6d8..db4c521 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversalSource.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversalSource.cs
@@ -71,23 +71,31 @@ namespace Gremlin.Net.Process.Traversal
Bytecode = bytecode;
}
-
public GraphTraversalSource With(string key)
{
- var source = new GraphTraversalSource(new
List<ITraversalStrategy>(TraversalStrategies),
- new Bytecode(Bytecode));
- source.Bytecode.AddSource("with", key);
- return source;
+ return With(key, true);
}
public GraphTraversalSource With(string key, object value)
{
- var source = new GraphTraversalSource(new
List<ITraversalStrategy>(TraversalStrategies),
- new Bytecode(Bytecode));
- source.Bytecode.AddSource("with", key, value);
- return source;
+ var optionsStrategyInst = Bytecode.SourceInstructions.Find(
+ inst => inst.OperatorName == "withStrategies" &&
inst.Arguments[0] is OptionsStrategy);
+ OptionsStrategy optionsStrategy;
+
+ if (optionsStrategyInst == null)
+ {
+ optionsStrategy = new OptionsStrategy();
+ optionsStrategy.Configuration[key] = value;
+ return WithStrategies(optionsStrategy);
+ }
+
+ optionsStrategy = optionsStrategyInst.Arguments[0];
+ optionsStrategy.Configuration[key] = value;
+ return new GraphTraversalSource(new
List<ITraversalStrategy>(TraversalStrategies),
+ new Bytecode(Bytecode));
}
+
public GraphTraversalSource WithBulk(bool useBulk)
{
var source = new GraphTraversalSource(new
List<ITraversalStrategy>(TraversalStrategies),
diff --git
a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Docs/Reference/GremlinVariantsTests.cs
b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Docs/Reference/GremlinVariantsTests.cs
index 723afa6..61264e0 100644
---
a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Docs/Reference/GremlinVariantsTests.cs
+++
b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Docs/Reference/GremlinVariantsTests.cs
@@ -23,6 +23,7 @@
using System.Threading.Tasks;
using Gremlin.Net.Driver;
+using Gremlin.Net.Driver.Messages;
using Gremlin.Net.Driver.Remote;
using Gremlin.Net.IntegrationTest.Process.Traversal.DriverRemoteConnection;
using Gremlin.Net.Process.Traversal;
@@ -105,6 +106,23 @@ using (var gremlinClient = new
GremlinClient(gremlinServer))
}
// end::submittingScripts[]
}
+
+ [Fact(Skip="No Server under localhost")]
+ public async Task SubmittingScriptsWithTimeoutTest()
+ {
+// tag::submittingScriptsWithTimeout[]
+var gremlinServer = new GremlinServer("localhost", 8182);
+using (var gremlinClient = new GremlinClient(gremlinServer))
+{
+ var response =
+ await gremlinClient.SubmitWithSingleResultAsync<string>(
+ RequestMessage.Build(Tokens.OpsEval).
+ AddArgument(Tokens.ArgsGremlin, "g.V().count()").
+ AddArgument(Tokens.ArgsEvalTimeout, 500).
+ Create());
+}
+// end::submittingScriptsWithTimeout[]
+ }
[Fact(Skip = "No Server under localhost")]
public void SubmittingScriptsWithAuthenticationTest()
diff --git
a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/GraphTraversalTests.cs
b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/GraphTraversalTests.cs
index 5e11e33..89597a3 100644
---
a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/GraphTraversalTests.cs
+++
b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/GraphTraversalTests.cs
@@ -24,6 +24,9 @@
using System.Linq;
using System.Collections.Generic;
using System.Threading.Tasks;
+using Gremlin.Net.Driver;
+using Gremlin.Net.Driver.Exceptions;
+using Gremlin.Net.Driver.Messages;
using Gremlin.Net.Process.Traversal;
using Gremlin.Net.Structure;
using Xunit;
@@ -201,8 +204,6 @@ namespace
Gremlin.Net.IntegrationTest.Process.Traversal.DriverRemoteConnection
[Fact]
public void ShouldUseOptionsInTraversal()
{
- // smoke test to validate serialization of OptionsStrategy. no way
to really validate this from an integration
- // test perspective because there's no way to access the internals
of the strategy via bytecode
var connection = _connectionFactory.CreateRemoteConnection();
var options = new Dictionary<string,object>
{
@@ -210,13 +211,15 @@ namespace
Gremlin.Net.IntegrationTest.Process.Traversal.DriverRemoteConnection
{"y", true}
};
var g =
AnonymousTraversalSource.Traversal().WithRemote(connection);
-
- var b = new Bindings();
+
var countWithStrategy = g.WithStrategies(new
OptionsStrategy(options)).V().Count().Next();
Assert.Equal(6, countWithStrategy);
+
+ var responseException = Assert.Throws<ResponseException>(() =>
+ g.With("y").With("x",
"test").With(Tokens.ArgsEvalTimeout, 10).Inject(1)
+
.SideEffect(Lambda.Groovy("Thread.sleep(10000)")).Iterate());
+ Assert.Equal(ResponseStatusCode.ServerTimeout,
responseException.StatusCode);
- var countWith = g.With("x", "test").With("y",
true).V().Count().Next();
- Assert.Equal(6, countWith);
}
[Fact]
diff --git
a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Tokens.java
b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Tokens.java
index 867edf2..68b5ebd 100644
---
a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Tokens.java
+++
b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Tokens.java
@@ -18,6 +18,10 @@
*/
package org.apache.tinkerpop.gremlin.driver;
+import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
+import org.apache.tinkerpop.gremlin.structure.Graph;
+
/**
* String constants used in gremlin-driver and gremlin-server.
*
@@ -32,20 +36,55 @@ public final class Tokens {
public static final String OPS_INVALID = "invalid";
public static final String OPS_CLOSE = "close";
+ /**
+ * The key for the unique identifier of the request.
+ */
public static final String REQUEST_ID = "requestId";
+ /**
+ * Argument name that allows definition of the number of iterations each
{@link ResponseMessage} should contain -
+ * overrides the @{code resultIterationBatchSize} server setting.
+ */
public static final String ARGS_BATCH_SIZE = "batchSize";
+
+ /**
+ * Argument name that allows to provide a map of key/value pairs to apply
as variables in the context of
+ * the Gremlin request sent to the server.
+ */
public static final String ARGS_BINDINGS = "bindings";
+
+ /**
+ * Argument name that allows definition of alias names for {@link Graph}
and {@link TraversalSource} objects on
+ * the remote system.
+ */
public static final String ARGS_ALIASES = "aliases";
public static final String ARGS_FORCE = "force";
+
+ /**
+ * Argument name that corresponds to the Gremlin to evaluate.
+ */
public static final String ARGS_GREMLIN = "gremlin";
+
+ /**
+ * Argument name that allows definition of the flavor of Gremlin used
(e.g. gremlin-groovy) to process the request.
+ */
public static final String ARGS_LANGUAGE = "language";
+
+ /**
+ * Argument name that allows the override of the server setting that
determines the maximum time to wait for a
+ * request to execute on the server.
+ */
public static final String ARGS_EVAL_TIMEOUT = "evaluationTimeout";
public static final String ARGS_HOST = "host";
public static final String ARGS_SESSION = "session";
public static final String ARGS_MANAGE_TRANSACTION = "manageTransaction";
public static final String ARGS_SASL = "sasl";
public static final String ARGS_SASL_MECHANISM = "saslMechanism";
+
+ /**
+ * A value that is a custom string that the user can pass to a server that
might accept it for purpose of
+ * identifying the kind of client it came from.
+ */
public static final String ARGS_USER_AGENT = "userAgent";
public static final String VAL_TRAVERSAL_SOURCE_ALIAS = "g";