This is an automated email from the ASF dual-hosted git repository.

kenhuuu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git

commit 485a67382dcb47d8eee3ec145dadf83491f74a35
Author: Ken Hu <[email protected]>
AuthorDate: Tue Mar 31 00:16:42 2026 -0700

    Add transactions to HTTP API section in provider documentation CTR
---
 docs/src/dev/provider/index.asciidoc | 101 ++++++++++++++++++++++++++++++++++-
 1 file changed, 99 insertions(+), 2 deletions(-)

diff --git a/docs/src/dev/provider/index.asciidoc 
b/docs/src/dev/provider/index.asciidoc
index 047b6c5c7c..4ee8fbfaa8 100644
--- a/docs/src/dev/provider/index.asciidoc
+++ b/docs/src/dev/provider/index.asciidoc
@@ -1041,6 +1041,7 @@ user-agent: NotAvailable Gremlin-Java.4.0.0 11.0.25 
Windows_11.10.0 amd64
 |Content-Type |The MIME type of the serialized body |No |None
 |Gremlin-Hints |A semi-colon separated list of key/value pair metadata that 
could be helpful to the server in processing a particular request in some way. 
Must be a hints (see table below). |No |N/A
 |User-Agent |The user agent. Follow the format specified by 
<<user-agent-format, user agent format>>. |No |<<user-agent-format, user agent 
format>>
+|X-Transaction-Id |Transaction ID that must match the `transactionId` field in 
the request body. Enables load balancer sticky routing without requiring body 
parsing. Only include when a transaction is active (i.e. after a successful 
begin and before commit/rollback). |No |N/A
 |=========================================================
 
 ===== Request Header Value Options
@@ -1068,6 +1069,7 @@ the serializer specified by the `Content-Type` header. 
The following are the key
 |language |The name of the ScriptEngine to use to parse the gremlin query. 
Default: "gremlin-lang" |String containing ScriptEngine name |No
 |materializeProperties |Whether to include all properties for results. One of 
"tokens" or "all". |String |No
 |bulkResults |Whether the results should be bulked by the server (only applies 
to GraphBinary) |Boolean |No
+|transactionId |A server-generated UUID that identifies an active transaction. 
Must be included in all non-begin requests within that transaction. Omit for 
non-transactional requests and for the initial begin request. |String |No
 |=========================================================
 
 ==== HTTP Response
@@ -1122,6 +1124,7 @@ serialized. In that case, the `Content-Type` of the 
response should be `applicat
 |Content-Type |The MIME type of the serialized body which is based on the 
request's `Accept` header. May also be "application/json". |Yes |N/A
 |Gremlin-RequestId |The server generated UUID that is used as a request ID. 
|Yes |N/A
 |Transfer-Encoding |The server should attempt to chunk all responses. |No 
|"chunked"
+|X-Transaction-Id |The transaction ID associated with this request. Present on 
all responses within a transaction, including the begin response where the 
server generates the ID. Not present on non-transactional responses. |No |N/A
 |=========================================================
 
 ===== Response Header Value Options
@@ -1144,13 +1147,14 @@ The following table details the HTTP status codes that 
Gremlin Server will send:
 |200 |SUCCESS |The server successfully processed a request to completion - 
there are no messages remaining in this stream.
 |204 |NO CONTENT |The server processed the request but there is no result to 
return (e.g. an `Iterator` with no elements) - there are no messages remaining 
in this stream.
 |206 |PARTIAL CONTENT |The server successfully returned some content, but 
there is more in the stream to arrive - wait for a `SUCCESS` to signify the end 
of the stream.
-|400 |BAD REQUEST |There was a problem with the HTTP request.
+|400 |BAD REQUEST |There was a problem with the HTTP request. For 
transaction-specific cases: begin on a graph that does not support 
transactions, commit or rollback sent without a transaction ID, begin sent with 
a user-supplied transaction ID, or graph alias mismatch within a transaction.
 |401 |UNAUTHORIZED |The request attempted to access resources that the 
requesting user did not have access to.
 |403 |FORBIDDEN |The server could authenticate the request, but will not 
fulfill it.
-|404 |NOT FOUND |The server was unable to find the requested resource.
+|404 |NOT FOUND |The server was unable to find the requested resource. Also 
returned when a `transactionId` does not correspond to any active transaction 
on this server. This covers transactions that were already committed, already 
rolled back, reclaimed by timeout, or never existed.
 |405 |METHOD NOT ALLOWED |The request used an unsupported method. The server 
only supports POST.
 |413 |REQUEST ENTITY TOO LARGE |The request was too large or the query could 
not be compiled due to size limitations.
 |500 |INTERNAL SERVER ERROR |A general server error occurred that prevented 
the request from being processed.
+|503 |SERVICE UNAVAILABLE |The server has reached its maximum number of 
concurrent transactions and cannot accept a new begin request.
 |505 |HTTP VERSION NOT SUPPORTED |A server error indicating that an 
unsupported version of HTTP is being used. Only HTTP/1.1 is supported.
 |=========================================================
 
@@ -1166,6 +1170,99 @@ For examples of actual requests and responses, take a 
look at the IO documentati
 link:https://tinkerpop.apache.org/docs/x.y.z/dev/io/#_requestmessage[GraphSON 
requests] and
 link:https://tinkerpop.apache.org/docs/x.y.z/dev/io/#_responsemessage[GraphSON 
responses].
 
+=== Transactions
+
+The HTTP API supports multi-request transactions that allow a client to group 
multiple Gremlin requests into a single
+atomic unit of work. Transaction lifecycle is controlled using standard 
Gremlin syntax (`g.tx().begin()`,
+`g.tx().commit()`, `g.tx().rollback()`) and all requests flow through the same 
`POST /gremlin` endpoint.
+
+==== Protocol Flow
+
+A transaction follows this sequence:
+
+. The client sends `g.tx().begin()` with no `transactionId`. The request body 
must include the `g` field to identify
+  the target traversal source.
+. The server opens a transaction against the specified graph, generates a 
String as the transaction ID, and returns it
+  in both the response body (as a `transactionId` field in a map) and the 
`X-Transaction-Id` response header.
+. For all subsequent requests within the transaction, the client must include 
the transaction ID in both the
+  `X-Transaction-Id` request header and the `transactionId` field of the 
request body.
+. The client closes the transaction by sending `g.tx().commit()` or 
`g.tx().rollback()` with the transaction ID
+  attached.
+
+An example begin request and response:
+
+[source,text]
+----
+POST /gremlin HTTP/1.1
+content-type: application/vnd.gremlin-v4.0+json
+accept: application/vnd.gremlin-v4.0+json
+
+{"gremlin": "g.tx().begin()", "g": "g"}
+----
+
+[source,text]
+----
+HTTP/1.1 200 OK
+Content-Type: application/vnd.gremlin-v4.0+json
+X-Transaction-Id: 3c72a3a8-be41-4a0b-88e5-a88ee6f1e8e4
+
+{"result": {"data": [{"transactionId": 
"3c72a3a8-be41-4a0b-88e5-a88ee6f1e8e4"}]}}
+----
+
+A subsequent transactional request:
+
+[source,text]
+----
+POST /gremlin HTTP/1.1
+content-type: application/vnd.gremlin-v4.0+json
+accept: application/vnd.gremlin-v4.0+json
+X-Transaction-Id: 3c72a3a8-be41-4a0b-88e5-a88ee6f1e8e4
+
+{"gremlin": "g.addV('person').property('name','alice')", "transactionId": 
"3c72a3a8-be41-4a0b-88e5-a88ee6f1e8e4"}
+----
+
+==== Client-Side Host Affinity
+
+The client is responsible for routing all requests in a transaction to the 
same server instance. The `X-Transaction-Id`
+header provides a standard mechanism for load balancers to achieve sticky 
routing without parsing the request body.
+This design is server-topology agnostic — it works identically whether the 
backend is a single server, a cluster with
+a load balancer, or a managed service. Each server manages only its own local 
transaction state.
+
+==== Graph Alias Locking
+
+The graph alias (`g` field) specified in the begin request determines which 
graph instance the transaction targets. This
+alias is locked for the lifetime of the transaction. If a subsequent request 
carries a different alias, the server
+rejects it with HTTP 400. This prevents cross-graph operations within a single 
transaction.
+
+==== Transaction Timeout and Idle Reclamation
+
+Servers implement a configurable transaction timeout (`transactionTimeout`, 
default 600000ms). The timeout represents
+how long a transaction can sit idle with no requests before the server 
forcibly rolls it back and removes it. The
+timeout resets on each request received for that transaction, so active 
transactions are not affected. After a timeout
+fires, any subsequent request with that transaction ID receives a 404 response.
+
+==== Transaction Capacity Limits
+
+Servers enforce a configurable maximum number of concurrent open transactions 
(`maxConcurrentTransactions`, default
+1000). When the limit is reached, new begin requests are rejected with HTTP 
503. Slots are freed when transactions
+close via commit, rollback, or timeout.
+
+==== Error Handling Within a Transaction
+
+If a traversal within an open transaction fails (bad syntax, runtime error, 
etc.), the server returns the error for
+that request but keeps the transaction open. The client can retry, submit 
other traversals, or explicitly roll back.
+A failed traversal does not implicitly close or roll back the transaction. 
Only an explicit commit, explicit rollback,
+or server-side timeout closes a transaction.
+
+==== Thread Affinity
+
+Graph transactions are typically `ThreadLocal`-bound. The server maintains a 
single-threaded executor per transaction
+to ensure all operations execute on the same thread. This is an important 
implementation detail for graph system
+providers whose `Transaction` implementation relies on thread-local state.
+
+NOTE: Non-transactional requests (those without a `transactionId`) are not 
affected by any of the transaction-specific
+behavior described above. They continue to operate exactly as before.
+
 === HTTP Request Interceptor
 
 A graph driver may support HTTP request intercepting which provides a means 
for the user of your graph driver to update

Reply via email to