This is an automated email from the ASF dual-hosted git repository. colegreer pushed a commit to branch tp4Docs in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit 71bbda6551589eb89f087e0ca66d4300986288d3 Author: Cole-Greer <[email protected]> AuthorDate: Fri Nov 15 10:12:17 2024 -0800 WIP Update docs to reflect console changes --- docs/src/reference/gremlin-applications.asciidoc | 284 ++--------------------- docs/src/reference/gremlin-variants.asciidoc | 2 +- 2 files changed, 15 insertions(+), 271 deletions(-) diff --git a/docs/src/reference/gremlin-applications.asciidoc b/docs/src/reference/gremlin-applications.asciidoc index 2f1d7f3d58..92d7e093c7 100644 --- a/docs/src/reference/gremlin-applications.asciidoc +++ b/docs/src/reference/gremlin-applications.asciidoc @@ -134,55 +134,16 @@ some other useful operations. The following table outlines the most commonly us |:install |:+ |Imports a Maven library and its dependencies into the Console. |:uninstall |:- |Removes a Maven library and its dependencies. A restart of the console is required for removal to fully take effect. |:plugin |:pin |Plugin management functions to list, activate and deactivate available plugins. -|:remote |:rem |Configures a "remote" context where Gremlin or results of Gremlin will be processed via usage of `:submit`. -|:submit |:> |Submit Gremlin to the currently active context defined by `:remote`. -|:bytecode |:bc |Provides options for translating and evaluating `Bytecode` for debugging purposes. |========================================================= -Many of the above commands are described elsewhere or are generally self-explanatory, but the `:bytecode` command -could use some additional explanation. The following code shows example usage: - -[source,text] ----- -gremlin> :bytecode from g.V().out('knows') <1> -==>{"@type":"g:Bytecode","@value":{"step":[["V"],["out","knows"]]}} -gremlin> :bytecode translate g {"@type":"g:Bytecode","@value":{"step":[["V"],["out","knows"]]}} <2> -==>g.V().out("knows") -gremlin> m = GraphSONMapper.build().create() -==>org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONMapper@69d6a7cd -gremlin> :bc config m <3> -==>Configured bytecode serializer -gremlin> :bc from g.V().property('d',java.time.YearMonth.now()) <4> -Could not find a type identifier for the class : class java.time.Month. Make sure the value to serialize has a type identifier registered for its class. (through reference chain: java.time.YearMonth["month"]) -Type ':help' or ':h' for help. -Display stack trace? [yN]n -gremlin> :bc reset <5> -==>Bytecode serializer reset to GraphSON 3.0 with extensions and TinkerGraph serializers -gremlin> :bc from g.V().property('d',java.time.YearMonth.now()) -==>{"@type":"g:Bytecode","@value":{"step":[["V"],["property","d",{"@type":"gx:YearMonth","@value":"2020-11"}]]}} ----- - -<1> Generates a GraphSON 3.0 representation of the traversal as bytecode. -<2> Converts bytecode in GraphSON 3.0 format to a traversal string. -<3> Configure a custom `GraphSONMapper` for the `:bytecode` command to use which can be helpful when working with -custom classes from different graph providers. The `config` option can take a `GraphSONMapper` argument as shown or -one or more `IoRegistry` or `SimpleModule` implementations that will plug into the default `GraphSONMapper` constructed -by the `:bytecode` command. The default will configure for GraphSON 3.0 with the extensions module and, if present, -the `TinkerIoRegistry` from TinkerGraph. -<4> Note that the `YearMonth` will not serialize because `m` did not configure the extensions module. -<5> After `reset` it works properly once more. - -NOTE: The Console does expose the `:record` command which is inherited from the Groovy Shell. This command works well -with local commands, but may record session outputs differently for `:remote` commands. If there is a need to use -`:record` it may be best to manually create a `Cluster` object and issue commands that way so that they evaluate -locally in the shell. +NOTE: The Console also exposes the `:record` command which is inherited from the Groovy Shell. === Interrupting Evaluations If there is some input that is taking too long to evaluate or to iterate through, use `ctrl+c` to attempt to interrupt that process. It is an "attempt" in the sense that the long running process is only informed of the interruption by the user and must respond to it (as with any call to `interrupt()` on a `Thread`). A `Traversal` will typically respond -to such requests as do most commands, including `:remote` operations. +to such requests as do most commands. [source,text] ---- @@ -568,7 +529,7 @@ Map<String,Object> params = new HashMap<>(); params.put("name","marko"); List<Result> list = client.submit("g.V().has('person','name',name).out('knows')", params).all().get(); -// bytecode +// traversal GraphTraversalSource g = traversal().with(DriverRemoteConnection.using("localhost",8182,"g")); List<Vertex> list = g.V().has("person","name","marko").out("knows").toList(); ---- @@ -579,7 +540,7 @@ def cluster = Cluster.open() def client = cluster.connect() def list = client.submit("g.V().has('person','name',name).out('knows')", [name: "marko"]).all().get(); -// bytecode +// traversal def g = traversal().with(DriverRemoteConnection.using("localhost",8182,"g")) def list = g.V().has('person','name','marko').out('knows').toList() ---- @@ -594,7 +555,7 @@ const client = new Client('ws://localhost:45940/gremlin', { traversalSource: "g" const conn = client.open(); const list = conn.submit("g.V().has('person','name',name).out('knows')",{name: 'marko'}).then(function (response) { ... }); -// bytecode +// traversal const g = gtraversal().with(new DriverRemoteConnection('ws://localhost:8182/gremlin')); const list = g.V().has("person","name","marko").out("knows").toList(); ---- @@ -604,7 +565,7 @@ const list = g.V().has("person","name","marko").out("knows").toList(); client = Client('ws://localhost:8182/gremlin', 'g') list = client.submit("g.V().has('person','name',name).out('knows')",{'name': 'marko'}).all() -# bytecode +# traversal g = traversal().with(DriverRemoteConnection('ws://localhost:8182/gremlin','g')) list = g.V().has("person","name","marko").out("knows").toList() ---- @@ -616,7 +577,7 @@ resultSet, err := client.SubmitWithOptions("g.V().has('person','name',name).out( new(RequestOptionsBuilder).AddBinding("name", "marko").Create()) result, err := resultSet.All() -// bytecode +// traversal remote, err := NewDriverRemoteConnection("ws://localhost:8182/gremlin") g := Traversal_().With(remote) list, err := g.V().Has("person", "name", "marko").Out("knows").ToList() @@ -636,7 +597,7 @@ and details in the <<gremlin-drivers-variants,Gremlin Drivers and Variants>> Sec [[connecting-via-console]] === Connecting via Console -With Gremlin Server running it is now possible to issue some scripts to it for processing. Start Gremlin Console as +Gremlin Console can be used to send remote Traversals to a running Gremlin Server. Start Gremlin Console as follows: [source,text] @@ -649,177 +610,19 @@ $ bin/gremlin.sh gremlin> ---- -The console has the notion of a "remote", which represents a place a script will be sent from the console to be -evaluated elsewhere in some other context (e.g. Gremlin Server, Hadoop, etc.). To create a remote in the console, -do the following: - -[gremlin-groovy] ----- -:remote connect tinkerpop.server conf/remote.yaml ----- - -The `:remote` command shown above displays the current status of the remote connection. This command can also be -used to configure a new connection and change other related settings. To actually send a script to the server a -different command is required: - -[gremlin-groovy] ----- -:> g.V().values('name') -:> g.V().has('name','marko').out('created').values('name') -:> g.E().label().groupCount() -result -:remote close ----- - -The `:>` command, which is a shorthand for `:submit`, sends the script to the server to execute there. Results are -wrapped in an `Result` object which is a just a holder for each individual result. The `class` shows the data type -for the containing value. Note that the last script sent was supposed to return a `Map`, but its `class` is -`java.lang.String`. By default, the connection is configured to only return text results. In other words, -Gremlin Server is using `toString` to serialize all results back to the console. This enables virtually any -object on the server to be returned to the console, but it doesn't allow the opportunity to work with this data -in any way in the console itself. A different configuration of the `:remote` is required to get the results back -as "objects": - -[gremlin-groovy] ----- -:remote connect tinkerpop.server conf/remote-objects.yaml <1> -:remote list <2> -:> g.E().label().groupCount() <3> -m = result[0].object <4> -m.sort {it.value} -script = """ - g.V().hasLabel('person'). - out('knows'). - out('created'). - group(). - by('name') - """ -:> @script <5> -:remote close ----- - -<1> This configuration file specifies that results should be deserialized back into an `Object` in the console with -the caveat being that the server and console both know how to serialize and deserialize the result to be returned. -<2> There are now two configured remote connections. The one marked by an asterisk is the one that was just created -and denotes the current one that `:submit` will react to. -<3> When the script is executed again, the `class` is no longer shown to be a `java.lang.String`. It is instead a `java.util.HashMap`. -<4> The last result of a remote script is always stored in the reserved variable `result`, which allows access to -the `Result` and by virtue of that, the `Map` itself. -<5> If the submission requires multiple-lines to express, then a multi-line string can be created. The `:>` command -realizes that the user is referencing a variable via `@` and submits the string script. - -TIP: In Groovy, `""" text """` is a convenient way to create a multi-line string and works well in concert with -`:> @variable`. Note that this model of submitting a string variable works for all `:>` based plugins, not just Gremlin Server. - -WARNING: Not all values that can be returned from a Gremlin script end up being serializable. For example, -submitting `:> graph` will return a `Graph` instance and in most cases those are not serializable by Gremlin Server -and will return a serialization error. It should be noted that `TinkerGraph`, as a convenience for shipping around -small sub-graphs, is serializable from Gremlin Server. - -The alternative syntax to connecting allows for the `Cluster` to be user constructed directly in the console as -opposed to simply providing a static YAML file. - -[gremlin-groovy] ----- -cluster = Cluster.open() -:remote connect tinkerpop.server cluster ----- - -The Gremlin Server `:remote config` command for the driver has the following configuration options: - -[width="100%",cols="3,10a",options="header"] -|========================================================= -|Command |Description -|alias | -[width="100%",cols="3,10",options="header"] -!========================================================= -!Option !Description -! _pairs_ !A set of key/value alias/binding pairs to apply to requests. -!`reset` !Clears any aliases that were supplied in previous configurations of the remote. -!`show` !Shows the current set of aliases which is returned as a `Map` -!========================================================= -|timeout |Specifies the length of time in milliseconds the Console will wait for a response from the server. Specify -"none" to have no timeout. By default, this setting uses "none". -|========================================================= - -[[console-aliases]] -==== Aliases - -The `alias` configuration command for the Gremlin Server `:remote` can be useful in situations where there are -multiple `Graph` or `TraversalSource` instances on the server, as it becomes possible to rename them from the client -for purposes of execution within the context of a script. Therefore, it becomes possible to submit commands this way: - -[gremlin-groovy] ----- -:remote connect tinkerpop.server conf/remote-objects.yaml -:remote config alias x g -:> x.E().label().groupCount() -:remote close ----- - -[[console-sessions]] -==== Sessions - -A `:remote` created in the following fashion will be "sessionless", meaning each script issued to the server with -`:>` will be encased in a transaction and no state will be maintained from one request to the next. - -[source,groovy] ----- -gremlin> :remote connect tinkerpop.server conf/remote-objects.yaml -==>Configured localhost/127.0.0.1:8182 ----- - -In other words, the transaction will be automatically committed (or rolledback on error) and any variables declared -in that script will be forgotten for the next request. See the section on <<sessions, "Considering Sessions">> -for more information on that topic. - -To enable the remote to connect with a session the `connect` argument takes another argument as follows: +In the console, groovy can be used to construct a remote TraversalSource and execute traversals on the server. [gremlin-groovy] ---- -:remote connect tinkerpop.server conf/remote.yaml session -:> x = 1 -:> y = 2 -:> x + y -:remote close ----- - -With the above command a session gets created with a random UUID for a session identifier. It is also possible to -assign a custom session identifier by adding it as the last argument to `:remote` command above. There is also the -option to replace "session" with "session-managed" to create a session that will auto-manage transactions (i.e. each -request will occur within the bounds of a transaction). In this way, the state of bound variables between requests are -maintained, but the need to manually managed the transactional scope of the graph is no longer required. +g = traversal().withRemote(DriverRemoteConnection.using("localhost",8182,"g")) -[[console-remote-console]] -==== Remote Console - -Previous examples have shown usage of the `:>` command to send scripts to Gremlin Server. The Gremlin Console also -supports an additional method for doing this which can be more convenient when the intention is to exclusively -work with a remote connection to the server. +g.V().values('name') +g.V().has('name','marko').out('created').values('name') +g.E().label().groupCount() -[gremlin-groovy] +g.close() ---- -:remote connect tinkerpop.server conf/remote.yaml session -:remote console -x = 1 -y = 2 -x + y -:remote console -:remote close ----- - -In the above example, the `:remote console` command is executed. It places the console in a state where the `:>` is -no longer required. Each script line is actually automatically submitted to Gremlin Server for evaluation. The -variables `x` and `y` that were defined actually don't exist locally - they only exist on the server! In this sense, -putting the console in this mode is basically like creating a window to a session on Gremlin Server. - -TIP: When using `:remote console` there is not much point to using a configuration that uses a serializer that returns -actual data. In other words, using a configuration like the one inside of `conf/remote-objects.yaml` isn't typically -useful as in this mode the result will only ever be displayed but not used. Using a serializer configuration like -the one in `conf/remote.yaml` should perform better. -NOTE: Console commands, those that begin with a colon (e.g. `:x`, `:remote`) do not execute remotely when in this mode. -They are all still evaluated locally. [[connecting-via-http]] === Connecting via HTTP @@ -2522,65 +2325,6 @@ Gremlin Server in this configuration should be more efficient when there are mul Gremlin Server will only close transactions on the graphs specified by the `aliases`. Keeping this setting `false`, will simply have Gremlin Server close transactions on all graphs for every request. -[[considering-state]] -==== Considering State - -With HTTP and any sessionless requests, there is no variable state maintained between requests. Therefore, -when <<connecting-via-console,connecting with the console>>, for example, it is not possible to create a variable in -one command and then expect to access it in the next: - -[source,groovy] ----- -gremlin> :remote connect tinkerpop.server conf/remote.yaml -==>Configured localhost/127.0.0.1:8182 -gremlin> :> x = 2 -==>2 -gremlin> :> 2 + x -No such property: x for class: Script4 -Display stack trace? [yN] n ----- - -The same behavior would be seen with HTTP or when using sessionless requests through one of the Gremlin Server drivers. -If having this behavior is desireable, then <<sessions,consider sessions>>. - -There is an exception to this notion of state not existing between requests and that is globally defined functions. -All functions created via scripts are global to the server. - -[source,groovy] ----- -gremlin> :> def subtractIt(int x, int y) { x - y } -==>null -gremlin> :> subtractIt(8,7) -==>1 ----- - -If this behavior is not desirable there are several options. A first option would be to consider using sessions. Each -session gets its own `ScriptEngine`, which maintains its own isolated cache of global functions, whereas sessionless -requests uses a single function cache. A second option would be to define functions as closures: - -[source,groovy] ----- -gremlin> :> multiplyIt = { int x, int y -> x * y } -==>Script7$_run_closure1@6b24f3ab -gremlin> :> multiplyIt(7, 8) -No signature of method: org.apache.tinkerpop.gremlin.groovy.jsr223.GremlinGroovyScriptEngine.multiplyIt() is applicable for argument types: (java.lang.Integer, java.lang.Integer) values: [7, 8] -Display stack trace? [yN] ----- - -When the function is declared this way, the function is viewed by the `ScriptEngine` as a variable rather than a global -function and since sessionless requests don't maintain state, the function is forgotten for the next request. A final -option would be to manage the `ScriptEngine` cache manually: - -[source,bourne] ----- -$ curl -X POST -d "{\"gremlin\":\"def divideIt(int x, int y){ x / y }\",\"bindings\":{\"#jsr223.groovy.engine.keep.globals\":\"phantom\"}}" "http://localhost:8182" -{"requestId":"97fe1467-a943-45ea-8fd6-9e889a6c9381","status":{"message":"","code":200,"attributes":{}},"result":{"data":[null],"meta":{}}} -$ curl -X POST -d "{\"gremlin\":\"divideIt(8, 2)\"}" "http://localhost:8182" -{"message":"Error encountered evaluating script: divideIt(8, 2)"} ----- - -In the above HTTP-based requests, the bindings contain a special parameter that tells the `ScriptEngine` cache to -immediately forget the script after execution. In this way, the function does not end up being globally available. [[request-retry]] ==== Request Retry diff --git a/docs/src/reference/gremlin-variants.asciidoc b/docs/src/reference/gremlin-variants.asciidoc index 7e4445bc5c..120a1c1f99 100644 --- a/docs/src/reference/gremlin-variants.asciidoc +++ b/docs/src/reference/gremlin-variants.asciidoc @@ -732,7 +732,7 @@ objects and then re-use them. [gremlin-groovy] ---- -cluster = Cluster.open('conf/remote-objects.yaml') +cluster = Cluster.open('conf/remote.yaml') client = cluster.connect() g = traversal().with(DriverRemoteConnection.using(client, "g")) g.V().elementMap()
