Class: ActiveCypher::Bolt::Transaction
- Inherits:
-
Object
- Object
- ActiveCypher::Bolt::Transaction
- Includes:
- Instrumentation
- Defined in:
- lib/active_cypher/bolt/transaction.rb
Overview
Manages transaction state (BEGIN/COMMIT/ROLLBACK) and runs queries within a transaction.
Instance Attribute Summary collapse
-
#bookmarks ⇒ Object
readonly
Returns the value of attribute bookmarks.
-
#connection ⇒ Object
readonly
Returns the value of attribute connection.
-
#metadata ⇒ Object
readonly
Returns the value of attribute metadata.
Instance Method Summary collapse
-
#active? ⇒ Boolean
Checks if the transaction is active.
-
#commit ⇒ Array<String>
Commits the transaction.
-
#committed? ⇒ Boolean
Checks if the transaction is committed.
-
#failed? ⇒ Boolean
Checks if the transaction is in a failed state.
-
#initialize(session, initial_bookmarks, metadata = {}) ⇒ Transaction
constructor
Initializes a new Transaction instance.
-
#rollback ⇒ Object
Rolls back the transaction.
-
#rolled_back? ⇒ Boolean
Checks if the transaction is rolled back.
-
#run(query, parameters = {}) ⇒ Result
Runs a Cypher query within this transaction.
Methods included from Instrumentation
#instrument, #instrument_connection, #instrument_query, #instrument_transaction, #sanitize_config, #sanitize_params, #sensitive_key?
Constructor Details
#initialize(session, initial_bookmarks, metadata = {}) ⇒ Transaction
Initializes a new Transaction instance.
16 17 18 19 20 21 22 |
# File 'lib/active_cypher/bolt/transaction.rb', line 16 def initialize(session, initial_bookmarks, = {}) @session = session @connection = session.connection @bookmarks = initial_bookmarks || [] @metadata = @state = :active end |
Instance Attribute Details
#bookmarks ⇒ Object (readonly)
Returns the value of attribute bookmarks.
9 10 11 |
# File 'lib/active_cypher/bolt/transaction.rb', line 9 def bookmarks @bookmarks end |
#connection ⇒ Object (readonly)
Returns the value of attribute connection.
9 10 11 |
# File 'lib/active_cypher/bolt/transaction.rb', line 9 def connection @connection end |
#metadata ⇒ Object (readonly)
Returns the value of attribute metadata.
9 10 11 |
# File 'lib/active_cypher/bolt/transaction.rb', line 9 def @metadata end |
Instance Method Details
#active? ⇒ Boolean
Checks if the transaction is active.
189 190 191 |
# File 'lib/active_cypher/bolt/transaction.rb', line 189 def active? @state == :active end |
#commit ⇒ Array<String>
Commits the transaction.
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
# File 'lib/active_cypher/bolt/transaction.rb', line 106 def commit raise ConnectionError, "Cannot commit a #{@state} transaction" unless @state == :active instrument_transaction(:commit, object_id) do # Send COMMIT message commit_msg = Messaging::Commit.new connection.(commit_msg) # Read response to COMMIT response = connection. case response when Messaging::Success # COMMIT succeeded @state = :committed # Extract bookmarks if any new_bookmarks = [] if response..key?('bookmark') new_bookmarks = [response.['bookmark']] @bookmarks = new_bookmarks end # Mark transaction as completed in the session @session.complete_transaction(self, new_bookmarks) new_bookmarks when Messaging::Failure # COMMIT failed @state = :failed code = response.['code'] = response.['message'] # Mark transaction as completed in the session @session.complete_transaction(self) raise QueryError, "Failed to commit transaction: #{code} - #{}" else raise ProtocolError, "Unexpected response to COMMIT: #{response.class}" end end rescue ConnectionError @state = :failed # Mark transaction as completed in the session @session.complete_transaction(self) raise end |
#committed? ⇒ Boolean
Checks if the transaction is committed.
194 195 196 |
# File 'lib/active_cypher/bolt/transaction.rb', line 194 def committed? @state == :committed end |
#failed? ⇒ Boolean
Checks if the transaction is in a failed state.
204 205 206 |
# File 'lib/active_cypher/bolt/transaction.rb', line 204 def failed? @state == :failed end |
#rollback ⇒ Object
Rolls back the transaction.
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
# File 'lib/active_cypher/bolt/transaction.rb', line 156 def rollback # If already committed or rolled back, do nothing return if @state == :committed || @state == :rolled_back instrument_transaction(:rollback, object_id) do # Send ROLLBACK message rollback_msg = Messaging::Rollback.new connection.(rollback_msg) # Read response to ROLLBACK response = connection. case response when Messaging::Success # ROLLBACK succeeded when Messaging::Failure # ROLLBACK failed - unusual but possible if connection is in a bad state response.['code'] response.['message'] # We don't raise here to ensure the rollback doesn't throw exceptions end rescue StandardError # We catch all exceptions during rollback to ensure it doesn't throw ensure # Always mark as rolled back and complete the transaction @state = :rolled_back @session.complete_transaction(self) end end |
#rolled_back? ⇒ Boolean
Checks if the transaction is rolled back.
199 200 201 |
# File 'lib/active_cypher/bolt/transaction.rb', line 199 def rolled_back? @state == :rolled_back end |
#run(query, parameters = {}) ⇒ Result
Runs a Cypher query within this transaction.
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/active_cypher/bolt/transaction.rb', line 29 def run(query, parameters = {}) raise ConnectionError, "Cannot run query on a #{@state} transaction" unless @state == :active # Ensure query is a string query_str = query.is_a?(String) ? query : query.to_s instrument_query(query_str, parameters, context: 'Transaction#run', metadata: { transaction_id: object_id }) do # Send RUN message = {} run_msg = Messaging::Run.new(query_str, parameters, ) connection.(run_msg) # Read response to RUN response = connection. qid = -1 fields = [] case response when Messaging::Success # RUN succeeded, extract metadata qid = response.['qid'] if response..key?('qid') fields = response.['fields'] if response..key?('fields') # Send PULL to get all records (-1 = all) = { 'n' => -1 } ['qid'] = qid if qid != -1 pull_msg = Messaging::Pull.new() connection.(pull_msg) # Process PULL response(s) records = [] = {} # Read messages until we get a SUCCESS (or FAILURE) loop do msg = connection. case msg when Messaging::Record # Store record with raw values - processing will happen in the adapter records << msg.values when Messaging::Success # Final SUCCESS with summary metadata = msg. break # Done processing results when Messaging::Failure connection.reset! # PULL failed - transaction is now failed @state = :failed code = msg.['code'] = msg.['message'] raise QueryError, "Query execution failed: #{code} - #{}" else raise ProtocolError, "Unexpected message type: #{msg.class}" end end # Create and return Result object Result.new(fields, records, , qid) when Messaging::Failure # RUN failed - transaction is now failed @state = :failed code = response.['code'] = response.['message'] raise QueryError, "Query execution failed: #{code} - #{}" else raise ProtocolError, "Unexpected response to RUN: #{response.class}" end end rescue ConnectionError @state = :failed raise end |