neo4j-ruby-driver 4.4.0.alpha.2 → 4.4.0.alpha.5

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.
Files changed (28) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +12 -1
  3. data/ruby/neo4j/driver/config.rb +8 -10
  4. data/ruby/neo4j/driver/graph_database.rb +0 -60
  5. data/ruby/neo4j/driver/internal/async/connection/channel_connector_impl.rb +8 -2
  6. data/ruby/neo4j/driver/internal/async/inbound/inbound_message_dispatcher.rb +1 -1
  7. data/ruby/neo4j/driver/internal/async/network_connection.rb +15 -22
  8. data/ruby/neo4j/driver/internal/async/pool/channel.rb +1 -0
  9. data/ruby/neo4j/driver/internal/async/pool/connection_pool_impl.rb +1 -0
  10. data/ruby/neo4j/driver/internal/cluster/loadbalancing/load_balancer.rb +1 -1
  11. data/ruby/neo4j/driver/internal/cluster/routing_table_registry_impl.rb +1 -1
  12. data/ruby/neo4j/driver/internal/cursor/async_result_cursor_impl.rb +13 -21
  13. data/ruby/neo4j/driver/internal/cursor/async_result_cursor_only_factory.rb +2 -3
  14. data/ruby/neo4j/driver/internal/driver_factory.rb +10 -11
  15. data/ruby/neo4j/driver/internal/handlers/channel_releasing_reset_response_handler.rb +11 -10
  16. data/ruby/neo4j/driver/internal/handlers/legacy_pull_all_response_handler.rb +6 -6
  17. data/ruby/neo4j/driver/internal/handlers/pulln/auto_pull_response_handler.rb +7 -4
  18. data/ruby/neo4j/driver/internal/handlers/reset_response_handler.rb +1 -1
  19. data/ruby/neo4j/driver/internal/handlers/run_response_handler.rb +2 -1
  20. data/ruby/neo4j/driver/internal/internal_bookmark.rb +3 -5
  21. data/ruby/neo4j/driver/internal/internal_driver.rb +1 -1
  22. data/ruby/neo4j/driver/internal/internal_entity.rb +3 -5
  23. data/ruby/neo4j/driver/internal/messaging/v3/bolt_protocol_v3.rb +2 -3
  24. data/ruby/neo4j/driver/internal/packstream/pack_stream.rb +1 -1
  25. data/ruby/neo4j/driver/internal/security/security_plan_impl.rb +16 -65
  26. data/ruby/neo4j/driver/internal/security_setting.rb +41 -48
  27. data/ruby/neo4j/driver/version.rb +1 -1
  28. metadata +2 -16
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 698039b3b9cd2cf99a79e5a96f23ad4be85aabe2dbf85274b01ec8bf05301658
4
- data.tar.gz: cf29ed98589d4e6aac9469d67d3e069696091612d9a0fd8eef2e3993f2ef9a4f
3
+ metadata.gz: 92d999b42ad79f180328388f8b50e610e35190b2efc0b5ad9f799773a3d5d006
4
+ data.tar.gz: 759f1058c5dcf0c12d970dec2793bd2f6a5600aecfcdeb43f63b19630f038fb2
5
5
  SHA512:
6
- metadata.gz: 3f2beecb1b73d3394f3ea6259c4664b7aa0400472edba1aafdc02a0b5932cd90e1e5ff2bf8319e6931c341b9e74a0037d4727ceffc4e29138f188fa373aee4b0
7
- data.tar.gz: 673f97b1c0eed87beea9f0c1538eb96fe34ff92fdd9b49ef82c9dc9e54b49b0197c98e578ea399023b3b1579774e474d3019527c67ed7a62b5251fdeff078f23
6
+ metadata.gz: 50d2744664faa1596e8fe964db0b083e216f58b001a4d3d7d70218752814a164d4e83ea71f5d4b4b2330432aa58d74b12875ea182bb8f99aad701a831032cc73
7
+ data.tar.gz: 5d8f9e3e8eb358d7aa494d7be74d3ee49507ff2496f346d0b5ab9defea5c92a6017e147ae51b0e128728a667ef924cdf8b7e13f69ff398a1f6f6606d24cddeef
data/README.md CHANGED
@@ -56,12 +56,23 @@ $ bin/setup
56
56
  $ rspec spec
57
57
  ```
58
58
 
59
- In case of heap space memory error (`org.neo4j.driver.exceptions.DatabaseException: Java heap space`), you should limit the dbms memory, for example:
59
+ Known errors:
60
+
61
+ 1. In case of heap space memory error (`org.neo4j.driver.exceptions.DatabaseException: Java heap space`), you should limit the dbms memory, for example:
60
62
 
61
63
  ```console
62
64
  $ neoctrl-configure servers/neo4j-enterprise-4.4.5 dbms.memory.pagecache.size=600m dbms.memory.heap.max_size=600m dbms.memory.heap.initial_size=600m dbms.directories.import= dbms.connectors.default_listen_address=::
63
65
  ```
64
66
 
67
+ 2. When using command `pip3 install --user git+https://github.com/klobuczek/boltkit@1.3#egg=boltkit`, if you have m1 mac chip, you may get error when pip3 tries to install `cryptography`. Steps to take in that case (reference https://stackoverflow.com/a/70074869/2559490)
68
+
69
+ ```console
70
+ $ pip uninstall cffi
71
+ $ python -m pip install --upgrade pip
72
+ $ pip install cffi
73
+ $ pip install cryptography
74
+ ```
75
+
65
76
  ## Contributing
66
77
 
67
78
  Suggestions, improvements, bug reports and pull requests are welcome on GitHub at https://github.com/neo4jrb/neo4j-ruby-driver.
@@ -10,7 +10,7 @@ module Neo4j
10
10
 
11
11
  attr_reader :strategy, :cert_files, :revocation_strategy
12
12
 
13
- #
13
+ # Sample config:
14
14
  # {
15
15
  # trust_strategy: {
16
16
  # strategy: :trust_custom_certificates,
@@ -62,12 +62,12 @@ module Neo4j
62
62
  max_transaction_retry_time: Internal::Retry::ExponentialBackoffRetryLogic::DEFAULT_MAX_RETRY_TIME,
63
63
  metrics_enabled: false,
64
64
  # resolver: nil # :set_address_resolver
65
- trust_strategy: TrustStrategy.trust_all_certificates,
65
+ trust_strategy: { strategy: :trust_all_certificates }
66
66
  }.freeze
67
67
 
68
68
  def initialize(**config)
69
69
  merge!(DEFAULTS).merge!(config.compact)
70
- init_security_and_trust_config(config)
70
+ init_security_and_trust_config
71
71
  end
72
72
 
73
73
  def routing_settings
@@ -77,13 +77,11 @@ module Neo4j
77
77
 
78
78
  private
79
79
 
80
- def init_security_and_trust_config(config)
81
- trust_strategy = config.key?(:trust_strategy) ? TrustStrategy.new(**config) : DEFAULTS[:trust_strategy]
82
- encryption = config.key?(:encryption) ? config[:encryption] : DEFAULTS[:encryption]
83
- customized = %i[encryption trust_strategy].any?(&config.method(:key?))
84
- merge!(
85
- security_settings: Neo4j::Driver::Internal::SecuritySetting.new(encryption, trust_strategy, customized),
86
- trust_strategy: trust_strategy
80
+ def init_security_and_trust_config
81
+ relevant = %i[encryption trust_strategy]
82
+ customized = slice(*relevant) == DEFAULTS.slice(*relevant)
83
+ merge!(security_settings: Neo4j::Driver::Internal::SecuritySetting.new(
84
+ fetch(:encryption), TrustStrategy.new(**fetch(:trust_strategy)), customized),
87
85
  )
88
86
  end
89
87
  end
@@ -8,66 +8,6 @@ module Neo4j::Driver
8
8
  auto_closable :driver, :routing_driver
9
9
  sync :driver
10
10
 
11
- GOGOBOLT = ["6060B017"].pack('H*')
12
-
13
- def handshake_concurrent(*versions)
14
- remote_port = 7687
15
- remote_addr = 'localhost'
16
- selector = NIO::Selector.new
17
- socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
18
- begin
19
- socket.connect_nonblock Socket.sockaddr_in(remote_port, remote_addr)
20
- rescue Errno::EINPROGRESS
21
- # Ruby's a-tryin' to connect us, we swear!
22
- selector.register(socket, :w)
23
- end
24
- selector.select do |monitor|
25
- case monitor.io
26
- when Socket
27
- if monitor.writable?
28
- begin
29
- socket.connect_nonblock Socket.sockaddr_in(remote_port, remote_addr)
30
- rescue Errno::EISCONN
31
- # SUCCESS! Since Ruby is crazy we discover we're successful via an exception
32
- end
33
- end
34
- end
35
- end
36
- socket.write_nonblock(GOGOBOLT)
37
- socket.write_nonblock(bolt_versions(*versions))
38
-
39
- @data = nil
40
- begin
41
- @data = socket.read_nonblock(16384)
42
- rescue IO::WaitReadable
43
- monitor = selector.register(socket, :r)
44
- monitor.value = proc do
45
- @data = socket.read_nonblock(16384)
46
- end
47
- end
48
- Concurrent::Promises.future do
49
- selector.select do |monitor|
50
- monitor.value.call
51
- end
52
- ruby_version(@data)
53
- end
54
- end
55
-
56
- class Connection < Async::Pool::Resource
57
- attr :version, true
58
- attr :io
59
-
60
- def initialize
61
- super
62
- @io = Async::IO::Endpoint.tcp('localhost', 7687).connect
63
- end
64
-
65
- def close
66
- super
67
- @io.close
68
- end
69
- end
70
-
71
11
  def driver(uri, auth_token = nil, **config)
72
12
  internal_driver(uri, auth_token, config, Internal::DriverFactory.new)
73
13
  end
@@ -16,9 +16,15 @@ module Neo4j::Driver
16
16
  end
17
17
 
18
18
  def connect(address)
19
- socket_host = (@domain_name_resolver.call(address.connection_host).first.ip_address rescue nil) || bracketless(address.connection_host)
19
+ socket_host = (@domain_name_resolver.call(address.connection_host).first.ip_address rescue nil) ||
20
+ bracketless(address.connection_host)
20
21
 
21
- channel_connected = ::Async::IO::Endpoint.tcp(socket_host, address.port).connect
22
+ endpoint = ::Async::IO::Endpoint.tcp(socket_host, address.port)
23
+ if @security_plan.requires_encryption?
24
+ endpoint = ::Async::IO::SSLEndpoint.new(endpoint, ssl_context: @security_plan.ssl_context,
25
+ hostname: address.host)
26
+ end
27
+ channel_connected = endpoint.connect
22
28
 
23
29
  # install_channel_connected_listeners(address, channel_connected, handshake_completed)
24
30
  # install_handshake_completed_listeners(handshake_completed, connection_initialized)
@@ -151,7 +151,7 @@ module Neo4j::Driver
151
151
  @auto_read_managing_handler.disable_auto_read_management
152
152
 
153
153
  # restore the default value of auto-read
154
- @channel.config.set_auto_read(true)
154
+ @channel.auto_read = true
155
155
  end
156
156
 
157
157
  @auto_read_managing_handler = new_handler
@@ -33,11 +33,11 @@ module Neo4j::Driver
33
33
  end
34
34
 
35
35
  def enable_auto_read
36
- set_auto_read(true) if open?
36
+ @channel.auto_read = true if open?
37
37
  end
38
38
 
39
39
  def disable_auto_read
40
- set_auto_read(false) if open?
40
+ @channel.auto_read = false if open?
41
41
  end
42
42
 
43
43
  def flush
@@ -69,13 +69,12 @@ module Neo4j::Driver
69
69
 
70
70
  def release
71
71
  if @status.compare_and_set(Status::OPEN, Status::RELEASED)
72
- @channel_pool.release(@channel)
72
+ handler = Handlers::ChannelReleasingResetResponseHandler.new(@channel, @channel_pool, @message_dispatcher, @log, @release)
73
+ write_reset_message_if_needed(handler, false)
74
+ # @metrics_listener.after_connection_released(Connection::ChannelAttributes.pool_id(@channel), @in_use_event)
75
+ # end
76
+ # @release_future
73
77
  end
74
- # handler = Handlers::ChannelReleasingResetResponseHandler.new(@channel, @channel_pool, @message_dispatcher, @clock, @release)
75
- # write_reset_message_if_needed(handler, false)
76
- # @metrics_listener.after_connection_released(Connection::ChannelAttributes.pool_id(@channel), @in_use_event)
77
- # end
78
- # @release_future
79
78
  end
80
79
 
81
80
  def terminate_and_release(reason)
@@ -91,15 +90,13 @@ module Neo4j::Driver
91
90
  private
92
91
 
93
92
  def write_reset_message_if_needed(reset_handler, is_session_reset)
94
- @channel.event_loop.execute do
95
- if is_session_reset && !open?
96
- reset_handler.on_success(java.util.Collections.empty_map)
97
- else
98
- # auto-read could've been disabled, re-enable it to automatically receive response for RESET
99
- set_auto_read(true)
100
- @message_dispatcher.enqueue(reset_handler)
101
- @channel.write_and_flush(Messaging::Request::ResetMessage::RESET).add_listener(-> (_future) { register_connection_read_timeout(@channel) })
102
- end
93
+ if is_session_reset && !open?
94
+ reset_handler.on_success
95
+ else
96
+ # auto-read could've been disabled, re-enable it to automatically receive response for RESET
97
+ @channel.auto_read = true
98
+ @message_dispatcher.enqueue(reset_handler)
99
+ @channel.write_and_flush(Messaging::Request::ResetMessage::RESET)#.add_listener(-> (_future) { register_connection_read_timeout(@channel) })
103
100
  end
104
101
  end
105
102
 
@@ -114,7 +111,7 @@ module Neo4j::Driver
114
111
  @message_dispatcher.enqueue(handler)
115
112
 
116
113
  if flush
117
- @channel.write_and_flush(message)#.add_listener(-> (_future) { register_connection_read_timeout(@channel) })
114
+ @channel.write_and_flush(message) #.add_listener(-> (_future) { register_connection_read_timeout(@channel) })
118
115
  else
119
116
  @channel.write(message)
120
117
  end
@@ -135,10 +132,6 @@ module Neo4j::Driver
135
132
  end
136
133
  end
137
134
 
138
- def set_auto_read(value)
139
- @channel.config.set_auto_read(value)
140
- end
141
-
142
135
  def verify_open(handler1, handler2)
143
136
  connection_status = @status.get
144
137
 
@@ -6,6 +6,7 @@ module Neo4j::Driver
6
6
  attr :stream
7
7
  attr_accessor :version, :protocol, :message_format, :message_dispatcher
8
8
  attr :attributes # should be attr
9
+ attr_accessor :auto_read
9
10
 
10
11
  def initialize(address, connector, logger)
11
12
  super()
@@ -20,6 +20,7 @@ module Neo4j::Driver
20
20
 
21
21
  begin
22
22
  channel = pool.acquire
23
+ @log.debug{"Channel #{channel.object_id} acquired"}
23
24
  rescue => error
24
25
  process_acquisition_error(pool, address, error)
25
26
  end
@@ -26,7 +26,7 @@ module Neo4j::Driver
26
26
  @routing_tables.ensure_routing_table(context).then_flat do |handler|
27
27
  acquire(context.mode, handler.routing_table).then do |connection|
28
28
  Async::Connection::RoutingConnection.new(connection,
29
- Util::Futures.join_now_or_else_throw(context.database_name_future, Async::ConnectionContext::PENDING_DATABASE_NAME_EXCEPTION_SUPPLIER),
29
+ Util::Futures.join_now_or_else_throw(context.database_name, Async::ConnectionContext::PENDING_DATABASE_NAME_EXCEPTION_SUPPLIER),
30
30
  context.mode, context.impersonated_user, handler)
31
31
  end
32
32
  end
@@ -4,7 +4,7 @@ module Neo4j::Driver
4
4
  class RoutingTableRegistryImpl
5
5
  def initialize(connection_pool, rediscovery, clock, logger, routing_table_purge_delay_ms)
6
6
  @factory = RoutingTableHandlerFactory.new(connection_pool, rediscovery, clock, logger, routing_table_purge_delay_ms)
7
- @routing_table_handlers = {}
7
+ @routing_table_handlers = Concurrent::Hash.new
8
8
  @principal_to_database_name_stage = {}
9
9
  @clock = clock
10
10
  @connection_pool = connection_pool
@@ -26,7 +26,7 @@ module Neo4j::Driver
26
26
  end
27
27
 
28
28
  def each_async(&action)
29
- internal_for_each_async(result_future, &action)
29
+ internal_for_each_async(&action)
30
30
  consume_async
31
31
  end
32
32
 
@@ -42,33 +42,25 @@ module Neo4j::Driver
42
42
 
43
43
  def pull_all_failure_async
44
44
  # runError has priority over other errors and is expected to have been reported to user by now
45
- @pull_all_handler.pull_all_failure_async.then { |error| @run_error ? nil : error }
45
+ @pull_all_handler.pull_all_failure_async.then { |error| run_error ? nil : error }
46
46
  end
47
47
 
48
- private def internal_for_each_async(result_future, &action)
49
- record_future = next_async
50
-
51
- # use async completion listener because of recursion, otherwise it is possible for
52
- # the caller thread to get StackOverflowError when result is large and buffered
53
- record_future.on_complete do |_fulfilled, record, error|
54
- if error
55
- result_future.reject(error)
56
- elsif record
57
- begin
58
- yield record
59
- rescue => action_error
60
- result_future.reject(action_error)
61
- return
62
- end
63
- internal_for_each_async(result_future, &action)
64
- else
65
- result_future.fulfill(nil)
48
+ private def internal_for_each_async
49
+ while record = next_async
50
+ begin
51
+ yield record
52
+ rescue
53
+ nil
66
54
  end
67
55
  end
68
56
  end
69
57
 
70
58
  def map_successful_run_completion_async
71
- @run_error || self
59
+ run_error || self
60
+ end
61
+
62
+ def run_error
63
+ @run_handler.error
72
64
  end
73
65
  end
74
66
  end
@@ -3,11 +3,10 @@ module Neo4j::Driver
3
3
  module Cursor
4
4
  # Used by Bolt V1, V2, V3
5
5
  class AsyncResultCursorOnlyFactory
6
- def initialize(connection, run_message, run_handler, run_future, pull_handler)
6
+ def initialize(connection, run_message, run_handler, pull_handler)
7
7
  @connection = Internal::Validator.require_non_nil!(connection)
8
8
  @run_message = Internal::Validator.require_non_nil!(run_message)
9
9
  @run_handler = Internal::Validator.require_non_nil!(run_handler)
10
- @run_future = Internal::Validator.require_non_nil!(run_future)
11
10
 
12
11
  @pull_all_handler = Internal::Validator.require_non_nil!(pull_handler)
13
12
  end
@@ -17,7 +16,7 @@ module Neo4j::Driver
17
16
  @connection.write(@run_message, @run_handler) # queues the run message, will be flushed with pull message together
18
17
  @pull_all_handler.pre_populate_records
19
18
 
20
- @run_future.handle { |_ignored, error| DisposableAsyncResultCursor.new(AsyncResultCursorImpl.new(error, @run_handler, @pull_all_handler)) }
19
+ DisposableAsyncResultCursor.new(AsyncResultCursorImpl.new(@run_handler, @pull_all_handler))
21
20
  end
22
21
 
23
22
  def rx_result
@@ -67,36 +67,35 @@ module Neo4j::Driver::Internal
67
67
 
68
68
  def create_driver(uri, security_plan, address, connection_pool, eventExecutorGroup, routing_settings, retryLogic, metricsProvider, config)
69
69
  if routing_scheme?(uri.scheme.downcase)
70
- createRoutingDriver(security_plan, address, connection_pool, eventExecutorGroup, routing_settings, retryLogic, metricsProvider, config)
70
+ create_routing_driver(security_plan, address, connection_pool, eventExecutorGroup, routing_settings, retryLogic, metricsProvider, config)
71
71
  else
72
72
  assert_no_routing_context(uri, routing_settings)
73
- createDirectDriver(security_plan, address, connection_pool, retryLogic, metricsProvider, config)
73
+ create_direct_driver(security_plan, address, connection_pool, retryLogic, metricsProvider, config)
74
74
  end
75
75
  rescue => driver_error
76
76
  # we need to close the connection pool if driver creation threw exception
77
- closeConnectionPoolAndSuppressError(connection_pool, driver_error)
78
- raise driver_error
77
+ close_connection_pool_and_suppress_error(connection_pool, driver_error)
78
+ raise
79
79
  end
80
80
 
81
- def createDirectDriver(securityPlan, address, connection_pool, retryLogic, metricsProvider, config)
81
+ def create_direct_driver(securityPlan, address, connection_pool, retryLogic, metricsProvider, config)
82
82
  connection_provider = DirectConnectionProvider.new(address, connection_pool)
83
83
  driver(:Direct, securityPlan, address, connection_provider, retryLogic, metricsProvider, config)
84
84
  end
85
85
 
86
- def createRoutingDriver(securityPlan, address, connection_pool, eventExecutorGroup, routingSettings, retryLogic, metricsProvider, config)
87
- connection_provider = createLoadBalancer(address, connection_pool, eventExecutorGroup, config, routingSettings)
86
+ def create_routing_driver(securityPlan, address, connection_pool, eventExecutorGroup, routingSettings, retryLogic, metricsProvider, config)
87
+ connection_provider = create_load_balancer(address, connection_pool, eventExecutorGroup, config, routingSettings)
88
88
  driver(:Routing, securityPlan, address, connection_provider, retryLogic, metricsProvider, config)
89
89
  end
90
90
 
91
91
  def driver(type, security_plan, address, connection_provider, retry_logic, metrics_provider, config)
92
92
  session_factory = SessionFactoryImpl.new(connection_provider, retry_logic, config)
93
93
  InternalDriver.new(security_plan, session_factory, metrics_provider, config[:logger]).tap do |driver|
94
- log = config[:logger]
95
- log.info { "#{type} driver instance #{driver.object_id} created for server address #{address}" }
94
+ config[:logger]&.info { "#{type} driver instance #{driver.object_id} created for server address #{address}" }
96
95
  end
97
96
  end
98
97
 
99
- def createLoadBalancer(address, connection_pool, eventExecutorGroup, config, routingSettings)
98
+ def create_load_balancer(address, connection_pool, eventExecutorGroup, config, routingSettings)
100
99
  load_balancing_strategy = Cluster::Loadbalancing::LeastConnectedLoadBalancingStrategy.new(connection_pool, config[:logger])
101
100
  resolver = create_resolver(config)
102
101
  Cluster::Loadbalancing::LoadBalancer.new(
@@ -110,7 +109,7 @@ module Neo4j::Driver::Internal
110
109
 
111
110
  protected
112
111
 
113
- def closeConnectionPoolAndSuppressError(connection_pool, main_error)
112
+ def close_connection_pool_and_suppress_error(connection_pool, main_error)
114
113
  connection_pool.close
115
114
  rescue => close_error
116
115
  Util::ErrorUtil.add_suppressed(main_error, close_error)
@@ -2,26 +2,27 @@ module Neo4j::Driver
2
2
  module Internal
3
3
  module Handlers
4
4
  class ChannelReleasingResetResponseHandler < ResetResponseHandler
5
- def initialize(channel, pool, message_dispatcher, clock, release_future)
5
+ def initialize(channel, pool, message_dispatcher, log, release_future)
6
6
  super(message_dispatcher, release_future)
7
7
  @channel = channel
8
8
  @pool = pool
9
- @clock = clock
9
+ @log = log
10
10
  end
11
11
 
12
- def reset_completed(completion_future, success)
12
+ def reset_completed(success)
13
13
  if success
14
14
  # update the last-used timestamp before returning the channel back to the pool
15
- Async::Connection::ChannelAttributes.set_last_used_timestamp(@channel, @clock.millis)
16
- closure_stage = Util::Futures.completed_with_null
15
+ # Async::Connection::ChannelAttributes.set_last_used_timestamp(@channel, @clock.millis)
16
+ # closure_stage = Util::Futures.completed_with_null
17
17
  else
18
18
  # close the channel before returning it back to the pool if RESET failed
19
- closure_stage = Util::Futures.as_completion_stage(@channel.close)
20
- end
21
-
22
- closure_stage.exceptionally(-> (_throwable) { nil }).then_compose(-> (_ignored) { @pool.release(@channel) }).when_complete do |_, _error|
23
- completion_future.complete(nil)
19
+ @channel.close
24
20
  end
21
+ rescue
22
+ nil
23
+ ensure
24
+ @pool.release(@channel)
25
+ @log.debug { "Channel #{@channel.object_id} released." }
25
26
  end
26
27
  end
27
28
  end
@@ -9,11 +9,11 @@ module Neo4j::Driver
9
9
  RECORD_BUFFER_HIGH_WATERMARK = ENV['record_buffer_high_watermark']&.to_i || 1000
10
10
 
11
11
  def initialize(query, run_response_handler, connection, metadata_extractor, completion_listener)
12
- @query = Util::Validator.require_non_nil!(query)
13
- @run_response_handler = Util::Validator.require_non_nil!(run_response_handler)
14
- @metadata_extractor = Util::Validator.require_non_nil!(metadata_extractor)
15
- @connection = Util::Validator.require_non_nil!(connection)
16
- @completion_listener = Util::Validator.require_non_nil!(completion_listener)
12
+ @query = Internal::Validator.require_non_nil!(query)
13
+ @run_response_handler = Internal::Validator.require_non_nil!(run_response_handler)
14
+ @metadata_extractor = Internal::Validator.require_non_nil!(metadata_extractor)
15
+ @connection = Internal::Validator.require_non_nil!(connection)
16
+ @completion_listener = Internal::Validator.require_non_nil!(completion_listener)
17
17
  @records = UNINITIALIZED_RECORDS
18
18
  end
19
19
 
@@ -212,7 +212,7 @@ module Neo4j::Driver
212
212
 
213
213
  def extract_result_summary(metadata)
214
214
  result_available_after = @run_response_handler.result_available_after
215
- @metadataExtractor.extract_summary(@query, @connection, result_available_after, metadata)
215
+ @metadata_extractor.extract_summary(@query, @connection, result_available_after, metadata)
216
216
  end
217
217
 
218
218
  def enable_auto_read
@@ -4,7 +4,6 @@ module Neo4j::Driver
4
4
  module Pulln
5
5
  class AutoPullResponseHandler < BasicPullResponseHandler
6
6
  delegate :signal, to: :@records
7
- UNINITIALIZED_RECORDS = ::Async::Queue.new
8
7
  LONG_MAX_VALUE = 2 ** 63 - 1
9
8
 
10
9
  def initialize(query, run_response_handler, connection, metadata_extractor, completion_listener, fetch_size)
@@ -20,7 +19,7 @@ module Neo4j::Driver
20
19
  @low_record_watermark = fetch_size * 0.3
21
20
  end
22
21
 
23
- @records = UNINITIALIZED_RECORDS
22
+ @records = ::Async::Queue.new
24
23
  @auto_pull_enabled = true
25
24
 
26
25
  install_record_and_summary_consumers
@@ -79,8 +78,8 @@ module Neo4j::Driver
79
78
  @summary
80
79
  end
81
80
 
82
- def list_async(map_function)
83
- pull_all_async.then_apply(-> (summary) { records_as_list(map_function) })
81
+ def list_async(&map_function)
82
+ pull_all_async.then_apply(-> (summary) { records_as_list(&map_function) })
84
83
  end
85
84
 
86
85
  def pull_all_failure_async
@@ -167,6 +166,10 @@ module Neo4j::Driver
167
166
  def completed_with_value_if_no_failure(value)
168
167
  @failure ? extract_failure : value
169
168
  end
169
+
170
+ # def request(size)
171
+ # @auto_pull_enabled ? Async { super } : super
172
+ # end
170
173
  end
171
174
  end
172
175
  end
@@ -9,7 +9,7 @@ module Neo4j::Driver
9
9
  @completion_future = completion_future
10
10
  end
11
11
 
12
- def on_success(_metadata)
12
+ def on_success(_metadata = {})
13
13
  reset_completed(true)
14
14
  end
15
15
 
@@ -3,7 +3,7 @@ module Neo4j::Driver
3
3
  module Handlers
4
4
  class RunResponseHandler
5
5
  include Spi::ResponseHandler
6
- attr_reader :query_keys, :result_available_after, :query_id
6
+ attr :query_keys, :result_available_after, :query_id, :error
7
7
 
8
8
  def initialize(metadata_extractor, connection, tx)
9
9
  @query_keys = []
@@ -26,6 +26,7 @@ module Neo4j::Driver
26
26
  elsif error.is_a?(Exceptions::ConnectionReadTimeoutException)
27
27
  connection.terminate_and_release(error.message)
28
28
  end
29
+ @error = error
29
30
  end
30
31
 
31
32
  def on_record(_fields)
@@ -10,14 +10,12 @@ module Neo4j::Driver
10
10
  @values = values.to_set
11
11
  end
12
12
 
13
- def eql?(other)
14
- values.eql?(other.values)
15
- end
16
-
17
13
  def ==(other)
18
- values == other.values
14
+ equal?(other) || self.class == other.class && values == other.values
19
15
  end
20
16
 
17
+ alias eql? ==
18
+
21
19
  def to_s
22
20
  "Bookmark{values=#{values}}"
23
21
  end
@@ -7,7 +7,7 @@ module Neo4j::Driver
7
7
  # delegate :verify_connectivity, to: :session_factory
8
8
  delegate :metrics, :metrics_enabled?, to: :metrics_provider
9
9
  auto_closable :session
10
- sync :close, :supports_multi_db?, :verify_connectivity
10
+ sync :close, :supports_multi_db?, :verify_connectivity, :session
11
11
 
12
12
  def initialize(security_plan, session_factory, metrics_provider, logger)
13
13
  @closed = Concurrent::AtomicBoolean.new(false)
@@ -10,13 +10,11 @@ module Neo4j::Driver
10
10
  @properties = properties
11
11
  end
12
12
 
13
- def eql?(other)
14
- id.eql?(other.id)
15
- end
16
-
17
13
  def ==(other)
18
- id == other.id
14
+ equal?(other) || self.class == other.class && id == other.id
19
15
  end
16
+
17
+ alias eql? ==
20
18
  end
21
19
  end
22
20
  end
@@ -58,11 +58,10 @@ module Neo4j::Driver
58
58
  end
59
59
 
60
60
  def build_result_cursor_factory(connection, query, bookmark_holder, tx, run_message, ignored)
61
- run_future = java.util.concurrent.CompletableFuture.new
62
- run_handler = Handlers::RunResponseHandler.new(run_future, METADATA_EXTRACTOR, connection, tx)
61
+ run_handler = Handlers::RunResponseHandler.new(METADATA_EXTRACTOR, connection, tx)
63
62
  pull_handler = Handlers::PullHandlers.new_bolt_v3_pull_all_handler(query, run_handler, connection, bookmark_holder, tx)
64
63
 
65
- Cursor::AsyncResultCursorOnlyFactory.new(connection, run_message, run_handler, run_future, pull_handler)
64
+ Cursor::AsyncResultCursorOnlyFactory.new(connection, run_message, run_handler, pull_handler)
66
65
  end
67
66
 
68
67
  def verify_database_name_before_transaction(database_name)
@@ -171,7 +171,7 @@ module Neo4j::Driver
171
171
  elsif size < PLUS_2_TO_THE_8
172
172
  write_byte(STRING_8).write_byte(size)
173
173
  elsif size < PLUS_2_TO_THE_16
174
- write_byte(BYTES_16).write_short(size)
174
+ write_byte(STRING_16).write_short(size)
175
175
  else
176
176
  write_byte(STRING_32).write_int(size)
177
177
  end
@@ -1,22 +1,20 @@
1
1
  module Neo4j::Driver::Internal
2
2
  module Security
3
- class SecurityPlanImpl < Struct.new(:requires_encryption, :ssl_context, :requires_hostname_verification,
3
+ class SecurityPlanImpl < Struct.new(:requires_encryption?, :ssl_context, :requires_hostname_verification?,
4
4
  :revocation_strategy)
5
5
  class << self
6
6
  def for_all_certificates(requires_hostname_verification, revocation_strategy)
7
- ssl_context = javax.net.ssl.SSLContext.get_instance('TLS')
8
- ssl_context.init(javax.net.ssl.KeyManager[0].new, [TrustAllTrustManager.new].to_java(javax.net.ssl.KeyManager), nil)
9
- new(true, ssl_context, requires_hostname_verification, revocation_strategy)
7
+ new(true, OpenSSL::SSL::SSLContext.new, requires_hostname_verification, revocation_strategy)
10
8
  end
11
9
 
12
- def for_custom_ca_signed_certificate(cert_file, requires_hostname_verification, revocation_strategy)
13
- ssl_context = config_ssl_context(cert_file, revocation_strategy)
14
- new(true, ssl_context, requires_hostname_verification, revocation_strategy)
10
+ def for_custom_ca_signed_certificates(cert_files, requires_hostname_verification, revocation_strategy)
11
+ new(true, custom_ca_signed_context(cert_files, requires_hostname_verification),
12
+ requires_hostname_verification, revocation_strategy)
15
13
  end
16
14
 
17
- def for_system_ca_signed_certificate(requires_hostname_verification, revocation_strategy)
18
- ssl_context = config_ssl_context(nil, revocation_strategy)
19
- new(true, ssl_context, requires_hostname_verification, revocation_strategy)
15
+ def for_system_ca_signed_certificates(requires_hostname_verification, revocation_strategy)
16
+ new(true, ca_signed_context(requires_hostname_verification), requires_hostname_verification,
17
+ revocation_strategy)
20
18
  end
21
19
 
22
20
  def insecure
@@ -25,68 +23,21 @@ module Neo4j::Driver::Internal
25
23
 
26
24
  private
27
25
 
28
- def configure_ssl_context(custom_cert_file, revocation_strategy)
29
- trusted_key_store = java.security.KeyStore.get_instance(java.security.KeyStore.get_default_type)
30
- trusted_key_store.load(nil, nil)
31
-
32
- if !custom_cert_file.nil?
33
- Util::CertificateTool.loadX509_cert(custom_cert_file, trusted_key_store)
34
- else
35
- load_system_certificates(trusted_key_store)
36
- end
37
-
38
- pkix_builder_parameters = java.security.cert.PKIXBuilderParameters.new(trusted_key_store, java.security.cert.X509CertSelector.new)
39
- pkix_builder_parameters.set_revocation_enabled(RevocationStrategy.requires_revocation_checking?(revocation_strategy))
40
-
41
- if RevocationStrategy.requires_revocation_checking?(revocation_strategy)
42
- java.lang.System.set_property('jdk.tls.client.enableStatusRequestExtension', true)
43
- if revocation_strategy == RevocationStrategy::VERIFY_IF_PRESENT
44
- java.security.Security.set_property('ocsp.enable', true)
45
- end
26
+ def ca_signed_context(requires_hostname_verification)
27
+ OpenSSL::SSL::SSLContext.new.tap do |context|
28
+ context.verify_mode = OpenSSL::SSL::VERIFY_PEER
29
+ context.verify_hostname = requires_hostname_verification
46
30
  end
47
-
48
- ssl_context = javax.net.ssl.SSLContext.get_instance('TLS')
49
-
50
- trust_manager_factory = javax.net.ssl.TrustManager.get_instance(javax.net.ssl.TrustManagerFactory.get_default_algorithm)
51
- trust_manager_factory.init(javax.net.ssl.CertPathTrustManagerParameters.new(pkix_builder_parameters))
52
- ssl_context.init(javax.net.ssl.KeyManager[0].new, trust_manager_factory.get_trust_managers, nil)
53
- ssl_context
54
31
  end
55
32
 
56
- def load_system_certificates(trusted_key_store)
57
- temp_factory = javax.net.ssl.TrustManagerFactory.get_instance(javax.net.ssl.TrustManagerFactory.get_default_algorithm)
58
- temp_factory.init(nil)
59
-
60
- x509_trust_manager = nil
61
- temp_factory.get_trust_managers.each do |trust_manager|
62
- if trust_manager.is_a?(javax.net.ssl.X509TrustManager)
63
- x509_trust_manager = javax.net.ssl.X509TrustManager.java_class.cast(trust_manager)
64
- break
33
+ def custom_ca_signed_context(cert_files, requires_hostname_verification)
34
+ ca_signed_context(requires_hostname_verification).tap do |context|
35
+ context.cert_store = OpenSSL::X509::Store.new.tap do |store|
36
+ cert_files.each(&store.method(:add_file))
65
37
  end
66
38
  end
67
-
68
- if x509_trust_manager.nil?
69
- raise Neo4j::Driver::Exceptions::CertificateException, 'No system certificates found'
70
- else
71
- Util::CertificateTool.load_x509_cert(x509_trust_manager.get_accepted_issuer, trusted_key_store)
72
- end
73
39
  end
74
40
  end
75
-
76
- class TrustAllTrustManager
77
- def check_client_trusted(chain, auth_type)
78
- raise Neo4j::Driver::Exceptions::CertificateException, 'All client connections to this client are forbidden.'
79
- end
80
-
81
- def check_server_trusted(chain, auth_type)
82
- end
83
-
84
- def get_accepted_issuers
85
- java.security.cert.X509Certificate[0].new
86
- end
87
- end
88
-
89
- private_constant :TrustAllTrustManager
90
41
  end
91
42
  end
92
43
  end
@@ -1,72 +1,65 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Neo4j::Driver::Internal
4
- class SecuritySetting
5
- include Scheme
3
+ module Neo4j::Driver
4
+ module Internal
5
+ class SecuritySetting
6
+ include Scheme
6
7
 
7
- attr_reader :encrypted, :trust_strategy, :customized
8
+ attr_reader :encrypted, :trust_strategy, :customized
8
9
 
9
- def initialize(encrypted, trust_strategy, customized)
10
- @encrypted = encrypted
11
- @trust_strategy = trust_strategy
12
- @customized = customized
13
- end
10
+ def initialize(encrypted, trust_strategy, customized)
11
+ @encrypted = encrypted
12
+ @trust_strategy = trust_strategy
13
+ @customized = customized
14
+ end
14
15
 
15
- def create_security_plan(uri_scheme)
16
- validate_scheme!(uri_scheme)
17
- begin
16
+ def create_security_plan(uri_scheme)
17
+ validate_scheme!(uri_scheme)
18
18
  if security_scheme?(uri_scheme)
19
19
  assert_security_settings_not_user_configured(uri_scheme)
20
20
  create_security_plan_from_scheme(uri_scheme)
21
21
  else
22
22
  create_security_plan_impl(encrypted, trust_strategy)
23
23
  end
24
- # rescue java.security.GeneralSecurityException, IOError
25
24
  rescue IOError
26
25
  raise Neo4j::Driver::Exceptions::ClientException, 'Unable to establish SSL parameters'
27
26
  end
28
- end
29
27
 
30
- def create_security_plan_from_scheme(uri_scheme)
31
- if high_trust_scheme?(uri_scheme)
32
- org.neo4j.driver.internal.security.SecurityPlanImpl.forSystemCASignedCertificates(
33
- true, org.neo4j.driver.internal.RevocationStrategy::NO_CHECKS
34
- )
35
- else
36
- org.neo4j.driver.internal.security.SecurityPlanImpl.forAllCertificates(false, org.neo4j.driver.internal.RevocationStrategy::NO_CHECKS)
28
+ def create_security_plan_from_scheme(uri_scheme)
29
+ if high_trust_scheme?(uri_scheme)
30
+ Security::SecurityPlanImpl.for_system_ca_signed_certificates(true, RevocationStrategy::NO_CHECKS)
31
+ else
32
+ Security::SecurityPlanImpl.for_all_certificates(false, RevocationStrategy::NO_CHECKS)
33
+ end
37
34
  end
38
- end
39
35
 
40
- private
36
+ private
41
37
 
42
- def assert_security_settings_not_user_configured(uri_scheme)
43
- return unless customized
44
-
45
- raise Neo4j::Driver::Exceptions::ClientException,
46
- "Scheme #{uri_scheme} is not configurable with manual encryption and trust settings"
47
- end
38
+ def assert_security_settings_not_user_configured(uri_scheme)
39
+ if customized
40
+ raise Neo4j::Driver::Exceptions::ClientException,
41
+ "Scheme #{uri_scheme} is not configurable with manual encryption and trust settings"
42
+ end
43
+ end
48
44
 
49
- def create_security_plan_impl(encrypted, trust_strategy)
50
- return Security::SecurityPlanImpl.insecure unless encrypted
45
+ def create_security_plan_impl(encrypted, trust_strategy)
46
+ return Security::SecurityPlanImpl.insecure unless encrypted
51
47
 
52
- hostname_verification_enabled = trust_strategy.hostname_verification_enabled?
53
- revocation_strategy = trust_strategy.revocation_strategy
48
+ hostname_verification_enabled = trust_strategy.hostname_verification_enabled?
49
+ revocation_strategy = trust_strategy.revocation_strategy
54
50
 
55
- case trust_strategy.strategy
56
- when Config::TrustStrategy::TRUST_CUSTOM_CA_SIGNED_CERTIFICATES
57
- return Security::SecurityPlanImpl.forCustomCASignedCertificates(
58
- trust_strategy.cert_file_to_java, hostname_verification_enabled, revocation_strategy
59
- )
60
- when Config::TrustStrategy::TRUST_SYSTEM_CA_SIGNED_CERTIFICATES
61
- return Security::SecurityPlanImpl.forSystemCASignedCertificates(
62
- hostname_verification_enabled, revocation_strategy
63
- )
64
- when Config::TrustStrategy::TRUST_ALL_CERTIFICATES
65
- return Security::SecurityPlanImpl.forAllCertificates(
66
- hostname_verification_enabled, revocation_strategy
67
- )
68
- else
69
- raise ClientException, "Unknown TLS authentication strategy: #{trust_strategy.strategy}"
51
+ case trust_strategy.strategy
52
+ when Config::TrustStrategy::TRUST_CUSTOM_CA_SIGNED_CERTIFICATES
53
+ Security::SecurityPlanImpl.for_custom_ca_signed_certificates(
54
+ trust_strategy.cert_files, hostname_verification_enabled, revocation_strategy)
55
+ when Config::TrustStrategy::TRUST_SYSTEM_CA_SIGNED_CERTIFICATES
56
+ Security::SecurityPlanImpl
57
+ .for_system_ca_signed_certificates(hostname_verification_enabled, revocation_strategy)
58
+ when Config::TrustStrategy::TRUST_ALL_CERTIFICATES
59
+ Security::SecurityPlanImpl.for_all_certificates(hostname_verification_enabled, revocation_strategy)
60
+ else
61
+ raise ClientException, "Unknown TLS authentication strategy: #{trust_strategy.strategy}"
62
+ end
70
63
  end
71
64
  end
72
65
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Neo4j
4
4
  module Driver
5
- VERSION = '4.4.0.alpha.2'
5
+ VERSION = '4.4.0.alpha.5'
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.alpha.2
4
+ version: 4.4.0.alpha.5
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-06-14 00:00:00.000000000 Z
11
+ date: 2022-06-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -136,20 +136,6 @@ dependencies:
136
136
  - - ">="
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
- - !ruby/object:Gem::Dependency
140
- name: parallel
141
- requirement: !ruby/object:Gem::Requirement
142
- requirements:
143
- - - ">="
144
- - !ruby/object:Gem::Version
145
- version: '0'
146
- type: :development
147
- prerelease: false
148
- version_requirements: !ruby/object:Gem::Requirement
149
- requirements:
150
- - - ">="
151
- - !ruby/object:Gem::Version
152
- version: '0'
153
139
  - !ruby/object:Gem::Dependency
154
140
  name: rake
155
141
  requirement: !ruby/object:Gem::Requirement