diff --git a/jruby/neo4j/driver.rb b/jruby/neo4j/driver.rb index 4694753c..73a6b3ba 100644 --- a/jruby/neo4j/driver.rb +++ b/jruby/neo4j/driver.rb @@ -51,6 +51,7 @@ module Types Java::OrgNeo4jDriverInternal::InternalResult.prepend Neo4j::Driver::Ext::InternalResult Java::OrgNeo4jDriverInternal::InternalSession.prepend Neo4j::Driver::Ext::InternalSession Java::OrgNeo4jDriverInternal::InternalTransaction.prepend Neo4j::Driver::Ext::InternalTransaction +Java::OrgNeo4jDriverInternal::DelegatingTransactionContext.prepend Neo4j::Driver::Ext::DelegatingTransactionContext Java::OrgNeo4jDriverInternalAsync::InternalAsyncSession.prepend Neo4j::Driver::Ext::Internal::Async::InternalAsyncSession Java::OrgNeo4jDriverInternalShadedBoltConnectionRoutedImplCluster::RoutingTableRegistryImpl.include Neo4j::Driver::Ext::Internal::Cluster::RoutingTableRegistryImpl # Java::OrgNeo4jDriverInternalCursor::DisposableAsyncResultCursor.prepend Neo4j::Driver::Ext::Internal::Cursor::DisposableAsyncResultCursor diff --git a/jruby/neo4j/driver/ext/delegating_transaction_context.rb b/jruby/neo4j/driver/ext/delegating_transaction_context.rb new file mode 100644 index 00000000..fd35a70d --- /dev/null +++ b/jruby/neo4j/driver/ext/delegating_transaction_context.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +module Neo4j + module Driver + module Ext + module DelegatingTransactionContext + include ExceptionCheckable + include RunOverride + + def run(statement, **parameters) + check { super(to_statement(statement, parameters)) } + end + end + end + end +end diff --git a/jruby/neo4j/driver/ext/internal_session.rb b/jruby/neo4j/driver/ext/internal_session.rb index b9a5349c..73fd67c8 100644 --- a/jruby/neo4j/driver/ext/internal_session.rb +++ b/jruby/neo4j/driver/ext/internal_session.rb @@ -14,10 +14,14 @@ module InternalSession # work around jruby issue https://github.com/jruby/jruby/issues/5603 Struct.new('Wrapper', :object) - %i[read write].each do |prefix| - define_method("#{prefix}_transaction") do |**config, &block| - check do - super(->(tx) { Struct::Wrapper.new(reverse_check { block.call(tx) }) }, to_java_config(Neo4j::Driver::TransactionConfig, **config)).object + # implementation of read_transaction, write_transaction, execute_read, execute_write + %i[read write].each do |mode| + ["#{mode}_transaction", "execute_#{mode}"].each do |method_name| + define_method(method_name) do |**config, &block| + Driver::Internal::Deprecator.log_warning(method_name, "execute_#{mode}".to_sym, '6.0') if method_name.include? 'transaction' + check do + super(->(tx) { Struct::Wrapper.new(reverse_check { block.call(tx) }) }, to_java_config(Neo4j::Driver::TransactionConfig, **config)).object + end end end end diff --git a/lib/neo4j/driver/internal/deprecator.rb b/lib/neo4j/driver/internal/deprecator.rb new file mode 100644 index 00000000..39cf266d --- /dev/null +++ b/lib/neo4j/driver/internal/deprecator.rb @@ -0,0 +1,15 @@ +module Neo4j + module Driver + module Internal + module Deprecator + def self.deprecator + @deprecator ||= ActiveSupport::Deprecation.new('6.0', 'neo4j-ruby-driver') + end + + def self.log_warning(old_method, new_method, version) + deprecator.deprecation_warning(old_method, new_method) + end + end + end + end +end diff --git a/ruby/neo4j/driver/internal/internal_session.rb b/ruby/neo4j/driver/internal/internal_session.rb index a9a84ef0..d14c0188 100644 --- a/ruby/neo4j/driver/internal/internal_session.rb +++ b/ruby/neo4j/driver/internal/internal_session.rb @@ -38,10 +38,20 @@ def begin_transaction(**config) end def read_transaction(**config, &block) + Deprecator.log_warning(:read_transaction, :execute_read, '6.0') transaction(AccessMode::READ, **config, &block) end def write_transaction(**config, &block) + Deprecator.log_warning(:write_transaction, :execute_write, '6.0') + transaction(AccessMode::WRITE, **config, &block) + end + + def execute_read(**config, &block) + transaction(AccessMode::READ, **config, &block) + end + + def execute_write(**config, &block) transaction(AccessMode::WRITE, **config, &block) end diff --git a/spec/integration/bookmark_spec.rb b/spec/integration/bookmark_spec.rb index cb3fa96e..9563af54 100755 --- a/spec/integration/bookmark_spec.rb +++ b/spec/integration/bookmark_spec.rb @@ -2,7 +2,7 @@ RSpec.describe 'Bookmark' do def create_node_in_tx(session) - session.write_transaction { |tx| tx.run('CREATE (a:Person)') } + session.execute_write { |tx| tx.run('CREATE (a:Person)') } end def preamble(session) @@ -93,7 +93,7 @@ def expect_single_value(bookmark, value) it 'fails on invalid bookmark using tx func' do bookmark = Neo4j::Driver::Bookmark.from('hi, this is an invalid bookmark') driver.session(bookmarks: bookmark) do |session| - expect { session.read_transaction { |tx| tx.run('RETURN 1').single } } + expect { session.execute_read { |tx| tx.run('RETURN 1').single } } .to raise_error Neo4j::Driver::Exceptions::ClientException do |e| expect(e.code).to eq 'Neo.ClientError.Transaction.InvalidBookmark' end diff --git a/spec/integration/causal_clustering_spec.rb b/spec/integration/causal_clustering_spec.rb index fe88da70..9d0fc5d2 100755 --- a/spec/integration/causal_clustering_spec.rb +++ b/spec/integration/causal_clustering_spec.rb @@ -163,7 +163,7 @@ def new_session(mode) create_driver(leader.routing_uri, routing_table_purge_delay: 3.minutes) do |driver| database = 'neo4j' driver.session(database: database) do |session| - session.read_transaction { |tx| tx.run('RETURN 1').consume } + session.execute_read { |tx| tx.run('RETURN 1').consume } end expect(driver.session_factory.connection_provider.routing_table_registry .routing_table_handler(database).routing_table.routers.to_a.size).to eq 3 @@ -181,7 +181,7 @@ def new_session(mode) leader.bolt_address, ] }) do |driver| driver.session do |session| - expect(session.read_transaction { |tx| tx.run('RETURN 1').single.first }).to eq 1 + expect(session.execute_read { |tx| tx.run('RETURN 1').single.first }).to eq 1 end end end diff --git a/spec/integration/session_spec.rb b/spec/integration/session_spec.rb index bf7cf1da..bed497f9 100755 --- a/spec/integration/session_spec.rb +++ b/spec/integration/session_spec.rb @@ -22,27 +22,51 @@ end it 'executes read transaction in read session' do - test_read_transaction(Neo4j::Driver::AccessMode::READ) + test_read_methods(Neo4j::Driver::AccessMode::READ, :read_transaction) end it 'executes read transaction in write session' do - test_read_transaction(Neo4j::Driver::AccessMode::WRITE) + test_read_methods(Neo4j::Driver::AccessMode::WRITE, :read_transaction) + end + + it 'executes execute_read in read session' do + test_read_methods(Neo4j::Driver::AccessMode::READ, :execute_read) + end + + it 'executes execute_read in write session' do + test_read_methods(Neo4j::Driver::AccessMode::WRITE, :execute_read) end it 'executes write transaction in read session' do - test_write_transaction(Neo4j::Driver::AccessMode::READ) + test_write_methods(Neo4j::Driver::AccessMode::READ, :write_transaction) end it 'executes write transaction in write session' do - test_write_transaction(Neo4j::Driver::AccessMode::WRITE) + test_write_methods(Neo4j::Driver::AccessMode::WRITE, :write_transaction) + end + + it 'executes execute_write in read session' do + test_write_methods(Neo4j::Driver::AccessMode::READ, :execute_write) + end + + it 'executes execute_write in write session' do + test_write_methods(Neo4j::Driver::AccessMode::WRITE, :execute_write) end it 'rolls back write transaction in read session when function throws exception' do - test_tx_rollback_when_function_throws_exception(Neo4j::Driver::AccessMode::READ) + test_tx_rollback_when_function_throws_exception(Neo4j::Driver::AccessMode::READ, :write_transaction) end it 'rolls back write transaction in write session when function throws exception' do - test_tx_rollback_when_function_throws_exception(Neo4j::Driver::AccessMode::WRITE) + test_tx_rollback_when_function_throws_exception(Neo4j::Driver::AccessMode::WRITE, :write_transaction) + end + + it 'rolls back execute write in read session when function throws exception' do + test_tx_rollback_when_function_throws_exception(Neo4j::Driver::AccessMode::READ, :execute_write) + end + + it 'rolls back execute write in write session when function throws exception' do + test_tx_rollback_when_function_throws_exception(Neo4j::Driver::AccessMode::WRITE, :execute_write) end class RaisingWork @@ -58,7 +82,7 @@ def execute(tx) result = tx.run(@query) raise Neo4j::Driver::Exceptions::ServiceUnavailableException if (@invoked += 1) <= @failures single = result.single - tx.commit + # tx.commit single end @@ -68,99 +92,59 @@ def to_proc end it 'retries read transaction until success' do - driver.session do |session| - session.run("CREATE (:Person {name: 'Bruce Banner'})") - end - - work = RaisingWork.new('MATCH (n) RETURN n.name', 2) - - driver.session do |session| - record = session.read_transaction(&work.to_proc) - expect(record[0]).to eq 'Bruce Banner' - end + test_read_retries_until_success(:read_transaction) + end - expect(work.invoked).to eq 3 + it 'retries execute read until success' do + test_read_retries_until_success(:execute_read) end it 'retries write transaction until success' do - work = RaisingWork.new("CREATE (p:Person {name: 'Hulk'}) RETURN p", 2) - driver.session do |session| - record = session.write_transaction(&work.to_proc) - expect(record[0][:name]).to eq 'Hulk' - end - - driver.session do |session| - record = session.run("MATCH (p: Person {name: 'Hulk'}) RETURN count(p)").single - expect(record[0]).to eq 1 - end + test_write_retries_until_success(:write_transaction) + end - expect(work.invoked).to eq 3 + it 'retries execute write until success' do + test_write_retries_until_success(:execute_write) end it 'retries read transaction until failure' do - work = RaisingWork.new('MATCH (n) RETURN n.name', 3) - driver.session do |session| - expect { session.read_transaction(&work.to_proc) } - .to raise_error Neo4j::Driver::Exceptions::ServiceUnavailableException - end + test_read_retries_until_failure(:read_transaction) + end - expect(work.invoked).to eq 3 + it 'retries execute read until failure' do + test_read_retries_until_failure(:execute_read) end it 'retries write transaction until failure' do - work = RaisingWork.new("CREATE (:Person {name: 'Ronan'})", 3) - driver.session do |session| - expect { session.write_transaction(&work.to_proc) } - .to raise_error Neo4j::Driver::Exceptions::ServiceUnavailableException - end + test_write_retries_until_failure(:write_transaction) + end - driver.session do |session| - result = session.run("MATCH (p:Person {name: 'Ronan'}) RETURN count(p)") - expect(result.single[0]).to eq 0 - end - expect(work.invoked).to eq 3 + it 'retries execute write until failure' do + test_write_retries_until_failure(:execute_write) end it 'collects write transaction retry errors' do - work = RaisingWork.new("CREATE (:Person {name: 'Ronan'})", 1000) - suppressed_errors = nil - driver.session do |session| - expect { session.write_transaction(&work.to_proc) } - .to raise_error Neo4j::Driver::Exceptions::ServiceUnavailableException do |e| - expect(e.suppressed).to be_present - suppressed_errors = e.suppressed.size - end - end - - driver.session do |session| - result = session.run("MATCH (p:Person {name: 'Ronan'}) RETURN count(p)") - expect(result.single[0]).to be_zero - end + test_write_errors_collect(:write_transaction) + end - expect(work.invoked).to eq suppressed_errors + 1 + it 'collects execute write retry errors' do + test_write_errors_collect(:execute_write) end it 'collects read transaction retry errors' do - work = RaisingWork.new('MATCH (n) RETURN n.name', 1000) - suppressed_errors = nil - driver.session do |session| - expect { session.read_transaction(&work.to_proc) } - .to raise_error Neo4j::Driver::Exceptions::ServiceUnavailableException do |e| - expect(e.suppressed).to be_present - suppressed_errors = e.suppressed.size - end - end + test_read_errors_collect(:read_transaction) + end - expect(work.invoked).to eq suppressed_errors + 1 + it 'collects execute read retry errors' do + test_read_errors_collect(:execute_read) end it 'commits read transaction without success' do - session = driver.session - expectEmptyBookmark(session.last_bookmark) - answer = session.read_transaction { |tx| tx.run('RETURN 42').single[0] } - session.close - expect(answer).to eq(42) - expect(session.last_bookmark).not_to be nil + test_commit_read_without_success(:read_transaction) + end + + it 'commits execute read without success' do + test_commit_read_without_success(:execute_read) end def expectEmptyBookmark(bookmark) @@ -176,14 +160,11 @@ def expectNotEmptyBookmark(bookmark) end it 'commits write transaction without success' do - driver.session do |session| - answer = session.write_transaction { |tx| tx.run("CREATE (:Person {name: 'Thor Odinson'}) RETURN 42").single[0] } - expect(answer).to eq(42) - end - val = driver.session do |session| - session.run("MATCH (p:Person {name: 'Thor Odinson'}) RETURN count(p)").single[0] - end - expect(val).to eq(1) + test_commit_write_without_success(:write_transaction) + end + + it 'commits execute write without success' do + test_commit_write_without_success(:execute_write) end it 'rolls back read transaction with failure' do @@ -216,33 +197,19 @@ def expectNotEmptyBookmark(bookmark) end it 'rolls back read transaction when exception is thrown' do - driver.session do |session| - expectEmptyBookmark(session.last_bookmark) - expect do - session.read_transaction do |tx| - val = tx.run('RETURN 42').single[0] - raise Neo4j::Driver::Exceptions::IllegalStateException if val == 42 - 1 - end - end.to raise_error Neo4j::Driver::Exceptions::IllegalStateException - expectEmptyBookmark(session.last_bookmark) - end + test_read_rollback_on_exception(:read_transaction) + end + + it 'rolls back execute read when exception is thrown' do + test_read_rollback_on_exception(:execute_read) end it 'rolls back write transaction when exception is thrown' do - driver.session do |session| - expectEmptyBookmark(session.last_bookmark) - expect do - session.write_transaction do |tx| - tx.run("CREATE (:Person {name: 'Natasha Romanoff'})") - raise Neo4j::Driver::Exceptions::IllegalStateException - end - end.to raise_error Neo4j::Driver::Exceptions::IllegalStateException - end - val = driver.session do |session| - session.run("MATCH (p:Person {name: 'Natasha Romanoff'}) RETURN count(p)").single[0] - end - expect(val).to eq(0) + test_write_rollback_on_exception(:write_transaction) + end + + it 'rolls back execute write when exception is thrown' do + test_write_rollback_on_exception(:execute_write) end it 'read tx rolled back when marked both success and failure' do @@ -441,17 +408,11 @@ def expectNotEmptyBookmark(bookmark) end it 'executes transaction work in caller thread' do - max_failures = 3 - caller_thread = Thread.current - failures = 0 - result = driver.session do |session| - session.read_transaction do - expect(Thread.current).to eq caller_thread - raise Neo4j::Driver::Exceptions::ServiceUnavailableException, 'Oh no' if (failures += 1) < max_failures - 'Hello' - end - end - expect(result).to eq 'Hello' + test_read_work_in_caller_thread(:read_transaction) + end + + it 'executes execute_read work in caller thread' do + test_read_work_in_caller_thread(:execute_read) end it 'Throws Run Failure Immediately And Closes Successfully' do @@ -515,22 +476,11 @@ def expectNotEmptyBookmark(bookmark) context "with 'bolt' scheme" do let(:scheme) { 'bolt' } # to avoid routing logic triggered by 'neo4j' scheme it 'does not retry on connection acquisition timeout' do - max_pool_size = 3 - config = { - max_connection_pool_size: max_pool_size, - connection_acquisition_timeout: 0.seconds, - max_transaction_retry_time: 42.days # retry for a really long time - } - Neo4j::Driver::GraphDatabase.driver(uri, basic_auth_token, **config) do |driver| - max_pool_size.times { driver.session.begin_transaction } - - invocations = Concurrent::AtomicFixnum.new - expect { driver.session.write_transaction { invocations.increment } } - .to raise_error Neo4j::Driver::Exceptions::ClientException, - /^Unable to acquire connection from the pool within configured maximum time of 0/ - # work should never be invoked - expect(invocations.value).to be_zero - end + test_retry_on_connection_acquisition_timeout(:write_transaction) + end + + it 'execute write does not retry on connection acquisition timeout' do + test_retry_on_connection_acquisition_timeout(:execute_write) end end @@ -640,10 +590,13 @@ def expectNotEmptyBookmark(bookmark) end it 'Allow Returning Null From Transaction Function' do - driver.session do |session| - expect(session.write_transaction { nil }).to be_nil - expect(session.read_transaction { nil }).to be_nil - end + test_write_read_allow_return_null(:write_transaction) + test_write_read_allow_return_null(:read_transaction) + end + + it 'Allow Returning Null From execute_write/read Function' do + test_write_read_allow_return_null(:execute_write) + test_write_read_allow_return_null(:execute_read) end it 'Allow Iterating Over Empty Result' do @@ -753,24 +706,25 @@ def count_nodes_with_id(id) end end - def test_read_transaction(mode) + def test_read_methods(mode, method_name) driver.session do |session| session.run("CREATE (:Person {name: 'Tony Stark'})").consume session.run("CREATE (:Person {name: 'Steve Rogers'})").consume end driver.session(default_access_mode: mode) do |session| - names = session.read_transaction do |tx| + names = session.send(method_name) do |tx| tx.run('MATCH (p:Person) RETURN p.name AS name').collect do |result| result[:name] end end + expect(names).to contain_exactly('Tony Stark', 'Steve Rogers') end end - def test_write_transaction(mode) + def test_write_methods(mode, method_name) driver.session(default_access_mode: mode) do |session| - session.write_transaction do |tx| + session.send(method_name) do |tx| node = tx.run("CREATE (s:Shield {material: 'Vibranium'}) RETURN s").next['s'] expect(node.properties[:material]).to eq('Vibranium') end @@ -781,13 +735,189 @@ def test_write_transaction(mode) end end - def test_tx_rollback_when_function_throws_exception(mode) + def test_read_retries_until_success(method_name) + driver.session do |session| + session.run("CREATE (:Person {name: 'Bruce Banner'})") + end + + work = RaisingWork.new('MATCH (n) RETURN n.name', 2) + + driver.session do |session| + record = session.send(method_name, &work.to_proc) + expect(record[0]).to eq 'Bruce Banner' + end + + expect(work.invoked).to eq 3 + end + + def test_write_retries_until_success(method_name) + work = RaisingWork.new("CREATE (p:Person {name: 'Hulk'}) RETURN p", 2) + driver.session do |session| + record = session.send(method_name, &work.to_proc) + expect(record[0][:name]).to eq 'Hulk' + end + + driver.session do |session| + record = session.run("MATCH (p: Person {name: 'Hulk'}) RETURN count(p)").single + expect(record[0]).to eq 1 + end + + expect(work.invoked).to eq 3 + end + + def test_read_retries_until_failure(method_name) + work = RaisingWork.new('MATCH (n) RETURN n.name', 3) + driver.session do |session| + expect { session.send(method_name, &work.to_proc) } + .to raise_error Neo4j::Driver::Exceptions::ServiceUnavailableException + end + + expect(work.invoked).to eq 3 + end + + def test_write_retries_until_failure(method_name) + work = RaisingWork.new("CREATE (:Person {name: 'Ronan'})", 3) + driver.session do |session| + expect { session.send(method_name, &work.to_proc) } + .to raise_error Neo4j::Driver::Exceptions::ServiceUnavailableException + end + + driver.session do |session| + result = session.run("MATCH (p:Person {name: 'Ronan'}) RETURN count(p)") + expect(result.single[0]).to eq 0 + end + expect(work.invoked).to eq 3 + end + + def test_write_errors_collect(method_name) + work = RaisingWork.new("CREATE (:Person {name: 'Ronan'})", 1000) + suppressed_errors = nil + driver.session do |session| + expect { session.send(method_name, &work.to_proc) } + .to raise_error Neo4j::Driver::Exceptions::ServiceUnavailableException do |e| + expect(e.suppressed).to be_present + suppressed_errors = e.suppressed.size + end + end + + driver.session do |session| + result = session.run("MATCH (p:Person {name: 'Ronan'}) RETURN count(p)") + expect(result.single[0]).to be_zero + end + + expect(work.invoked).to eq suppressed_errors + 1 + end + + def test_read_errors_collect(method_name) + work = RaisingWork.new('MATCH (n) RETURN n.name', 1000) + suppressed_errors = nil + driver.session do |session| + expect { session.send(method_name, &work.to_proc) } + .to raise_error Neo4j::Driver::Exceptions::ServiceUnavailableException do |e| + expect(e.suppressed).to be_present + suppressed_errors = e.suppressed.size + end + end + + expect(work.invoked).to eq suppressed_errors + 1 + end + + def test_commit_read_without_success(method_name) + session = driver.session + expectEmptyBookmark(session.last_bookmark) + answer = session.send(method_name) { |tx| tx.run('RETURN 42').single[0] } + session.close + expect(answer).to eq(42) + expect(session.last_bookmark).not_to be nil + end + + def test_commit_write_without_success(method_name) + driver.session do |session| + answer = session.send(method_name) { |tx| tx.run("CREATE (:Person {name: 'Thor Odinson'}) RETURN 42").single[0] } + expect(answer).to eq(42) + end + val = driver.session do |session| + session.run("MATCH (p:Person {name: 'Thor Odinson'}) RETURN count(p)").single[0] + end + expect(val).to eq(1) + end + + def test_read_rollback_on_exception(method_name) + driver.session do |session| + expectEmptyBookmark(session.last_bookmark) + expect do + session.send(method_name) do |tx| + val = tx.run('RETURN 42').single[0] + raise Neo4j::Driver::Exceptions::IllegalStateException if val == 42 + 1 + end + end.to raise_error Neo4j::Driver::Exceptions::IllegalStateException + expectEmptyBookmark(session.last_bookmark) + end + end + + def test_write_rollback_on_exception(method_name) + driver.session do |session| + expectEmptyBookmark(session.last_bookmark) + expect do + session.send(method_name) do |tx| + tx.run("CREATE (:Person {name: 'Natasha Romanoff'})") + raise Neo4j::Driver::Exceptions::IllegalStateException + end + end.to raise_error Neo4j::Driver::Exceptions::IllegalStateException + end + val = driver.session do |session| + session.run("MATCH (p:Person {name: 'Natasha Romanoff'}) RETURN count(p)").single[0] + end + expect(val).to eq(0) + end + + def test_read_work_in_caller_thread(method_name) + max_failures = 3 + caller_thread = Thread.current + failures = 0 + result = driver.session do |session| + session.send(method_name) do + expect(Thread.current).to eq caller_thread + raise Neo4j::Driver::Exceptions::ServiceUnavailableException, 'Oh no' if (failures += 1) < max_failures + 'Hello' + end + end + expect(result).to eq 'Hello' + end + + def test_retry_on_connection_acquisition_timeout(method_name) + max_pool_size = 3 + config = { + max_connection_pool_size: max_pool_size, + connection_acquisition_timeout: 0.seconds, + max_transaction_retry_time: 42.days # retry for a really long time + } + Neo4j::Driver::GraphDatabase.driver(uri, basic_auth_token, **config) do |driver| + max_pool_size.times { driver.session.begin_transaction } + + invocations = Concurrent::AtomicFixnum.new + expect { driver.session.send(method_name) { invocations.increment } } + .to raise_error Neo4j::Driver::Exceptions::ClientException, + /^Unable to acquire connection from the pool within configured maximum time of 0/ + # work should never be invoked + expect(invocations.value).to be_zero + end + end + + def test_write_read_allow_return_null(method_name) + driver.session do |session| + expect(session.send(method_name) { nil }).to be_nil + end + end + + def test_tx_rollback_when_function_throws_exception(mode, method_name) driver.session(default_access_mode: mode) do |session| expect do - session.write_transaction do |tx| + session.send(method_name) do |tx| tx.run("CREATE (:Person {name: 'Thanos'})") tx.run('UNWIND range(0, 1) AS i RETURN 10/i') - tx.commit + # tx.commit end end.to raise_error Neo4j::Driver::Exceptions::ClientException, '/ by zero' end diff --git a/spec/neo4j/driver/duration_spec.rb b/spec/neo4j/driver/duration_spec.rb index ac7e9f28..7db70ce4 100644 --- a/spec/neo4j/driver/duration_spec.rb +++ b/spec/neo4j/driver/duration_spec.rb @@ -4,7 +4,7 @@ describe 'param' do subject(:result) do driver.session do |session| - session.read_transaction { |tx| tx.run('RETURN $param', param: param).single.first } + session.execute_read { |tx| tx.run('RETURN $param', param: param).single.first } end end @@ -74,7 +74,7 @@ describe 'cypher functions' do subject(:result) do driver.session do |session| - session.read_transaction { |tx| tx.run("RETURN duration('#{duration}')").single.first } + session.execute_read { |tx| tx.run("RETURN duration('#{duration}')").single.first } end end @@ -146,7 +146,7 @@ describe 'roundtrip ruby check' do subject do driver.session do |session| - session.read_transaction do |tx| + session.execute_read do |tx| dt = tx.run('RETURN duration($param)', param: param).single.first dt == tx.run('RETURN $param', param: dt).single.first end @@ -159,7 +159,7 @@ describe 'roundtrip neo4j check' do subject do driver.session do |session| - session.read_transaction do |tx| + session.execute_read do |tx| dt = tx.run('RETURN duration($param)', param: param).single.first tx.run('RETURN duration($param) = $dt', param: param, dt: dt).single.first end diff --git a/spec/neo4j/driver/graph_database_spec.rb b/spec/neo4j/driver/graph_database_spec.rb index 577c50e3..8c429ab4 100644 --- a/spec/neo4j/driver/graph_database_spec.rb +++ b/spec/neo4j/driver/graph_database_spec.rb @@ -3,7 +3,7 @@ RSpec.describe Neo4j::Driver::GraphDatabase do def simple_query(driver) driver.session do |session| - session.read_transaction { |tx| tx.run('RETURN 1').single.first } + session.execute_read { |tx| tx.run('RETURN 1').single.first } end end diff --git a/spec/neo4j/driver/result_spec.rb b/spec/neo4j/driver/result_spec.rb index 70b9acc3..aa0ea97b 100644 --- a/spec/neo4j/driver/result_spec.rb +++ b/spec/neo4j/driver/result_spec.rb @@ -35,7 +35,7 @@ driver.session do |session| session.run('UNWIND range(1, 100) AS x CREATE (:Property {id: x})').consume query = 'MATCH (p:Property) RETURN p' - session.read_transaction do |tx| + session.execute_read do |tx| expect(100.times.map { tx.run(query) }.map(&:to_a).flatten.map { |record| record[:p][:id] }.count).to eq 10_000 end end diff --git a/spec/neo4j/driver/simplified_examples_spec.rb b/spec/neo4j/driver/simplified_examples_spec.rb index c61e36ac..74e09018 100644 --- a/spec/neo4j/driver/simplified_examples_spec.rb +++ b/spec/neo4j/driver/simplified_examples_spec.rb @@ -44,10 +44,10 @@ expect(result.first).to eq 'John' end - it 'raises type mismatch error read_transaction' do + it 'raises type mismatch error execute_read' do driver.session do |session| expect do - session.read_transaction do |tx| + session.execute_read do |tx| tx.run('MATCH (r) MATCH ()-[r]-() RETURN r') end end.to raise_error(Neo4j::Driver::Exceptions::ClientException, /Type mismatch:/) @@ -66,11 +66,11 @@ it 'raise exception on delete without detach' do driver.session do |session| - session.write_transaction do |tx| + session.execute_write do |tx| tx.run('CREATE (:Label)-[:REL]->()') end expect do - session.write_transaction do |tx| + session.execute_write do |tx| tx.run('MATCH (l:Label) DELETE l') end end.to raise_error(Neo4j::Driver::Exceptions::ClientException, /Cannot delete/) @@ -80,7 +80,7 @@ it 'accepts transaction config' do driver.session do |session| - session.read_transaction(timeout: 1.minute, metadata: { a: 1, b: 'string' }) do |tx| + session.execute_read(timeout: 1.minute, metadata: { a: 1, b: 'string' }) do |tx| expect(tx.run('RETURN 1').single.first).to eq 1 end end @@ -140,7 +140,7 @@ it 'handles multiple queries in a transaction' do driver.session do |session| - session.read_transaction do |tx| + session.execute_read do |tx| tx.run('RETURN 1') expect(tx.run('RETURN 2').next.first).to eq 2 end diff --git a/spec/neo4j/driver/temporal_types_spec.rb b/spec/neo4j/driver/temporal_types_spec.rb index 60c1c7bf..1a0abdb8 100644 --- a/spec/neo4j/driver/temporal_types_spec.rb +++ b/spec/neo4j/driver/temporal_types_spec.rb @@ -4,7 +4,7 @@ describe 'param' do subject do driver.session do |session| - session.write_transaction { |tx| tx.run('RETURN $param', param: param).single.first } + session.execute_write { |tx| tx.run('RETURN $param', param: param).single.first } end end @@ -39,7 +39,7 @@ describe 'cypher functions' do subject do driver.session do |session| - session.write_transaction { |tx| tx.run("RETURN #{function}").single.first } + session.execute_write { |tx| tx.run("RETURN #{function}").single.first } end end @@ -88,7 +88,7 @@ describe 'datetime roundtrip ruby check' do subject do driver.session do |session| - session.write_transaction do |tx| + session.execute_write do |tx| dt = tx.run('RETURN datetime($param)', param: param).single.first dt == tx.run('RETURN $param', param: dt).single.first end @@ -129,7 +129,7 @@ describe 'datetime roundtrip neo4j check' do subject do driver.session do |session| - session.write_transaction do |tx| + session.execute_write do |tx| dt = tx.run('RETURN datetime($param)', param: param).single.first tx.run('RETURN datetime($param) = $dt', param: param, dt: dt).single.first end diff --git a/spec/neo4j/driver/types/local_date_time_spec.rb b/spec/neo4j/driver/types/local_date_time_spec.rb index 8d87703d..868a484a 100644 --- a/spec/neo4j/driver/types/local_date_time_spec.rb +++ b/spec/neo4j/driver/types/local_date_time_spec.rb @@ -22,7 +22,7 @@ describe 'cypher functions' do subject do driver.session do |session| - session.read_transaction { |tx| tx.run("RETURN #{function}").single.first } + session.execute_read { |tx| tx.run("RETURN #{function}").single.first } end end @@ -39,7 +39,7 @@ describe 'localdatetime roundtrip ruby check' do subject do driver.session do |session| - session.read_transaction do |tx| + session.execute_read do |tx| dt = tx.run('RETURN localdatetime($param)', param: param).single.first dt == tx.run('RETURN $param', param: dt).single.first end @@ -56,7 +56,7 @@ describe 'localdatetime roundtrip neo4j check' do subject do driver.session do |session| - session.read_transaction do |tx| + session.execute_read do |tx| dt = tx.run('RETURN localdatetime($param)', param: param).single.first tx.run('RETURN localdatetime($param) = $dt', param: param, dt: dt).single.first end diff --git a/spec/neo4j/driver/types/local_time_spec.rb b/spec/neo4j/driver/types/local_time_spec.rb index fa8c3cf2..b1a9ef04 100644 --- a/spec/neo4j/driver/types/local_time_spec.rb +++ b/spec/neo4j/driver/types/local_time_spec.rb @@ -22,7 +22,7 @@ describe 'cypher functions' do subject do driver.session do |session| - session.write_transaction { |tx| tx.run("RETURN #{function}").single.first } + session.execute_write { |tx| tx.run("RETURN #{function}").single.first } end end @@ -39,7 +39,7 @@ describe 'datetime roundtrip ruby check' do subject do driver.session do |session| - session.write_transaction do |tx| + session.execute_write do |tx| dt = tx.run('RETURN localtime($param)', param: param).single.first dt == tx.run('RETURN $param', param: dt).single.first end @@ -56,7 +56,7 @@ describe 'datetime roundtrip neo4j check' do subject do driver.session do |session| - session.write_transaction do |tx| + session.execute_write do |tx| dt = tx.run('RETURN localtime($param)', param: param).single.first tx.run('RETURN localtime($param) = $dt', param: param, dt: dt).single.first end diff --git a/spec/neo4j/driver/types/node_spec.rb b/spec/neo4j/driver/types/node_spec.rb index d3349a45..62a365d2 100644 --- a/spec/neo4j/driver/types/node_spec.rb +++ b/spec/neo4j/driver/types/node_spec.rb @@ -3,7 +3,7 @@ RSpec.describe Neo4j::Driver::Types::Node do subject do driver.session do |session| - session.write_transaction do |tx| + session.execute_write do |tx| tx.run('CREATE (p:Person{created: $date}) RETURN p', date: date).single.first end end @@ -11,7 +11,7 @@ let(:updated) do driver.session do |session| - session.write_transaction do |tx| + session.execute_write do |tx| tx.run('MATCH (p:Person) SET p.updated = $date RETURN p', date: date + 2.days).single.first end end @@ -19,7 +19,7 @@ let(:other) do driver.session do |session| - session.write_transaction do |tx| + session.execute_write do |tx| tx.run('CREATE (p:Person{created: $date}) RETURN p', date: date).single.first end end diff --git a/spec/neo4j/driver/types/offset_time_spec.rb b/spec/neo4j/driver/types/offset_time_spec.rb index 3bbaca3f..22361d11 100644 --- a/spec/neo4j/driver/types/offset_time_spec.rb +++ b/spec/neo4j/driver/types/offset_time_spec.rb @@ -23,7 +23,7 @@ describe 'cypher functions' do subject do driver.session do |session| - session.write_transaction { |tx| tx.run("RETURN #{function}").single.first } + session.execute_write { |tx| tx.run("RETURN #{function}").single.first } end end @@ -47,7 +47,7 @@ describe 'offset_time roundtrip ruby check' do subject do driver.session do |session| - session.write_transaction do |tx| + session.execute_write do |tx| dt = tx.run('RETURN time($param)', param: param).single.first dt == tx.run('RETURN $param', param: dt).single.first end @@ -64,7 +64,7 @@ describe 'offset_time roundtrip neo4j check' do subject do driver.session do |session| - session.write_transaction do |tx| + session.execute_write do |tx| dt = tx.run('RETURN time($param)', param: param).single.first tx.run('RETURN time($param) = $dt', param: param, dt: dt).single.first end diff --git a/spec/neo4j/driver/types/path_spec.rb b/spec/neo4j/driver/types/path_spec.rb index 4ad837a5..1a2a87ec 100644 --- a/spec/neo4j/driver/types/path_spec.rb +++ b/spec/neo4j/driver/types/path_spec.rb @@ -4,7 +4,7 @@ shared_examples 'path' do subject do driver.session do |session| - session.write_transaction do |tx| + session.execute_write do |tx| tx.run("CREATE p=#{path_fragment} RETURN p").single.first end end diff --git a/spec/neo4j/driver/types/relationship_spec.rb b/spec/neo4j/driver/types/relationship_spec.rb index 430d9629..eea74c2e 100644 --- a/spec/neo4j/driver/types/relationship_spec.rb +++ b/spec/neo4j/driver/types/relationship_spec.rb @@ -3,7 +3,7 @@ RSpec.describe Neo4j::Driver::Types::Relationship do subject do session = driver.session - session.write_transaction { |tx| tx.run('CREATE ()-[f:friend_of{strength: 1}]->() RETURN f').single.first } + session.execute_write { |tx| tx.run('CREATE ()-[f:friend_of{strength: 1}]->() RETURN f').single.first } ensure session&.close end diff --git a/spec/neo4j/driver/types_spec.rb b/spec/neo4j/driver/types_spec.rb index 25997695..50d07962 100644 --- a/spec/neo4j/driver/types_spec.rb +++ b/spec/neo4j/driver/types_spec.rb @@ -3,7 +3,7 @@ RSpec.describe Neo4j::Driver do subject do driver.session do |session| - session.write_transaction { |tx| tx.run('RETURN $param', param: param).single.first } + session.execute_write { |tx| tx.run('RETURN $param', param: param).single.first } end end diff --git a/spec/neo4j/driver/util/test_util.rb b/spec/neo4j/driver/util/test_util.rb index f9a7e247..d71d510b 100644 --- a/spec/neo4j/driver/util/test_util.rb +++ b/spec/neo4j/driver/util/test_util.rb @@ -13,7 +13,7 @@ def clean_db(driver) def count_nodes(driver, bookmark) driver.session(bookmarks: bookmark) do |session| - session.read_transaction { |tx| tx.run('MATCH (n) RETURN count(n)').single.first } + session.execute_read { |tx| tx.run('MATCH (n) RETURN count(n)').single.first } end end @@ -24,7 +24,7 @@ def clean_db_in_session(session) end def delete_batch_of_nodes(session) - session.write_transaction do |tx| + session.execute_write do |tx| tx.run('MATCH (n) WITH n LIMIT 10000 DETACH DELETE n RETURN count(n)').single.first end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 80630bda..77c792c7 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -40,4 +40,5 @@ config.filter_run_excluding version: method(:not_version?) config.filter_run_excluding concurrency: true unless RUBY_PLATFORM == 'java' config.exclude_pattern = 'spec/ruby/**/*_spec.rb' if RUBY_PLATFORM == 'java' + Neo4j::Driver::Internal::Deprecator.deprecator.behavior = :silence end