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.
- checksums.yaml +4 -4
- data/README.md +12 -1
- data/ruby/neo4j/driver/config.rb +8 -10
- data/ruby/neo4j/driver/graph_database.rb +0 -60
- data/ruby/neo4j/driver/internal/async/connection/channel_connector_impl.rb +8 -2
- data/ruby/neo4j/driver/internal/async/inbound/inbound_message_dispatcher.rb +1 -1
- data/ruby/neo4j/driver/internal/async/network_connection.rb +15 -22
- data/ruby/neo4j/driver/internal/async/pool/channel.rb +1 -0
- data/ruby/neo4j/driver/internal/async/pool/connection_pool_impl.rb +1 -0
- data/ruby/neo4j/driver/internal/cluster/loadbalancing/load_balancer.rb +1 -1
- data/ruby/neo4j/driver/internal/cluster/routing_table_registry_impl.rb +1 -1
- data/ruby/neo4j/driver/internal/cursor/async_result_cursor_impl.rb +13 -21
- data/ruby/neo4j/driver/internal/cursor/async_result_cursor_only_factory.rb +2 -3
- data/ruby/neo4j/driver/internal/driver_factory.rb +10 -11
- data/ruby/neo4j/driver/internal/handlers/channel_releasing_reset_response_handler.rb +11 -10
- data/ruby/neo4j/driver/internal/handlers/legacy_pull_all_response_handler.rb +6 -6
- data/ruby/neo4j/driver/internal/handlers/pulln/auto_pull_response_handler.rb +7 -4
- data/ruby/neo4j/driver/internal/handlers/reset_response_handler.rb +1 -1
- data/ruby/neo4j/driver/internal/handlers/run_response_handler.rb +2 -1
- data/ruby/neo4j/driver/internal/internal_bookmark.rb +3 -5
- data/ruby/neo4j/driver/internal/internal_driver.rb +1 -1
- data/ruby/neo4j/driver/internal/internal_entity.rb +3 -5
- data/ruby/neo4j/driver/internal/messaging/v3/bolt_protocol_v3.rb +2 -3
- data/ruby/neo4j/driver/internal/packstream/pack_stream.rb +1 -1
- data/ruby/neo4j/driver/internal/security/security_plan_impl.rb +16 -65
- data/ruby/neo4j/driver/internal/security_setting.rb +41 -48
- data/ruby/neo4j/driver/version.rb +1 -1
- metadata +2 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 92d999b42ad79f180328388f8b50e610e35190b2efc0b5ad9f799773a3d5d006
|
4
|
+
data.tar.gz: 759f1058c5dcf0c12d970dec2793bd2f6a5600aecfcdeb43f63b19630f038fb2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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.
|
data/ruby/neo4j/driver/config.rb
CHANGED
@@ -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:
|
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
|
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
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
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) ||
|
19
|
+
socket_host = (@domain_name_resolver.call(address.connection_host).first.ip_address rescue nil) ||
|
20
|
+
bracketless(address.connection_host)
|
20
21
|
|
21
|
-
|
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.
|
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
|
-
|
36
|
+
@channel.auto_read = true if open?
|
37
37
|
end
|
38
38
|
|
39
39
|
def disable_auto_read
|
40
|
-
|
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
|
-
|
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
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
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
|
|
@@ -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.
|
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(
|
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|
|
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
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
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
|
-
|
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,
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
78
|
-
raise
|
77
|
+
close_connection_pool_and_suppress_error(connection_pool, driver_error)
|
78
|
+
raise
|
79
79
|
end
|
80
80
|
|
81
|
-
def
|
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
|
87
|
-
connection_provider =
|
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
|
-
|
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
|
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
|
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,
|
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
|
-
@
|
9
|
+
@log = log
|
10
10
|
end
|
11
11
|
|
12
|
-
def reset_completed(
|
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
|
-
|
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 =
|
13
|
-
@run_response_handler =
|
14
|
-
@metadata_extractor =
|
15
|
-
@connection =
|
16
|
-
@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
|
-
@
|
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 =
|
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
|
@@ -3,7 +3,7 @@ module Neo4j::Driver
|
|
3
3
|
module Handlers
|
4
4
|
class RunResponseHandler
|
5
5
|
include Spi::ResponseHandler
|
6
|
-
|
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
|
-
|
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,
|
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(
|
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
|
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
|
-
|
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
|
13
|
-
|
14
|
-
|
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
|
18
|
-
|
19
|
-
|
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
|
29
|
-
|
30
|
-
|
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
|
57
|
-
|
58
|
-
|
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
|
4
|
-
|
5
|
-
|
3
|
+
module Neo4j::Driver
|
4
|
+
module Internal
|
5
|
+
class SecuritySetting
|
6
|
+
include Scheme
|
6
7
|
|
7
|
-
|
8
|
+
attr_reader :encrypted, :trust_strategy, :customized
|
8
9
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
10
|
+
def initialize(encrypted, trust_strategy, customized)
|
11
|
+
@encrypted = encrypted
|
12
|
+
@trust_strategy = trust_strategy
|
13
|
+
@customized = customized
|
14
|
+
end
|
14
15
|
|
15
|
-
|
16
|
-
|
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
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
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
|
-
|
36
|
+
private
|
41
37
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
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
|
-
|
50
|
-
|
45
|
+
def create_security_plan_impl(encrypted, trust_strategy)
|
46
|
+
return Security::SecurityPlanImpl.insecure unless encrypted
|
51
47
|
|
52
|
-
|
53
|
-
|
48
|
+
hostname_verification_enabled = trust_strategy.hostname_verification_enabled?
|
49
|
+
revocation_strategy = trust_strategy.revocation_strategy
|
54
50
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
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
|
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.
|
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-
|
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
|