Skip to content

Add explicit transaction support to non-Java GLVs#3434

Open
kenhuuu wants to merge 4 commits into
masterfrom
tx-glv
Open

Add explicit transaction support to non-Java GLVs#3434
kenhuuu wants to merge 4 commits into
masterfrom
tx-glv

Conversation

@kenhuuu
Copy link
Copy Markdown
Contributor

@kenhuuu kenhuuu commented May 28, 2026

Implement Transaction classes in gremlin-python, gremlin-go, gremlin-javascript, and gremlin-dotnet that mirror the Java HttpRemoteTransaction. Transaction wraps a Client and provides begin/commit/rollback/close lifecycle plus a submit() method for plain gremlin-lang strings.

gremlin-driver's default transaction close behavior is now rollback to match all GLVs.

Also changes how requests are submitted in gremlin-go. In particular it now waits for response headers before returning. This allows users to check if the response returns an err (pretty much any non-200 OK response), before having to check the ResultSet itself.

kenhuuu added 4 commits May 27, 2026 14:32
This behaves the same as the TraversalOpProcessor would have
in the 3.x line. All traversals are now transactional if the
underlying Graph supports transactions. Traversals that aren't
explicitly in a transaction are now wrapped into their own
implicit transaction and the server will autocommit on sucess
and rollback on failure.

Assisted-by: Kiro:claude-opus-4-6
Split executeAndStream() into sendRequest() (synchronous HTTP call) and
streamResponse() (async body streaming). submit() now blocks until the
server acknowledges the request (response headers received), then streams
the body in the background.

Non-GraphBinary HTTP errors (400/500 with text/JSON bodies) are now
returned directly from submit() instead of being embedded in the
ResultSet. Tests updated accordingly.

Assisted-by: Kiro:claude-opus-4-6
Implement Transaction classes in gremlin-python, gremlin-go,
gremlin-javascript, and gremlin-dotnet that mirror the Java
HttpRemoteTransaction. Transaction wraps a Client and provides
begin/commit/rollback/close lifecycle plus a submit() method for
plain gremlin-lang strings.

Key design decisions:
- Default close behavior changed from commit to rollback (all GLVs)
- Transactions are single-use (terminal state after commit/rollback)
- gtx.tx() returns the same Transaction (enables gtx.tx().commit())

Assisted-by: Kiro:claude-opus-4-6

IMPORTANT: Transaction support over HTTP is not yet implemented in Gremlin-Go. This will be addressed by the official
4.0.0 release.
Gremlin-Go supports remote transactions over HTTP. Transactions can be created from a `GraphTraversalSource` or
Copy link
Copy Markdown
Contributor

@spmallette spmallette Jun 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can't exactly say scripts vs bytecode anymore, but GraphTraversalSource vs Client doesn't sound quite right either. or maybe the way its introduced is sounding off to me?

Upgrade docs describe it as:

  • Traversal API: g.tx().begin() returns a transaction-bound GraphTraversalSource
  • Driver API: client.transact() (or client.Transact() in .NET) returns a Transaction with submit() methods

seems like it should at least be consistent with that.

and there is no way in TinkerPop to string together multiple traversals into the same transaction.

IMPORTANT: 4.0.0-beta.1 Release - Remote transactions are not supported in this beta.
Remote transactions are supported across all GLVs. See the <<transactions,Transactions>> section and each GLV's
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since this section is on limitations, i think the point is to assume there is complete transaction support. we'd only document the absence of support.


The default behavior of `close()` on a remote transaction has been changed from `commit` to `rollback` across all
GLVs (including the Java driver). This aligns with the embedded graph transaction default and is the safer behavior:
partial work is discarded if the user forgets to call `commit()`. In Java, the behavior can still be overridden via
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be more accurate to say that "In Java with embedded mode,"

Copy link
Copy Markdown
Contributor

@GumpacG GumpacG left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

VOTE +1

import { Traversal, Traverser } from '../process/traversal.js';
import type { ConnectionOptions } from './connection.js';

export type RemoteConnectionOptions = ConnectionOptions & { session?: string };
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If sessions are being removed, should this be removed as well?

private readonly IGremlinClient _client;
private readonly string _traversalSource;
// Serializes all submissions to guarantee ordering. Matches the role of
// Java's synchronized on HttpRemoteTransaction.submitInternal.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can remove this line.

defer t.mutex.Unlock()

if !t.isOpen {
return newError(err1102TransactionRollbackNotOpenedError)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are both being called by Commit() and Rollback() and should have different errors.

/// Synchronous dispose (required by IGremlinClient/IDisposable).
/// Does not attempt rollback. Use <c>await using</c> for proper cleanup.
/// </summary>
public void Dispose()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this have rollback for sync?

Base automatically changed from implicit-tx to master June 2, 2026 19:48
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.

3 participants