Skip to content

TINKERPOP-3237 Add custom type serializer API for gremlin-go#3335

Open
DR1N0 wants to merge 1 commit intoapache:3.8-devfrom
DR1N0:feature/custom-type-serializer
Open

TINKERPOP-3237 Add custom type serializer API for gremlin-go#3335
DR1N0 wants to merge 1 commit intoapache:3.8-devfrom
DR1N0:feature/custom-type-serializer

Conversation

@DR1N0
Copy link
Contributor

@DR1N0 DR1N0 commented Mar 20, 2026

Summary

This PR adds support for serializing custom types in gremlin-go, bringing it to feature parity with the Java driver and completing the custom type support that currently only includes deserialization. This implements the official GraphBinary specification for custom types, enabling full round-trip support for custom graph database types.

Motivation

While gremlin-go supports deserializing custom types via RegisterCustomTypeReader(), it lacks the corresponding serialization capability. This creates an asymmetry where users can read custom types from server responses but cannot write them in requests. The Java driver already has full custom type support (both CustomTypeSerializer reader and writer), and this PR brings gremlin-go to the same level.

Changes

New API Functions

  • RegisterCustomTypeWriter(valueType reflect.Type, typeName string, writer CustomTypeWriter) - Registers a custom serializer for a specific type
  • UnregisterCustomTypeWriter(valueType reflect.Type) - Unregisters a custom serializer

New Types

  • CustomTypeWriter - Function type for user-provided serialization functions
  • CustomTypeInfo - Struct holding type metadata (name and writer function)

Implementation Details

  • Added customTypeWriter() function to handle GraphBinary custom type format (type_code=0x00, type_name, value)
  • Modified getType() to detect registered custom types before checking built-in types
  • Modified write() to properly handle custom type format, matching the Java implementation in GraphBinaryWriter.java:
    if (serializer instanceof CustomTypeSerializer) {
        buffer.writeBytes(customTypeCodeBytes);  // 0x00
        writeValue(customTypeSerializer.getTypeName(), buffer, false);
        customTypeSerializer.write(value, buffer, this);
    }

GraphBinary Format Compliance

The implementation follows the exact format used by Java's GraphBinaryWriter:

  • Type code: 0x00 (DataType.CUSTOM)
  • Type name: UTF-8 string with length prefix
  • Value: Custom-serialized data

This ensures cross-driver compatibility - custom types serialized by gremlin-go can be deserialized by Java drivers and vice versa.

Updated Files

  • gremlin-go/driver/serializer.go - Added type definitions and registration functions
  • gremlin-go/driver/graphBinary.go - Added custom type writer implementation and modified type detection
  • gremlin-go/driver/serializer_test.go - Added test cases following existing patterns
  • CHANGELOG.asciidoc - Added changelog entry

Test Coverage

Tests follow the same pattern as existing custom type reader tests:

  • Success case in TestSerializer: "test serialized request message w/ custom type"
  • Failure case in TestSerializerFailures: "test unregistered custom type writer failure"

All tests pass:

=== RUN   TestSerializer/test_serialized_request_message_w/_custom_type
--- PASS: TestSerializer/test_serialized_request_message_w/_custom_type (0.00s)
=== RUN   TestSerializerFailures/test_unregistered_custom_type_writer_failure
--- PASS: TestSerializerFailures/test_unregistered_custom_type_writer_failure (0.00s)

Use Case

This feature enables users to serialize custom graph database types (e.g., JanusGraph's RelationIdentifier) when sending requests to the server:

import (
    "bytes"
    "encoding/binary"
    "reflect"
)

// Define custom type writer
customWriter := func(value interface{}, buffer *bytes.Buffer) error {
    // Custom serialization logic matching server expectations
    return nil
}

// Register the writer
RegisterCustomTypeWriter(
    reflect.TypeOf((*MyCustomType)(nil)),
    "janusgraph.RelationIdentifier",  // Must match server-side type name
    customWriter
)

// Now MyCustomType instances can be serialized in requests
client.Submit("g.E().has('id', rid)", map[string]interface{}{"rid": customValue})

Benefits

  1. Feature Parity: Brings gremlin-go to the same level as the Java driver
  2. GraphBinary Compliance: Implements the official specification
  3. Cross-Driver Compatibility: Custom types work across Java, Go, and other GraphBinary drivers
  4. Complete Custom Type Support: Enables full round-trip custom type handling

Backward Compatibility

This change is fully backward compatible - it only adds new functionality without modifying existing APIs or behavior.

References

  • Java implementation: gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/GraphBinaryWriter.java
  • GraphBinary specification for custom types (DataType.CUSTOM = 0x00)

@codecov-commenter
Copy link

codecov-commenter commented Mar 20, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
⚠️ Please upload report for BASE (3.8-dev@81073ea). Learn more about missing BASE report.

Additional details and impacted files
@@            Coverage Diff             @@
##             3.8-dev    #3335   +/-   ##
==========================================
  Coverage           ?   76.46%           
  Complexity         ?    14890           
==========================================
  Files              ?     1159           
  Lines              ?    72135           
  Branches           ?     8057           
==========================================
  Hits               ?    55159           
  Misses             ?    14047           
  Partials           ?     2929           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants