neo4j-ruby-driver 4.4.0.beta.1 → 4.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c795045f581183398e15ba5c44c1f89b10ea234a9a6dc1e46fecd8c02b857bb3
4
- data.tar.gz: 1859daea7265d9409d001e748048ab97837fe26895d80fe4e24773b1b51ed49d
3
+ metadata.gz: 6fd1245f505176d11efea03e96cc022216e0e93f93581aaf6b55d6397097cf2d
4
+ data.tar.gz: 7a7394025131851020cfda11949bed86860be9fb599b22efe458e8d79bcbffc2
5
5
  SHA512:
6
- metadata.gz: 5f72367997a92a64e8a75ef08bfca59d0acffaac7589e594b69d8fead9173dc3339d6b3dc26ad63ae1f2f0f7cde0a9f172908e9112b92b3496c209ef8c99e01d
7
- data.tar.gz: 7bee1a6da116192d42ad2d9b86091d787211af683278c9cfe136f3c8ebf3d1d8c807834b44d5162a308b47b5208ee8e0b40302961a5dfb83c16a7180353d617e
6
+ metadata.gz: b77c6e15952c126b67a67fc953c9da825fb8aee8399c8929eb8bc45d43542b0f88ef2d019de39877409c9c5fb73e3d04972ad79dcbda9f8b64a62f47120e6a34
7
+ data.tar.gz: d1a0538ad1ec75804854efaf5d0cd951573f25fb1b976adf0fe606826d87e8141f30453cd77eec1b390201f3d80515d0094840855121f43766e11db5d0d1108e
@@ -4,9 +4,7 @@ module Neo4j::Driver
4
4
  class GraphDatabase
5
5
  class << self
6
6
  extend AutoClosable
7
- extend Synchronizable
8
7
  auto_closable :driver, :routing_driver
9
- sync :driver
10
8
 
11
9
  def driver(uri, auth_token = nil, **config)
12
10
  internal_driver(uri, auth_token, config, Internal::DriverFactory.new)
@@ -66,7 +64,7 @@ module Neo4j::Driver
66
64
 
67
65
  def close_driver(driver, uri, log)
68
66
  driver.close
69
- rescue StandardError => close_error
67
+ rescue => close_error
70
68
  log.warn { "Unable to close driver towards URI: #{uri}\n#{close_error}" }
71
69
  end
72
70
 
@@ -7,7 +7,7 @@ module Neo4j::Driver
7
7
 
8
8
  attr_reader :server_agent, :server_address, :server_version
9
9
 
10
- def initialize(channel, channel_pool, logger)
10
+ def initialize(channel, channel_pool, logger, &on_pool_shutdown)
11
11
  @log = logger
12
12
  @channel = channel
13
13
  @message_dispatcher = channel.attributes[:message_dispatcher]
@@ -16,6 +16,7 @@ module Neo4j::Driver
16
16
  @server_version = channel.attributes[:server_version]
17
17
  @protocol = Messaging::BoltProtocol.for_channel(channel)
18
18
  @channel_pool = channel_pool
19
+ @on_pool_shutdow = on_pool_shutdown
19
20
  # @release_future = java.util.concurrent.CompletableFuture.new
20
21
  # @clock = clock
21
22
  # @connection_read_timeout = Connection::ChannelAttributes.connection_read_timeout(channel) || nil
@@ -89,10 +90,25 @@ module Neo4j::Driver
89
90
  # auto-read could've been disabled, re-enable it to automatically receive response for RESET
90
91
  @channel.auto_read = true
91
92
  @message_dispatcher.enqueue(reset_handler)
92
- @channel.write_and_flush(Messaging::Request::ResetMessage::RESET) #.add_listener(-> (_future) { register_connection_read_timeout(@channel) })
93
+ write_to_channel(Messaging::Request::ResetMessage::RESET, true)
93
94
  end
94
95
  end
95
96
 
97
+ def write_to_channel(message, flush = false)
98
+ if flush
99
+ @channel.write_and_flush(message) #.add_listener(-> (_future) { register_connection_read_timeout(@channel) })
100
+ else
101
+ @channel.write(message)
102
+ end
103
+ rescue EOFError, Errno::ECONNRESET, Errno::EPIPE => e
104
+ terminate_and_release(e.message)
105
+ @log.debug("Shutting down connection pool towards #{@server_address} due to error: #{e.message}")
106
+ @channel_pool.shutdown(&:close)
107
+ @on_pool_shutdow.call
108
+ # should remove routing table entry as well
109
+ raise Exceptions::SessionExpiredException, e.message
110
+ end
111
+
96
112
  def flush_in_event_loop
97
113
  @channel.event_loop.execute do
98
114
  @channel.flush
@@ -103,11 +119,7 @@ module Neo4j::Driver
103
119
  def write_message_in_event_loop(message, handler, flush)
104
120
  @message_dispatcher.enqueue(handler)
105
121
 
106
- if flush
107
- @channel.write_and_flush(message) #.add_listener(-> (_future) { register_connection_read_timeout(@channel) })
108
- else
109
- @channel.write(message)
110
- end
122
+ write_to_channel(message, flush)
111
123
  end
112
124
 
113
125
  def write_messages_in_event_loop(message1, handler1, message2, handler2, flush)
@@ -10,7 +10,7 @@ module Neo4j::Driver
10
10
 
11
11
  def initialize(address, connector, logger)
12
12
  @attributes = Connection::ChannelAttributes.new
13
- @stream = Connection::Stream.new(connector.connect(address))
13
+ @stream = Connection::Stream.new(connect_to_io_socket(connector, address))
14
14
  @stream.write(Connection::BoltProtocolUtil.handshake_buf)
15
15
  @stream.flush
16
16
  Connection::HandshakeHandler.new(logger).decode(self)
@@ -39,6 +39,10 @@ module Neo4j::Driver
39
39
 
40
40
  private
41
41
 
42
+ def connect_to_io_socket(connector, address)
43
+ Sync { connector.connect(address) }
44
+ end
45
+
42
46
  def bracketless(host)
43
47
  host.delete_prefix('[').delete_suffix(']')
44
48
  end
@@ -2,7 +2,7 @@ module Neo4j::Driver
2
2
  module Internal
3
3
  module Async
4
4
  module Pool
5
- class Controller < ConnectionPool
5
+ class ChannelPool < ConnectionPool
6
6
  def initialize(limit: nil, acquisition_timeout: nil, &block)
7
7
  super(size: limit, timeout: acquisition_timeout, &block)
8
8
  @available = TimedStack.new(@size, &block)
@@ -20,12 +20,12 @@ module Neo4j::Driver
20
20
 
21
21
  begin
22
22
  channel = pool.acquire
23
- @log.debug{"Channel #{channel.object_id} acquired"}
23
+ @log.debug { "Channel #{channel.object_id} acquired" }
24
24
  rescue => error
25
25
  process_acquisition_error(pool, address, error)
26
26
  end
27
27
  assert_not_closed(address, channel, pool)
28
- NetworkConnection.new(channel, pool, @log)
28
+ NetworkConnection.new(channel, pool, @log) { remove(pool) }
29
29
  end
30
30
 
31
31
  def retain_all(addresses_to_retain)
@@ -46,6 +46,12 @@ module Neo4j::Driver
46
46
  end
47
47
  end
48
48
 
49
+ def remove(pool)
50
+ @address_to_pool_lock.with_write_lock do
51
+ @address_to_pool.each { |address, value| @address_to_pool.delete(address) if value == pool }
52
+ end
53
+ end
54
+
49
55
  def in_use_connections(address)
50
56
  @address_to_pool[address]&.size || 0
51
57
  # @netty_channel_tracker.in_use_channel_count(address)
@@ -81,7 +87,7 @@ module Neo4j::Driver
81
87
  # NettyChannelPool returns future failed with TimeoutException if acquire operation takes more than
82
88
  # configured time, translate this exception to a prettier one and re-throw
83
89
  raise Neo4j::Driver::Exceptions::ClientException.new("Unable to acquire connection from the pool within configured maximum time of #{@settings.connection_acquisition_timeout.inspect}")
84
- # elsif pool.closed?
90
+ # elsif pool.closed?
85
91
  # There is a race condition where a thread tries to acquire a connection while the pool is closed by another concurrent thread.
86
92
  # Treat as failed to obtain connection for a direct driver. For a routing driver, this error should be retried.
87
93
  # raise Neo4j::Driver::Exceptions::ServiceUnavailableException, "Connection pool for server #{server_address} is closed while acquiring a connection."
@@ -109,7 +115,7 @@ module Neo4j::Driver
109
115
  end
110
116
 
111
117
  def new_pool(address)
112
- Controller.new(limit: @settings.max_connection_pool_size, acquisition_timeout: @settings.connection_acquisition_timeout) { Channel.new(address, @connector, @log) }
118
+ ChannelPool.new(limit: @settings.max_connection_pool_size, acquisition_timeout: @settings.connection_acquisition_timeout) { Channel.new(address, @connector, @log) }
113
119
  end
114
120
 
115
121
  def get_or_create_pool(address)
@@ -41,13 +41,15 @@ module Neo4j::Driver
41
41
  def supports_multi_db?
42
42
  addresses = @rediscovery.resolve
43
43
  base_error = Exceptions::ServiceUnavailableException.new("Failed to perform multi-databases feature detection with the following servers: #{addresses}")
44
- addresses.lazy.map do |address|
45
- private_suports_multi_db?(address)
44
+ addresses.each do |address|
45
+ return private_suports_multi_db?(address)
46
46
  rescue Exceptions::SecurityException
47
47
  raise
48
48
  rescue => error
49
49
  Util::Futures.combine_errors(base_error, error)
50
- end.find { |result| !result.nil? } or raise base_error
50
+ end
51
+
52
+ raise base_error
51
53
  end
52
54
 
53
55
  private
@@ -12,19 +12,19 @@ module Neo4j::Driver
12
12
 
13
13
  def get_cluster_composition(connection, database_name, bookmark, impersonated_user)
14
14
  runner = if Messaging::Request::MultiDatabaseUtil.supports_route_message?(connection)
15
- @route_message_routing_procedure_runner
16
- elsif Messaging::Request::MultiDatabaseUtil.supports_multi_database?(connection)
17
- @multi_database_routing_procedure_runner
18
- else
19
- @single_database_routing_procedure_runner
20
- end
15
+ @route_message_routing_procedure_runner
16
+ elsif Messaging::Request::MultiDatabaseUtil.supports_multi_database?(connection)
17
+ @multi_database_routing_procedure_runner
18
+ else
19
+ @single_database_routing_procedure_runner
20
+ end
21
21
 
22
22
  process_routing_response(runner.run(connection, database_name, bookmark, impersonated_user))
23
23
  end
24
24
 
25
25
  def process_routing_response(response)
26
26
  unless response.success?
27
- raise response.error.class, "Failed to run '#{invoked_procedure_string(response)}' on server. Please make sure that there is a Neo4j server or cluster up running."
27
+ raise response.error, "Failed to run '#{invoked_procedure_string(response)}' on server. Please make sure that there is a Neo4j server or cluster up running."
28
28
  end
29
29
 
30
30
  records = response.records
@@ -36,7 +36,7 @@ module Neo4j::Driver
36
36
 
37
37
  # failed to parse the record
38
38
  begin
39
- cluster = ClusterComposition.parse( records[0], Time.now)
39
+ cluster = ClusterComposition.parse(records[0], Time.now)
40
40
  rescue Exceptions::Value::ValueException => e
41
41
  raise Exceptions::ProtocolException, "#{PROTOCOL_ERROR_MESSAGE % invoked_procedure_string(response)} unparsable record received. #{e}"
42
42
  end
@@ -17,8 +17,8 @@ module Neo4j::Driver
17
17
  procedure = procedure_query(connection.server_version, database_name)
18
18
  bookmark_holder = bookmark_holder(bookmark)
19
19
  begin
20
- records = run_procedure(delegate, procedure, bookmark_holder)
21
- RoutingProcedureResponse.new(procedure, records: records)
20
+ result = run_procedure(delegate, procedure, bookmark_holder)
21
+ RoutingProcedureResponse.new(procedure, **result.error ? { error: result.error } : { records: result.result! })
22
22
  rescue => error
23
23
  handle_error(procedure, error)
24
24
  ensure
@@ -48,7 +48,7 @@ module Neo4j::Driver
48
48
  connection.protocol
49
49
  .run_in_auto_commit_transaction(connection, procedure, bookmark_holder, TransactionConfig.empty,
50
50
  Handlers::Pulln::FetchSizeUtil::UNLIMITED_FETCH_SIZE)
51
- .async_result.then(&:to_a)
51
+ .async_result.list_async
52
52
  end
53
53
 
54
54
  def release_connection(connection)
@@ -2,7 +2,6 @@ module Neo4j::Driver
2
2
  module Internal
3
3
  module Cursor
4
4
  class AsyncResultCursorImpl
5
- include Enumerable
6
5
  delegate :consume_async, :next_async, :peek_async, to: :@pull_all_handler
7
6
 
8
7
  def initialize(run_handler, pull_all_handler)
@@ -29,13 +28,7 @@ module Neo4j::Driver
29
28
  end
30
29
  end
31
30
 
32
- def each(&action)
33
- result_holder = Util::ResultHolder.new
34
- internal_for_each_async(result_holder, &action)
35
- result_holder.then { consume_async }
36
- end
37
-
38
- def to_async(&map_function)
31
+ def list_async(&map_function)
39
32
  @pull_all_handler.list_async(&block_given? ? map_function : :itself)
40
33
  end
41
34
 
@@ -49,23 +42,6 @@ module Neo4j::Driver
49
42
  @pull_all_handler.pull_all_failure_async.then { |error| run_error ? nil : error }
50
43
  end
51
44
 
52
- private def internal_for_each_async(result_holder, &action)
53
- next_async.chain do |record, error|
54
- if error
55
- result_holder.fail(error)
56
- elsif record
57
- begin
58
- yield record
59
- rescue => action_error
60
- result_holder.fail(action_error)
61
- end
62
- internal_for_each_async(result_holder, &action)
63
- else
64
- result_holder.succeed(nil)
65
- end
66
- end
67
- end
68
-
69
45
  def map_successful_run_completion_async
