GumpacG commented on code in PR #3434: URL: https://github.com/apache/tinkerpop/pull/3434#discussion_r3337425118
########## gremlin-go/driver/transaction.go: ########## @@ -0,0 +1,195 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +*/ + +package gremlingo + +import ( + "fmt" + "sync" +) + +// Transaction controls an explicit remote transaction. A thin wrapper around +// a Client that adds transaction lifecycle (begin/commit/rollback/close) and +// attaches a transactionId to every request. +// +// Created via Client.Transact() or GraphTraversalSource.Tx(). The traversal +// source (g alias) is inherited from the Client and cannot be changed. +// +// Transactions are short-lived and single-use. After commit or rollback, the +// transaction ID is invalid and the object cannot be reused. +// +// This struct is NOT safe for concurrent semantic use. The mutex serializes +// requests if a user accidentally shares the Transaction across goroutines. +type Transaction struct { + client *Client + transactionId string + isOpen bool + failed bool + mutex sync.Mutex +} + +func (t *Transaction) Begin() (*GraphTraversalSource, error) { + t.mutex.Lock() + defer t.mutex.Unlock() + + if t.isOpen || t.failed { + return nil, newError(err1101TransactionRepeatedOpenError) + } + + // Submit g.tx().begin() via the Client to obtain a server-generated transactionId + rs, err := t.client.SubmitWithOptions("g.tx().begin()", + RequestOptions{}) + if err != nil { + t.failed = true + return nil, newError(err1105TransactionBeginFailedError, err) + } + + results, err := rs.All() + if err != nil { + t.failed = true + return nil, newError(err1105TransactionBeginFailedError, err) + } + + txId, err := extractTransactionId(results) + if err != nil { + t.failed = true + return nil, err + } + + t.transactionId = txId + t.isOpen = true + + // Create a transaction-bound remote connection that injects transactionId + txDRC := &transactionRemoteConnection{ + transaction: t, + } + gts := &GraphTraversalSource{ + graph: nil, + gremlinLang: NewGremlinLang(nil), + remoteConnection: txDRC, + } + return gts, nil +} + +func (t *Transaction) Commit() error { + return t.closeTransaction("g.tx().commit()") +} + +func (t *Transaction) Rollback() error { + return t.closeTransaction("g.tx().rollback()") +} + +// Close rolls back the transaction if still open. This is the safe default: +// partial work is discarded rather than accidentally persisted. +func (t *Transaction) Close() error { + t.mutex.Lock() + defer t.mutex.Unlock() + + if !t.isOpen { + return nil + } + + return t.closeTransactionLocked("g.tx().rollback()") +} + +func (t *Transaction) IsOpen() bool { + t.mutex.Lock() + defer t.mutex.Unlock() + return t.isOpen +} + +// TransactionId returns the server-generated transaction ID, or empty string if not yet begun. +func (t *Transaction) TransactionId() string { + t.mutex.Lock() + defer t.mutex.Unlock() + return t.transactionId +} + +func (t *Transaction) closeTransaction(script string) error { + t.mutex.Lock() + defer t.mutex.Unlock() + + if !t.isOpen { + return newError(err1102TransactionRollbackNotOpenedError) Review Comment: These are both being called by `Commit()` and `Rollback()` and should have different errors. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
