Gremlin-Go, named gremlingo
as a package, consists of two main groups of entities at a high level: Driver-related and Gremlin-related entities.
Driver-related entities are used to handle the processing, parsing, and sending of Gremlin traversal queries. They are also responsible for deserializing responses from a Gremlin Server and the API for consuming the responses.
The entities are as follows, from the highest level to the lowest:
A Client
represents the entry point to interaction with a Gremlin-supported server. A URL parameter is required for construction, with additional configuration options such as HTTP headers and TLS configuration available.
The Client
has two main responsibilities:
connection
types.Client
does not track or have any real state.Close()
can be invoked on a Client
in order to close any instances of connection
that in its current connectionPool
.classDiagram class Client Client: pool connectionPool Client: NewClient(host, configurations) Client Client: Close() Client: Submit(traversal) ResultSet Client: submit(bytecode) ResultSet
sequenceDiagram autonumber User->>gremlingo: NewClient() gremlingo-->>User: *Client User->>Client: Submit() Client-->>User: ResultSet
A connectionPool
is a collection of connection
. The implementation used is a loadBalancingPool
. It attempts to evenly load balance traversals by delegating it to the least-busy connection in the pool. The loadBalancingPool
has a maximum connection count, and a newConnectionTheshold
, where if the currently least-used connection has reached, will trigger the creation of a new connection
for use. If there are multiple connection
that sit unused, all but one will be closed
and removed from the pool.
connection
close()
in invoked, all connection
have their respective close()
method invoked asynchronously and are removed from the pool.A connection
represents an individual communication component with a Gremlin Server. A connection
has the sole responsibility of being the representation of a communication channel to a Gremlin Server, providing the interface for sending requests to said server, as well as holding response ResultSet
instances to consume responses asynchronously until they are consumed.
protocol
ResultSet
initialized
established
closed
closedDueToError
close()
is invoked, set the state to closed
and also invoke close()
on the protocol
.classDiagram class connection connection: protocol *protocol connection: results "map[string]ResultSet" connection: state connectionState connection: close() connection: createConnection(host) connection: write(request) ResultSet
sequenceDiagram Client->>connection(Pool): write() connection->>protocol: write(ResultSet) protocol-->>connection(Pool): ResultSet loop Readloop protocol->>protocol: Async population of ResultSet end connection-->>Client: ResultSet
The protocol
entity handles invoking serialization and deserialization of data, as well as handling the lifecycle of raw data passed to and received from the transporter
layer. Upon creation, an instance of protocol
starts a goroutine
to asynchronously read and populate data into a ResultSet
that is owned by the parent connection
.
transporter
serializer
closed bool
close()
is invoked, set the closed
boolean to true
which will terminate the goroutine
used for asynchronously reading, and invoke close()
on the transporter
.classDiagram class protocol protocol: transporter *transporter protocol: serializer *serializer protocol: close() protocol: write(request) protocol: readLoop(map[string]ResultSet)
sequenceDiagram connection->>protocol: write(request) protocol->>serializer: serializeMessage(request) serializer-->>protocol: bytes protocol->>transporter: Write(bytes) transporter-->>protocol: response protocol->>serializer: deserializeMessage(response) serializer-->>protocol: population of ResultSet protocol-->>connection: population of ResultSet
A serializer
is responsible for translating the traversal into binary format for sending and vice versa for receiving data from a Gremlin server. It is also responsible for identifying the data types of arguments and responses to properly delegate them to the appropriate internal type serializer.
classDiagram class serializer serializer: serializeMessage(request) []byte serializer: deserializeMessage([]byte) response
The transporter
is an interface that describes the lowest-level methods that are required for sending and receiving requests, which implementing types are ones that are implementations of network protocols. The default implementation used for Gremlin-Go is Gorilla WebSocket, a Go implementation of the WebSocket protocol.
transporter
interface requires method close()
, which closes the network protocol depending on its implementation.classDiagram class transporter transporter: Connect() transporter: Write([]byte) transporter: Read([]byte) transporter: Close() transporter: IsClosed() bool
A Result
represents an individual output from a Gremlin traversal query. Its interface provides the ability to transform the output into Go data types for use.
Lifecycle and States
classDiagram class Result Result: GetString() string Result: GetInt() int Result: GetByte() byte Result: Get...() ...
A ResultSet
is the immediate output of executing a Gremlin traversal. It contains a set of the individual Result
types. ResultSet
is populated asynchronously by a goroutine
and thus also handles the providing of Result
as they are available transparently to the user.
Result
States
closed bool
ResultSet
has method Close()
which can be used to stop the asynchronous generation of Result
if it is no longer required. Sets closed
to true
.
classDiagram class ResultSet ResultSet: GetAggregateTo() string ResultSet: GetStatusAttributes() map[string]interface{} ResultSet: GetAggregateTo() string ResultSet: GetRequestID() string ResultSet: IsEmpty() bool ResultSet: Close() ResultSet: Channel() chan ResultSet: All() []Result ResultSet: GetError() error
Gremlin-related entities are for the purpose of enabling the Gremlin query language to be used programmatically in Go. They responsible for integration with the Driver components, as well as translating the query language to a format that can be sent and consumed by a Gremlin-supported server. Most importantly, these entities are what allow the actual writing of Gremlin traversals in Go.
A DriverRemoteConnection
is an entity that represents a connection to a remote Gremlin Server, and is consumed as a parameter when creating a traversal. It wraps a Client
in order to provide the proper context and interface for a traversal to communicate with the Driver-related entities. Like the Client
, it can take in configuration, which is passed through to the Client
it owns.
Client
DriverRemoteConnection
does not keep track of state, but it exports method Close()
which invokes Close()
on the Client
it owns.classDiagram class DriverRemoteConnection DriverRemoteConnection: client *Client DriverRemoteConnection: NewDriverRemoteConnection(host, configurations) DriverRemoteConnection DriverRemoteConnection: Close() DriverRemoteConnection: Submit(traversal) ResultSet DriverRemoteConnection: SubmitBytecode(bytecode) ResultSet
sequenceDiagram User->>gremlingo: NewDriverRemoteConnection() gremlingo-->>User: DriverRemoteConnection User->>Traversal_: WithRemote(DriverRemoteConnection) Traversal_-->>User: g GraphTraversal User->>GraphTraversal: g.V()... GraphTraversal->>DriverRemoteConnection: bytecode DriverRemoteConnection->>Client: SubmitBytecode(bytecode) Client-->>DriverRemoteConnection: ResultSet DriverRemoteConnection-->>GraphTraversal: ResultSet GraphTraversal-->>User: ResultSet
The GraphTraversal
is the programmatic representation of a Gremlin traversal. It is the entity that methods are invoked and chained off of to build a traversal.
bytecode
classDiagram class GraphTraversal GraphTraversal: bytecode *bytecode GraphTraversal: V() GraphTraversal GraphTraversal: AddE() GraphTraversal GraphTraversal: AddV() GraphTraversal GraphTraversal: GremlinSteps...() GraphTraversal
bytecode
is the byte representation of a traversal that a Gremlin Server consumes and understands. Each GraphTraversal
owns one of these, and builds it up to represent the GraphTraversal
.
For a list of driver-side errors that may occur and common fixes, see:
TODO