70
46
  run_error&.then(&Util::ResultHolder.method(:failed)) || Util::ResultHolder.successful(self)
71
47
  end
@@ -34,6 +34,11 @@ module Neo4j::Driver
34
34
  @delegate.each(&action)
35
35
  end
36
36
 
37
+ def list_async(&block)
38
+ assert_not_disposed
39
+ @delegate.list_async(&block)
40
+ end
41
+
37
42
  def discard_all_failure_async
38
43
  @disposed = true
39
44
  @delegate.discard_all_failure_async
@@ -4,7 +4,6 @@ module Neo4j::Driver
4
4
  # This is the Pull All response handler that handles pull all messages in Bolt v3 and previous protocol versions.
5
5
  class LegacyPullAllResponseHandler
6
6
  include Spi::ResponseHandler
7
- include Enumerable
8
7
  RECORD_BUFFER_LOW_WATERMARK = ENV['record_buffer_low_watermark']&.to_i || 300
9
8
  RECORD_BUFFER_HIGH_WATERMARK = ENV['record_buffer_high_watermark']&.to_i || 1000
10
9
 
@@ -83,12 +82,15 @@ module Neo4j::Driver
83
82
  Util::ResultHolder.successful(@summary)
84
83
  end
85
84
 
86
- def each
87
- pull_all_failure_async.then do
85
+ def list_async(&block)
86
+ pull_all_failure_async.then do |error|
87
+ raise error if error
88
88
  unless @finished
89
89
  raise Exceptions::IllegalStateException, "Can't get records as list because SUCCESS or FAILURE did not arrive"
90
90
  end
91
- @records.each { |record| yield record }
91
+ @records.items.map(&block)
92
+ ensure
93
+ @records.items.clear
92
94
  end
93
95
  end
94
96
 
@@ -3,7 +3,6 @@ module Neo4j::Driver
3
3
  module Handlers
4
4
  module Pulln
5
5
  class AutoPullResponseHandler < BasicPullResponseHandler
6
- include Enumerable
7
6
  delegate :signal, to: :@records
8
7
  LONG_MAX_VALUE = 2 ** 63 - 1
9
8
 
@@ -79,12 +78,14 @@ module Neo4j::Driver
79
78
  completed_with_value_if_no_failure(@summary)
80
79
  end
81
80
 
82
- def each
81
+ def list_async(&block)
83
82
  pull_all_async.then do
84
83
  unless done?
85
84
  raise Exceptions::IllegalStateException, "Can't get records as list because SUCCESS or FAILURE did not arrive"
86
85
  end
87
- @records.each { |record| yield record }
86
+ @records.items.map(&block)
87
+ ensure
88
+ @records.items.clear
88
89
  end
89
90
  end
90
91
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Neo4j
4
4
  module Driver
5
- VERSION = '4.4.0.beta.1'
5
+ VERSION = '4.4.1'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: neo4j-ruby-driver
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.4.0.beta.1
4
+ version: 4.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Heinrich Klobuczek
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-09-25 00:00:00.000000000 Z
11
+ date: 2023-01-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -287,9 +287,9 @@ files:
287
287
  - ruby/neo4j/driver/internal/async/outbound/chunk_aware_byte_buf_output.rb
288
288
  - ruby/neo4j/driver/internal/async/outbound/outbound_message_handler.rb
289
289
  - ruby/neo4j/driver/internal/async/pool/channel.rb
290
+ - ruby/neo4j/driver/internal/async/pool/channel_pool.rb
290
291
  - ruby/neo4j/driver/internal/async/pool/channel_tracker.rb
291
292
  - ruby/neo4j/driver/internal/async/pool/connection_pool_impl.rb
292
- - ruby/neo4j/driver/internal/async/pool/controller.rb
293
293
  - ruby/neo4j/driver/internal/async/pool/netty_channel_health_checker.rb
294
294
  - ruby/neo4j/driver/internal/async/pool/netty_channel_pool.rb
295
295
  - ruby/neo4j/driver/internal/async/pool/network_connection_factory.rb
@@ -496,11 +496,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
496
496
  version: '3.1'
497
497
  required_rubygems_version: !ruby/object:Gem::Requirement
498
498
  requirements:
499
- - - ">"
499
+ - - ">="
500
500
  - !ruby/object:Gem::Version
501
- version: 1.3.1
501
+ version: '0'
502
502
  requirements: []
503
- rubygems_version: 3.3.7
503
+ rubygems_version: 3.3.26
504
504
  signing_key:
505
505
  specification_version: 4
506
506
  summary: ''