Skip to content

Commit 5d86993

Browse files
xiazcykenhuuu
andauthored
Enable .NET driver over HTTP for 4.0.0 (#3338)
Replace Bytecode with GremlinLang, update GraphBinary serializers to 4.0 format, implemented non-streaming HTTP while replacing all WebSocket reference and settings, added interceptors to .NET with new reference auth implementations, split request and response serializer to allow user customization, and moved MimeType into IMessageSerializer. --------- Co-authored-by: Ken Hu <106191785+kenhuuu@users.noreply.github.com>
1 parent 17060bc commit 5d86993

175 files changed

Lines changed: 7577 additions & 9967 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/build-test.yml

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -339,40 +339,40 @@ jobs:
339339
EXCLUDE="${EXCLUDE_MODULES/,-:gremlin-python},$EXCLUDE_FOR_GLV"
340340
mvn clean install -pl $EXCLUDE -q -DskipTests -Dci
341341
mvn verify -pl gremlin-python
342-
# dotnet:
343-
# name: .NET
344-
# timeout-minutes: 20
345-
# needs: cache-gremlin-server-docker-image
346-
# runs-on: ubuntu-latest
347-
# steps:
348-
# - uses: actions/checkout@v6
349-
# - name: Set up JDK11
350-
# uses: actions/setup-java@v5
351-
# with:
352-
# java-version: '11'
353-
# distribution: 'temurin'
354-
# - name: Set up .NET 8.0.x
355-
# uses: actions/setup-dotnet@v4
356-
# with:
357-
# dotnet-version: '8.0.x'
358-
# - name: Get Cached Server Base Image
359-
# uses: actions/cache@v5
360-
# id: gremlin-server-test-docker-image
361-
# with:
362-
# path: |
363-
# ./gremlin-server/*
364-
# ~/.m2/repository/org/apache/tinkerpop/*
365-
# key: ${{ github.sha }}
366-
# - name: Load Docker Image
367-
# working-directory: ./gremlin-server
368-
# run: docker load --input gremlin-server.tar
369-
# - name: Build with Maven
370-
# run: |
371-
# touch gremlin-dotnet/src/.glv
372-
# touch gremlin-dotnet/test/.glv
373-
# EXCLUDE="${EXCLUDE_MODULES/-:gremlin-dotnet-source,-:gremlin-dotnet-tests,},$EXCLUDE_FOR_GLV"
374-
# mvn clean install -pl $EXCLUDE -q -DskipTests -Dci
375-
# mvn verify -pl :gremlin-dotnet,:gremlin-dotnet-tests -P gremlin-dotnet
342+
dotnet:
343+
name: .NET
344+
timeout-minutes: 20
345+
needs: cache-gremlin-server-docker-image
346+
runs-on: ubuntu-latest
347+
steps:
348+
- uses: actions/checkout@v6
349+
- name: Set up JDK11
350+
uses: actions/setup-java@v5
351+
with:
352+
java-version: '11'
353+
distribution: 'temurin'
354+
- name: Set up .NET 8.0.x
355+
uses: actions/setup-dotnet@v4
356+
with:
357+
dotnet-version: '8.0.x'
358+
- name: Get Cached Server Base Image
359+
uses: actions/cache@v5
360+
id: gremlin-server-test-docker-image
361+
with:
362+
path: |
363+
./gremlin-server/*
364+
~/.m2/repository/org/apache/tinkerpop/*
365+
key: ${{ github.sha }}
366+
- name: Load Docker Image
367+
working-directory: ./gremlin-server
368+
run: docker load --input gremlin-server.tar
369+
- name: Build with Maven
370+
run: |
371+
touch gremlin-dotnet/src/.glv
372+
touch gremlin-dotnet/test/.glv
373+
EXCLUDE="${EXCLUDE_MODULES/-:gremlin-dotnet-source,-:gremlin-dotnet-tests,},$EXCLUDE_FOR_GLV"
374+
mvn clean install -pl $EXCLUDE -q -DskipTests -Dci
375+
mvn verify -pl :gremlin-dotnet,:gremlin-dotnet-tests -P gremlin-dotnet
376376
neo4j-gremlin:
377377
name: neo4j-gremlin
378378
timeout-minutes: 20

CHANGELOG.asciidoc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
3737
* Added `RequestInterceptor` to `gremlin-go` with `auth` reference implementations to replace `authInfo`.
3838
* Refactored GraphBinary serializers to use `io.Writer` and `io.Reader` instead of `*bytes.Buffer` for streaming capacities.
3939
* Refactored `httpProtocol` and `httpTransport` in `gremlin-go` into single `connection.go` that handles HTTP request and response.
40+
* Replace `Bytecode` with `GremlinLang` in `gremlin-dotnet`.
41+
* Replace `WebSocket` with `HTTP` (non-streaming) in `gremlin-dotnet`.
42+
* Added `MimeType` to `IMessageSerializer` and split client option to allow separate request and response serialization in `gremlin-dotnet`.
43+
* Added `RequestInterceptor` to `gremlin-dotnet` with `auth` reference implementations.
4044
* Bumped ANTLR to 4.13.2
4145
* Bumped SLF4j to 2.0.16.
4246
* Bumped GMavenPlus to 4.1.1.

gremlin-dotnet/Examples/BasicGremlin/BasicGremlin.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ under the License.
2020
using Gremlin.Net.Driver;
2121
using Gremlin.Net.Driver.Remote;
2222
using static Gremlin.Net.Process.Traversal.AnonymousTraversalSource;
23+
using static Gremlin.Net.Process.Traversal.__;
2324

2425
public class BasicGremlinExample
2526
{
@@ -40,8 +41,8 @@ static async Task Main()
4041

4142
// Be sure to use a terminating step like Next() or Iterate() so that the traversal "executes"
4243
// Iterate() does not return any data and is used to just generate side-effects (i.e. write data to the database)
43-
g.V(v1).AddE("knows").To(v2).Property("weight", 0.75).Iterate();
44-
g.V(v1).AddE("knows").To(v3).Property("weight", 0.75).Iterate();
44+
g.V(v1).AddE("knows").To(Constant(v2)).Property("weight", 0.75).Iterate();
45+
g.V(v1).AddE("knows").To(Constant(v3)).Property("weight", 0.75).Iterate();
4546

4647
// Retrieve the data from the "marko" vertex
4748
var marko = await g.V().Has(VertexLabel, "name", "marko").Values<string>("name").Promise(t => t.Next());

gremlin-dotnet/Examples/Connections/Connections.cs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,20 @@ under the License.
1919

2020
using Gremlin.Net.Driver;
2121
using Gremlin.Net.Driver.Remote;
22-
using Gremlin.Net.Structure.IO.GraphSON;
2322
using static Gremlin.Net.Process.Traversal.AnonymousTraversalSource;
2423

2524
public class ConnectionExample
2625
{
2726
static readonly string ServerHost = Environment.GetEnvironmentVariable("GREMLIN_SERVER_HOST") ?? "localhost";
2827
static readonly int ServerPort = int.Parse(Environment.GetEnvironmentVariable("GREMLIN_SERVER_PORT") ?? "8182");
28+
static readonly int SecureServerPort = int.Parse(Environment.GetEnvironmentVariable("GREMLIN_SECURE_SERVER_PORT") ?? "8183");
2929
static readonly string VertexLabel = Environment.GetEnvironmentVariable("VERTEX_LABEL") ?? "connection";
3030

3131
static void Main()
3232
{
3333
WithRemoteConnection();
3434
WithConf();
35-
WithSerializer();
35+
WithBasicAuth();
3636
}
3737

3838
// Connecting to the server
@@ -48,23 +48,30 @@ static void WithRemoteConnection()
4848
Console.WriteLine("Vertex count: " + count);
4949
}
5050

51-
// Connecting to the server with customized configurations
51+
// Connecting to the server with customized connection settings
5252
static void WithConf()
5353
{
54-
using var remoteConnection = new DriverRemoteConnection(new GremlinClient(
55-
new GremlinServer(hostname: ServerHost, port: ServerPort, enableSsl: false, username: "", password: "")), "g");
54+
var server = new GremlinServer(ServerHost, ServerPort);
55+
var settings = new ConnectionSettings
56+
{
57+
ConnectionTimeout = TimeSpan.FromSeconds(30),
58+
};
59+
using var remoteConnection = new DriverRemoteConnection(
60+
new GremlinClient(server, connectionSettings: settings), "g");
5661
var g = Traversal().With(remoteConnection);
5762

5863
var v = g.AddV(VertexLabel).Iterate();
5964
var count = g.V().HasLabel(VertexLabel).Count().Next();
6065
Console.WriteLine("Vertex count: " + count);
6166
}
6267

63-
// Specifying a serializer
64-
static void WithSerializer()
68+
// Connecting with basic authentication using a request interceptor
69+
static void WithBasicAuth()
6570
{
66-
var server = new GremlinServer(ServerHost, ServerPort);
67-
var client = new GremlinClient(server, new GraphSON3MessageSerializer());
71+
var server = new GremlinServer(ServerHost, SecureServerPort, enableSsl: true);
72+
var client = new GremlinClient(server,
73+
connectionSettings: new ConnectionSettings { SkipCertificateValidation = true },
74+
interceptors: new[] { Auth.BasicAuth("stephen", "password") });
6875
using var remoteConnection = new DriverRemoteConnection(client, "g");
6976
var g = Traversal().With(remoteConnection);
7077

gremlin-dotnet/Examples/ModernTraversals/ModernTraversals.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ This example requires the Modern toy graph to be preloaded upon launching the Gr
4747
var e2 = g.V(1).BothE().Where(OtherV().HasId(2)).ToList(); // (2)
4848
var v1 = g.V(1).Next();
4949
var v2 = g.V(2).Next();
50-
var e3 = g.V(v1).BothE().Where(OtherV().Is(v2)).ToList(); // (3)
51-
var e4 = g.V(v1).OutE().Where(InV().Is(v2)).ToList(); // (4)
50+
var e3 = g.V(v1).BothE().Where(OtherV().Id().Is(v2)).ToList(); // (3)
51+
var e4 = g.V(v1).OutE().Where(InV().Id().Is(v2)).ToList(); // (4)
5252
var e5 = g.V(1).OutE().Where(InV().Has(T.Id, Within(2, 3))).ToList(); // (5)
5353
var e6 = g.V(1).Out().Where(__.In().HasId(6)).ToList(); // (6)
5454

gremlin-dotnet/build/generate.groovy

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ radishGremlinFile.withWriter('UTF-8') { Writer writer ->
6565
'using Gremlin.Net.Process.Traversal;\n' +
6666
'using Gremlin.Net.Process.Traversal.Strategy.Optimization;\n' +
6767
'using Gremlin.Net.Process.Traversal.Strategy.Verification;\n' +
68+
'using Gremlin.Net.Process.Traversal.Strategy.Finalization;\n' +
6869
'using Gremlin.Net.Process.Traversal.Strategy.Decoration;\n')
6970
writer.writeLine('namespace Gremlin.Net.IntegrationTest.Gherkin\n' +
7071
'{\n' +
@@ -138,9 +139,16 @@ radishGremlinFile.withWriter('UTF-8') { Writer writer ->
138139
' Func<GraphTraversalSource, IDictionary<string, object>, ITraversal> f = list[0];\n' +
139140
' list.RemoveAt(0);\n' +
140141
' ITraversal traversal = f.Invoke(g, parameters);\n' +
141-
' foreach (var sideEffect in sideEffects)\n' +
142+
' // Side effects need to be prepended as source steps (before traversal steps).\n' +
143+
' // Build them in a temporary GremlinLang and prepend to the traversal\'s gremlin string.\n' +
144+
' if (sideEffects.Count > 0)\n' +
142145
' {\n' +
143-
' traversal.Bytecode.AddSource("withSideEffect", sideEffect.Key, sideEffect.Value);\n' +
146+
' var sideEffectLang = new GremlinLang();\n' +
147+
' foreach (var sideEffect in sideEffects)\n' +
148+
' {\n' +
149+
' sideEffectLang.AddSource("withSideEffect", sideEffect.Key, sideEffect.Value);\n' +
150+
' }\n' +
151+
' traversal.GremlinLang.Gremlin = sideEffectLang.Gremlin + traversal.GremlinLang.Gremlin;\n' +
144152
' }\n' +
145153
' return traversal;\n' +
146154
' }\n' +

gremlin-dotnet/docker-compose.yml

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,26 +35,26 @@ services:
3535
- ${HOME}/.m2:/root/.m2
3636
- ${ABS_PROJECT_HOME}/gremlin-test/target:/opt/gremlin-test
3737
healthcheck:
38-
test: [ "CMD-SHELL", "apk add curl && curl -f http://localhost:45940?gremlin=100-1" ]
38+
test: [ "CMD-SHELL", "apk add curl && curl -X POST -d '{\"gremlin\":\"g.inject(1)\"}' http://localhost:45940" ]
3939
interval: 30s
4040
timeout: 10s
4141
retries: 30
4242
start_period: 30s
43-
depends_on:
44-
- gremlin-socket-server
4543

4644
gremlin-dotnet-integration-tests:
4745
container_name: gremlin-dotnet-integration-tests
4846
image: mcr.microsoft.com/dotnet/sdk:8.0
4947
volumes:
5048
- .:/gremlin-dotnet
5149
- ../gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features:/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features
50+
- ../gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/structure/io:/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/structure/io
5251
- ../docker/gremlin-test-server:/gremlin-dotnet/gremlin-test-server
5352
- ../gremlin-tools/gremlin-socket-server/conf:/gremlin-dotnet/gremlin-socket-server/conf/
5453
environment:
5554
- DOCKER_ENVIRONMENT=true
5655
- GREMLIN_SERVER_HOST=gremlin-server-test-dotnet
5756
- GREMLIN_SERVER_PORT=45940
57+
- GREMLIN_SECURE_SERVER_PORT=45941
5858
- VERTEX_LABEL=dotnet-example
5959
working_dir: /gremlin-dotnet
6060
command: >
@@ -72,10 +72,3 @@ services:
7272
depends_on:
7373
gremlin-server-test-dotnet:
7474
condition: service_healthy
75-
76-
gremlin-socket-server:
77-
container_name: gremlin-socket-server
78-
image: tinkerpop/gremlin-socket-server:${GREMLIN_SERVER}
79-
ports:
80-
- "45943:45943"
81-

0 commit comments

Comments
 (0)