neo4j-ruby-driver 4.4.0.alpha.6 → 4.4.0.alpha.7
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/lib/neo4j/driver/exceptions/protocol_exception.rb +2 -2
- data/lib/neo4j/driver/internal/bolt_server_address.rb +6 -6
- data/lib/neo4j/driver/types/time.rb +4 -2
- data/ruby/neo4j/driver/internal/async/network_session.rb +4 -3
- data/ruby/neo4j/driver/internal/async/pool/{netty_channel_tracker.rb → channel_tracker.rb} +6 -8
- data/ruby/neo4j/driver/internal/async/pool/connection_pool_impl.rb +3 -3
- data/ruby/neo4j/driver/internal/cluster/cluster_composition.rb +10 -20
- data/ruby/neo4j/driver/internal/cluster/cluster_composition_lookup_result.rb +2 -2
- data/ruby/neo4j/driver/internal/cluster/cluster_routing_table.rb +37 -54
- data/ruby/neo4j/driver/internal/cluster/identity_resolver.rb +1 -4
- data/ruby/neo4j/driver/internal/cluster/loadbalancing/least_connected_load_balancing_strategy.rb +6 -6
- data/ruby/neo4j/driver/internal/cluster/loadbalancing/load_balancer.rb +44 -80
- data/ruby/neo4j/driver/internal/cluster/multi_databases_routing_procedure_runner.rb +6 -9
- data/ruby/neo4j/driver/internal/cluster/rediscovery_impl.rb +65 -155
- data/ruby/neo4j/driver/internal/cluster/route_message_routing_procedure_runner.rb +2 -2
- data/ruby/neo4j/driver/internal/cluster/routing_procedure_cluster_composition_provider.rb +8 -12
- data/ruby/neo4j/driver/internal/cluster/routing_procedure_response.rb +19 -3
- data/ruby/neo4j/driver/internal/cluster/routing_table_handler_impl.rb +46 -67
- data/ruby/neo4j/driver/internal/cluster/routing_table_registry_impl.rb +42 -61
- data/ruby/neo4j/driver/internal/cluster/single_database_routing_procedure_runner.rb +8 -10
- data/ruby/neo4j/driver/internal/cursor/async_result_cursor_impl.rb +2 -1
- data/ruby/neo4j/driver/internal/cursor/disposable_async_result_cursor.rb +11 -14
- data/ruby/neo4j/driver/internal/database_name_util.rb +3 -3
- data/ruby/neo4j/driver/internal/default_bookmark_holder.rb +1 -7
- data/ruby/neo4j/driver/internal/direct_connection_provider.rb +1 -1
- data/ruby/neo4j/driver/internal/driver_factory.rb +4 -4
- data/ruby/neo4j/driver/internal/handlers/legacy_pull_all_response_handler.rb +34 -24
- data/ruby/neo4j/driver/internal/impersonation_util.rb +2 -2
- data/ruby/neo4j/driver/internal/internal_bookmark.rb +1 -1
- data/ruby/neo4j/driver/internal/internal_database_name.rb +3 -5
- data/ruby/neo4j/driver/internal/messaging/bolt_protocol_version.rb +3 -1
- data/ruby/neo4j/driver/internal/messaging/encode/route_message_encoder.rb +8 -2
- data/ruby/neo4j/driver/internal/messaging/encode/route_v44_message_encoder.rb +8 -13
- data/ruby/neo4j/driver/internal/messaging/request/begin_message.rb +2 -3
- data/ruby/neo4j/driver/internal/messaging/request/multi_database_util.rb +2 -2
- data/ruby/neo4j/driver/internal/messaging/request/route_message.rb +5 -10
- data/ruby/neo4j/driver/internal/messaging/request/run_with_metadata_message.rb +5 -3
- data/ruby/neo4j/driver/internal/messaging/request/transaction_metadata_builder.rb +2 -2
- data/ruby/neo4j/driver/internal/messaging/v3/bolt_protocol_v3.rb +1 -1
- data/ruby/neo4j/driver/internal/messaging/v44/message_writer_v44.rb +1 -1
- data/ruby/neo4j/driver/internal/read_only_bookmark_holder.rb +13 -0
- data/ruby/neo4j/driver/internal/resolved_bolt_server_address.rb +35 -0
- data/ruby/neo4j/driver/internal/security/security_plan_impl.rb +14 -9
- data/ruby/neo4j/driver/internal/util/error_util.rb +1 -1
- data/ruby/neo4j/driver/net/{server_address1.rb → server_address.rb} +2 -2
- data/ruby/neo4j/driver/query.rb +1 -1
- data/ruby/neo4j/driver/transaction_config.rb +5 -1
- data/ruby/neo4j/driver/values.rb +3 -3
- data/ruby/neo4j/driver/version.rb +1 -1
- metadata +6 -5
- data/ruby/neo4j/driver/internal/database_name.rb +0 -12
@@ -2,78 +2,57 @@ module Neo4j::Driver
|
|
2
2
|
module Internal
|
3
3
|
module Cluster
|
4
4
|
class RoutingTableRegistryImpl
|
5
|
-
def initialize(connection_pool, rediscovery, clock, logger,
|
6
|
-
@factory = RoutingTableHandlerFactory.new(connection_pool, rediscovery, clock, logger,
|
7
|
-
@routing_table_handlers = Concurrent::
|
8
|
-
@
|
5
|
+
def initialize(connection_pool, rediscovery, clock, logger, routing_table_purge_delay)
|
6
|
+
@factory = RoutingTableHandlerFactory.new(connection_pool, rediscovery, clock, logger, routing_table_purge_delay)
|
7
|
+
@routing_table_handlers = Concurrent::Map.new
|
8
|
+
@principal_to_database_name = {}
|
9
9
|
@clock = clock
|
10
10
|
@connection_pool = connection_pool
|
11
11
|
@rediscovery = rediscovery
|
12
12
|
@log = logger
|
13
|
+
@mutex = Mutex.new
|
13
14
|
end
|
14
15
|
|
15
16
|
def ensure_routing_table(context)
|
16
|
-
ensure_database_name_is_completed(context)
|
17
|
-
|
18
|
-
|
19
|
-
handler.ensure_routing_table(completed_context).then_apply(-> (_ignored) { handler })
|
20
|
-
end
|
17
|
+
ctx_and_handler = ensure_database_name_is_completed(context)
|
18
|
+
(ctx_and_handler.handler || get_or_create(context.database_name))
|
19
|
+
.tap { |handler| handler.ensure_routing_table(ctx_and_handler.context) }
|
21
20
|
end
|
22
21
|
|
23
22
|
private def ensure_database_name_is_completed(context)
|
24
|
-
|
23
|
+
context_database_name = context.database_name
|
24
|
+
|
25
|
+
return ConnectionContextAndHandler.new(context, nil) if context_database_name
|
26
|
+
@mutex.synchronize do
|
27
|
+
return ConnectionContextAndHandler.new(context, nil) if context_database_name
|
25
28
|
|
26
|
-
if context_database_name_future.done?
|
27
|
-
context_and_handler_stage = java.util.concurrent.CompletableFuture.completed_future(ConnectionContextAndHandler.new(context, nil))
|
28
|
-
else
|
29
29
|
impersonated_user = context.impersonated_user
|
30
30
|
principal = Principal.new(impersonated_user)
|
31
|
-
|
32
|
-
handler_ref =
|
33
|
-
|
34
|
-
if database_name_stage.nil?
|
35
|
-
database_name_future = java.util.concurrent.CompletableFuture.new
|
36
|
-
@principal_to_database_name_stage[principal] = database_name_future
|
37
|
-
database_name_stage = database_name_future
|
38
|
-
|
39
|
-
routing_table = ClusterRoutingTable.new(DatabaseNameUtil::DEFAULT_DATABASE, @clock)
|
40
|
-
|
41
|
-
@rediscovery.lookup_cluster_composition(routing_table, @connection_pool, context.rediscovery_bookmark, impersonated_user).then_compose do |composition_lookup_result|
|
42
|
-
database_name = DatabaseNameUtil.database(composition_lookup_result.cluster_composition.database_name)
|
43
|
-
handler = get_or_create(database_name)
|
44
|
-
handler_ref.set(handler)
|
45
|
-
handler.update_routing_table(composition_lookup_result).then_apply(-> (_ignored) { database_name })
|
46
|
-
end.when_complete do |database_name, _throwable|
|
47
|
-
@principal_to_database_name_stage.delete(principal)
|
48
|
-
end.when_complete do |database_name, throwable|
|
49
|
-
if throwable.nil?
|
50
|
-
database_name_future.complete(database_name)
|
51
|
-
else
|
52
|
-
database_name_future.complete_exceptionally(throwable)
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
31
|
+
database_name = @principal_to_database_name[principal]
|
32
|
+
handler_ref = Concurrent::AtomicReference.new
|
56
33
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
34
|
+
if database_name.nil?
|
35
|
+
@principal_to_database_name[principal] = database_name
|
36
|
+
|
37
|
+
routing_table = ClusterRoutingTable.new(DatabaseNameUtil.default_database, @clock)
|
38
|
+
|
39
|
+
composition_lookup_result = @rediscovery.lookup_cluster_composition(routing_table, @connection_pool, context.rediscovery_bookmark, impersonated_user)
|
40
|
+
database_name = DatabaseNameUtil.database(composition_lookup_result.cluster_composition.database_name)
|
41
|
+
handler = get_or_create(database_name)
|
42
|
+
handler_ref.set(handler)
|
43
|
+
handler.update_routing_table(composition_lookup_result)
|
44
|
+
@principal_to_database_name.delete(principal)
|
61
45
|
end
|
62
|
-
end
|
63
46
|
|
64
|
-
|
47
|
+
context.database_name = database_name
|
48
|
+
ConnectionContextAndHandler.new(context, handler_ref.get)
|
49
|
+
end
|
65
50
|
end
|
66
51
|
|
67
52
|
def all_servers
|
68
53
|
# obviously we just had a snapshot of all servers in all routing tables
|
69
54
|
# after we read it, the set could already be changed.
|
70
|
-
servers
|
71
|
-
|
72
|
-
@routing_table_handlers.values.each do |table_handler|
|
73
|
-
servers << table_handler.servers
|
74
|
-
end
|
75
|
-
|
76
|
-
servers
|
55
|
+
@routing_table_handlers.values.map(&:servers).reduce(&:+)
|
77
56
|
end
|
78
57
|
|
79
58
|
def remove(database_name)
|
@@ -90,17 +69,19 @@ module Neo4j::Driver
|
|
90
69
|
end
|
91
70
|
end
|
92
71
|
|
93
|
-
def
|
94
|
-
|
72
|
+
def routing_table_handler(database_name)
|
73
|
+
database_name = DatabaseNameUtil.database(database_name) unless database_name.is_a?(InternalDatabaseName)
|
74
|
+
@routing_table_handlers[database_name]
|
95
75
|
end
|
96
76
|
|
97
|
-
|
98
|
-
|
99
|
-
end
|
77
|
+
# For tests
|
78
|
+
delegate :key?, to: :@routing_table_handlers
|
100
79
|
|
101
80
|
def get_or_create(database_name)
|
102
|
-
@routing_table_handlers.compute_if_absent(database_name) do
|
103
|
-
|
81
|
+
@routing_table_handlers.compute_if_absent(database_name) do
|
82
|
+
# TODO: Verify if applies
|
83
|
+
# Note: Atomic methods taking a block do not allow the self instance to be used within the block. Doing so will cause a deadlock.
|
84
|
+
handler = @factory.new_instance(database_name, self)
|
104
85
|
@log.debug("Routing table handler for database '#{database_name.description}' is added.")
|
105
86
|
handler
|
106
87
|
end
|
@@ -109,17 +90,17 @@ module Neo4j::Driver
|
|
109
90
|
private
|
110
91
|
|
111
92
|
class RoutingTableHandlerFactory
|
112
|
-
def initialize(connection_pool, rediscovery, clock, logger,
|
93
|
+
def initialize(connection_pool, rediscovery, clock, logger, routing_table_purge_delay)
|
113
94
|
@connection_pool = connection_pool
|
114
95
|
@rediscovery = rediscovery
|
115
96
|
@clock = clock
|
116
97
|
@logger = logger
|
117
|
-
@
|
98
|
+
@routing_table_purge_delay = routing_table_purge_delay
|
118
99
|
end
|
119
100
|
|
120
101
|
def new_instance(database_name, all_tables)
|
121
102
|
routing_table = ClusterRoutingTable.new(database_name, @clock)
|
122
|
-
RoutingTableHandlerImpl.new(routing_table, @rediscovery, @connection_pool, all_tables, @logger, @
|
103
|
+
RoutingTableHandlerImpl.new(routing_table, @rediscovery, @connection_pool, all_tables, @logger, @routing_table_purge_delay)
|
123
104
|
end
|
124
105
|
end
|
125
106
|
|
@@ -5,7 +5,7 @@ module Neo4j::Driver
|
|
5
5
|
# This implementation of the {@link RoutingProcedureRunner} works with single database versions of Neo4j calling
|
6
6
|
# the procedure `dbms.cluster.routing.getRoutingTable`
|
7
7
|
class SingleDatabaseRoutingProcedureRunner
|
8
|
-
ROUTING_CONTEXT =
|
8
|
+
ROUTING_CONTEXT = :context
|
9
9
|
GET_ROUTING_TABLE = "CALL dbms.cluster.routing.getRoutingTable($#{ROUTING_CONTEXT})"
|
10
10
|
|
11
11
|
def initialize(context)
|
@@ -16,17 +16,15 @@ module Neo4j::Driver
|
|
16
16
|
delegate = connection(connection)
|
17
17
|
procedure = procedure_query(connection.server_version, database_name)
|
18
18
|
bookmark_holder = bookmark_holder(bookmark)
|
19
|
-
run_procedure(delegate, procedure, bookmark_holder)
|
20
|
-
|
21
|
-
|
22
|
-
end
|
23
|
-
end
|
19
|
+
records = run_procedure(delegate, procedure, bookmark_holder)
|
20
|
+
release_connection(delegate)
|
21
|
+
process_procedure_response(procedure, records, error)
|
24
22
|
end
|
25
23
|
|
26
24
|
private
|
27
25
|
|
28
26
|
def connection(connection)
|
29
|
-
Async::Connection::DirectConnection.new(connection, default_database, AccessMode::WRITE, nil)
|
27
|
+
Async::Connection::DirectConnection.new(connection, DatabaseNameUtil.default_database, AccessMode::WRITE, nil)
|
30
28
|
end
|
31
29
|
|
32
30
|
def procedure_query(server_version, database_name)
|
@@ -45,16 +43,16 @@ module Neo4j::Driver
|
|
45
43
|
connection.protocol
|
46
44
|
.run_in_auto_commit_transaction(connection, procedure, bookmark_holder, TransactionConfig.empty,
|
47
45
|
Handlers::Pulln::FetchSizeUtil::UNLIMITED_FETCH_SIZE)
|
48
|
-
.async_result.
|
46
|
+
.async_result.to_a
|
49
47
|
end
|
50
48
|
|
51
|
-
def release_connection(connection
|
49
|
+
def release_connection(connection)
|
52
50
|
# It is not strictly required to release connection after routing procedure invocation because it'll
|
53
51
|
# be released by the PULL_ALL response handler after result is fully fetched. Such release will happen
|
54
52
|
# in background. However, releasing it early as part of whole chain makes it easier to reason about
|
55
53
|
# rediscovery in stub server tests. Some of them assume connections to instances not present in new
|
56
54
|
# routing table will be closed immediately.
|
57
|
-
connection.release
|
55
|
+
connection.release
|
58
56
|
end
|
59
57
|
|
60
58
|
def process_procedure_response(procedure, records, error)
|
@@ -2,6 +2,7 @@ module Neo4j::Driver
|
|
2
2
|
module Internal
|
3
3
|
module Cursor
|
4
4
|
class AsyncResultCursorImpl
|
5
|
+
include Enumerable
|
5
6
|
delegate :consume_async, :next_async, :peek_async, to: :@pull_all_handler
|
6
7
|
|
7
8
|
def initialize(run_handler, pull_all_handler)
|
@@ -25,7 +26,7 @@ module Neo4j::Driver
|
|
25
26
|
first_record
|
26
27
|
end
|
27
28
|
|
28
|
-
def
|
29
|
+
def each(&action)
|
29
30
|
internal_for_each_async(&action)
|
30
31
|
consume_async
|
31
32
|
end
|
@@ -2,6 +2,7 @@ module Neo4j::Driver
|
|
2
2
|
module Internal
|
3
3
|
module Cursor
|
4
4
|
class DisposableAsyncResultCursor
|
5
|
+
include Enumerable
|
5
6
|
delegate :keys, :pull_all_failure_async, to: :@delegate
|
6
7
|
|
7
8
|
def initialize(delegate)
|
@@ -14,25 +15,23 @@ module Neo4j::Driver
|
|
14
15
|
end
|
15
16
|
|
16
17
|
def next_async
|
17
|
-
assert_not_disposed
|
18
|
+
assert_not_disposed
|
19
|
+
@delegate.next_async
|
18
20
|
end
|
19
21
|
|
20
22
|
def peek_async
|
21
|
-
assert_not_disposed
|
23
|
+
assert_not_disposed
|
24
|
+
@delegate.peek_async
|
22
25
|
end
|
23
26
|
|
24
27
|
def single_async
|
25
|
-
assert_not_disposed
|
28
|
+
assert_not_disposed
|
29
|
+
@delegate.single_async
|
26
30
|
end
|
27
31
|
|
28
|
-
def
|
29
|
-
assert_not_disposed
|
30
|
-
|
31
|
-
|
32
|
-
def list_async(map_function = nil)
|
33
|
-
return assert_not_disposed.then_compose(-> (_ignored) { @delegate.list_async(map_function) }) if map_function.present?
|
34
|
-
|
35
|
-
assert_not_disposed.then_compose(-> (_ignored) { @delegate.list_async })
|
32
|
+
def each(&action)
|
33
|
+
assert_not_disposed
|
34
|
+
@delegate.each(&action)
|
36
35
|
end
|
37
36
|
|
38
37
|
def discard_all_failure_async
|
@@ -41,9 +40,7 @@ module Neo4j::Driver
|
|
41
40
|
end
|
42
41
|
|
43
42
|
private def assert_not_disposed
|
44
|
-
|
45
|
-
|
46
|
-
Util::Futures.completed_with_null
|
43
|
+
raise Neo4j::Driver::Internal::Util.new_result_consumed_error if @disposed
|
47
44
|
end
|
48
45
|
|
49
46
|
def disposed?
|
@@ -6,8 +6,8 @@ module Neo4j::Driver
|
|
6
6
|
|
7
7
|
private
|
8
8
|
|
9
|
-
DEFAULT_DATABASE =
|
10
|
-
SYSTEM_DATABASE = InternalDatabaseName.new(SYSTEM_DATABASE_NAME)
|
9
|
+
DEFAULT_DATABASE = InternalDatabaseName.new(description: '<default database>')
|
10
|
+
SYSTEM_DATABASE = InternalDatabaseName.new(database_name: SYSTEM_DATABASE_NAME)
|
11
11
|
|
12
12
|
public
|
13
13
|
|
@@ -27,7 +27,7 @@ module Neo4j::Driver
|
|
27
27
|
when SYSTEM_DATABASE_NAME
|
28
28
|
system_database
|
29
29
|
else
|
30
|
-
InternalDatabaseName.new(name)
|
30
|
+
InternalDatabaseName.new(database_name: name)
|
31
31
|
end
|
32
32
|
end
|
33
33
|
end
|
@@ -1,12 +1,6 @@
|
|
1
1
|
module Neo4j::Driver
|
2
2
|
module Internal
|
3
|
-
class DefaultBookmarkHolder
|
4
|
-
attr_reader :bookmark
|
5
|
-
|
6
|
-
def initialize(bookmark = InternalBookmark.empty)
|
7
|
-
@bookmark = bookmark
|
8
|
-
end
|
9
|
-
|
3
|
+
class DefaultBookmarkHolder < ReadOnlyBookmarkHolder
|
10
4
|
def bookmark=(bookmark)
|
11
5
|
@bookmark = bookmark if bookmark.present?
|
12
6
|
end
|
@@ -83,8 +83,8 @@ module Neo4j::Driver::Internal
|
|
83
83
|
driver(:Direct, securityPlan, address, connection_provider, retryLogic, metricsProvider, config)
|
84
84
|
end
|
85
85
|
|
86
|
-
def create_routing_driver(securityPlan, address, connection_pool, eventExecutorGroup,
|
87
|
-
connection_provider = create_load_balancer(address, connection_pool, eventExecutorGroup, config,
|
86
|
+
def create_routing_driver(securityPlan, address, connection_pool, eventExecutorGroup, routing_settings, retryLogic, metricsProvider, config)
|
87
|
+
connection_provider = create_load_balancer(address, connection_pool, eventExecutorGroup, config, routing_settings)
|
88
88
|
driver(:Routing, securityPlan, address, connection_provider, retryLogic, metricsProvider, config)
|
89
89
|
end
|
90
90
|
|
@@ -95,11 +95,11 @@ module Neo4j::Driver::Internal
|
|
95
95
|
end
|
96
96
|
end
|
97
97
|
|
98
|
-
def create_load_balancer(address, connection_pool, eventExecutorGroup, config,
|
98
|
+
def create_load_balancer(address, connection_pool, eventExecutorGroup, config, routing_settings)
|
99
99
|
load_balancing_strategy = Cluster::Loadbalancing::LeastConnectedLoadBalancingStrategy.new(connection_pool, config[:logger])
|
100
100
|
resolver = create_resolver(config)
|
101
101
|
Cluster::Loadbalancing::LoadBalancer.new(
|
102
|
-
address,
|
102
|
+
address, routing_settings, connection_pool, eventExecutorGroup,
|
103
103
|
config[:logger], load_balancing_strategy, resolver, &method(:domain_name_resolver))
|
104
104
|
end
|
105
105
|
|
@@ -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
|
-
UNINITIALIZED_RECORDS = []
|
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
|
|
@@ -14,7 +13,7 @@ module Neo4j::Driver
|
|
14
13
|
@metadata_extractor = Internal::Validator.require_non_nil!(metadata_extractor)
|
15
14
|
@connection = Internal::Validator.require_non_nil!(connection)
|
16
15
|
@completion_listener = Internal::Validator.require_non_nil!(completion_listener)
|
17
|
-
@records =
|
16
|
+
@records = ::Async::Queue.new
|
18
17
|
end
|
19
18
|
|
20
19
|
def can_manage_auto_read?
|
@@ -39,7 +38,7 @@ module Neo4j::Driver
|
|
39
38
|
|
40
39
|
failed_record_future = fail_record_future(error)
|
41
40
|
|
42
|
-
if
|
41
|
+
if failed_record_future
|
43
42
|
# error propagated through the record future
|
44
43
|
complete_failure_future(nil)
|
45
44
|
else
|
@@ -54,7 +53,7 @@ module Neo4j::Driver
|
|
54
53
|
if @ignore_records
|
55
54
|
complete_record_future(nil)
|
56
55
|
else
|
57
|
-
record = InternalRecord.new(run_response_handler.query_keys, fields)
|
56
|
+
record = InternalRecord.new(@run_response_handler.query_keys, fields)
|
58
57
|
enqueue_record(record)
|
59
58
|
complete_record_future(record)
|
60
59
|
end
|
@@ -65,36 +64,46 @@ module Neo4j::Driver
|
|
65
64
|
end
|
66
65
|
|
67
66
|
def peek_async
|
68
|
-
|
67
|
+
while @records.empty? && !(@ignore_records || @finished)
|
68
|
+
@records.wait
|
69
|
+
end
|
70
|
+
@records.items.first
|
69
71
|
|
70
|
-
if record.nil?
|
71
|
-
|
72
|
+
# if record.nil?
|
73
|
+
# return Util::Futures.failed_future(extract_failure) unless @failure.nil?
|
72
74
|
|
73
|
-
|
75
|
+
# return Util::Futures.completed_with_null if @ignore_records || @finished
|
74
76
|
|
75
|
-
|
77
|
+
# @record_future = java.util.concurrent.CompletableFuture.new if @record_future.nil?
|
76
78
|
|
77
|
-
|
78
|
-
else
|
79
|
-
|
80
|
-
|
79
|
+
# @record_future
|
80
|
+
# else
|
81
|
+
# # java.util.concurrent.CompletableFuture.completed_future(record)
|
82
|
+
# record
|
83
|
+
# end
|
81
84
|
end
|
82
85
|
|
83
86
|
def next_async
|
84
|
-
|
87
|
+
dequeue_record if peek_async
|
85
88
|
end
|
86
89
|
|
87
90
|
def consume_async
|
88
91
|
@ignore_records = true
|
89
|
-
@records.clear
|
90
|
-
|
91
|
-
pull_all_failure_async.then_apply do |error|
|
92
|
-
unless error.nil?
|
93
|
-
raise Util::Futures.as_completion_exception, error
|
94
|
-
end
|
92
|
+
@records.items.clear
|
95
93
|
|
94
|
+
if pull_all_failure_async.nil?
|
96
95
|
@summary
|
96
|
+
else
|
97
|
+
raise Util::Futures.as_completion_exception, pull_all_failure_async
|
97
98
|
end
|
99
|
+
|
100
|
+
# pull_all_failure_async do |error|
|
101
|
+
# unless error.nil?
|
102
|
+
# raise Util::Futures.as_completion_exception, error
|
103
|
+
# end
|
104
|
+
|
105
|
+
# @summary
|
106
|
+
# end
|
98
107
|
end
|
99
108
|
|
100
109
|
def list_async(map_function)
|
@@ -115,7 +124,8 @@ module Neo4j::Driver
|
|
115
124
|
if !@failure.nil?
|
116
125
|
return java.util.concurrent.CompletableFuture.completed_future(extract_failure)
|
117
126
|
elsif @finished
|
118
|
-
return
|
127
|
+
return nil
|
128
|
+
# return Util::Futures.completed_with_null
|
119
129
|
else
|
120
130
|
if @failure_future.nil?
|
121
131
|
# neither SUCCESS nor FAILURE message has arrived, register future to be notified when it arrives
|
@@ -139,7 +149,7 @@ module Neo4j::Driver
|
|
139
149
|
# when failure is requested we have to buffer all remaining records and then return the error
|
140
150
|
# do not disable auto-read in this case, otherwise records will not be consumed and trailing
|
141
151
|
# SUCCESS or FAILURE message will not arrive as well, so callers will get stuck waiting for the error
|
142
|
-
if !should_buffer_all_records && records.size > RECORD_BUFFER_HIGH_WATERMARK
|
152
|
+
if !should_buffer_all_records && @records.size > RECORD_BUFFER_HIGH_WATERMARK
|
143
153
|
# more than high watermark records are already queued, tell connection to stop auto-reading from network
|
144
154
|
# this is needed to deal with slow consumers, we do not want to buffer all records in memory if they are
|
145
155
|
# fetched from network faster than consumed
|
@@ -148,7 +158,7 @@ module Neo4j::Driver
|
|
148
158
|
end
|
149
159
|
|
150
160
|
def dequeue_record
|
151
|
-
record = @records.
|
161
|
+
record = @records.dequeue
|
152
162
|
|
153
163
|
if @records.size < RECORD_BUFFER_LOW_WATERMARK
|
154
164
|
# less than low watermark records are now available in the buffer, tell connection to pre-fetch more
|
@@ -170,7 +180,7 @@ module Neo4j::Driver
|
|
170
180
|
result << map_function.apply(record)
|
171
181
|
end
|
172
182
|
|
173
|
-
@records.clear
|
183
|
+
@records.items.clear
|
174
184
|
result
|
175
185
|
end
|
176
186
|
|
@@ -14,8 +14,8 @@ module Neo4j::Driver
|
|
14
14
|
private
|
15
15
|
|
16
16
|
def self.supports_impersonation?(connection)
|
17
|
-
connection.server_version
|
18
|
-
|
17
|
+
connection.server_version >= Util::ServerVersion::V4_4_0 &&
|
18
|
+
connection.protocol.version >= Messaging::V44::BoltProtocolV44::VERSION
|
19
19
|
end
|
20
20
|
end
|
21
21
|
end
|
@@ -2,13 +2,13 @@ module Neo4j::Driver
|
|
2
2
|
module Internal
|
3
3
|
class InternalBookmark
|
4
4
|
include Bookmark
|
5
|
-
EMPTY = new
|
6
5
|
attr :values
|
7
6
|
delegate :hash, :empty?, to: :values
|
8
7
|
|
9
8
|
private def initialize(*values)
|
10
9
|
@values = values.to_set
|
11
10
|
end
|
11
|
+
EMPTY = new.freeze
|
12
12
|
|
13
13
|
def ==(other)
|
14
14
|
equal?(other) || self.class == other.class && values == other.values
|
@@ -1,10 +1,8 @@
|
|
1
1
|
module Neo4j::Driver
|
2
2
|
module Internal
|
3
|
-
class InternalDatabaseName < Struct.new(:database_name)
|
4
|
-
|
5
|
-
|
6
|
-
def initialize(database_name)
|
7
|
-
super(Validator.require_non_nil!(database_name))
|
3
|
+
class InternalDatabaseName < Struct.new(:database_name, :description)
|
4
|
+
def initialize(database_name: nil, description: database_name)
|
5
|
+
super(database_name, description)
|
8
6
|
end
|
9
7
|
end
|
10
8
|
end
|
@@ -2,10 +2,12 @@ module Neo4j::Driver
|
|
2
2
|
module Internal
|
3
3
|
module Messaging
|
4
4
|
class BoltProtocolVersion < Struct.new(:major_version, :minor_version)
|
5
|
+
include Comparable
|
6
|
+
|
5
7
|
def self.from_raw_bytes(raw_version)
|
6
8
|
major = raw_version & 0x000000FF
|
7
9
|
minor = (raw_version >> 8) & 0x000000FF
|
8
|
-
new(major,minor)
|
10
|
+
new(major, minor)
|
9
11
|
end
|
10
12
|
|
11
13
|
def to_int
|
@@ -8,8 +8,14 @@ module Neo4j::Driver
|
|
8
8
|
Util::Preconditions.check_argument(message, Request::RouteMessage)
|
9
9
|
packer.pack_struct_header(3, message.signature)
|
10
10
|
packer.pack(message.routing_context)
|
11
|
-
packer.pack(message.bookmark
|
12
|
-
packer.pack(message
|
11
|
+
packer.pack(message.bookmark&.values || [])
|
12
|
+
packer.pack(option(message))
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def option(message)
|
18
|
+
message.database_name
|
13
19
|
end
|
14
20
|
end
|
15
21
|
end
|
@@ -3,22 +3,17 @@ module Neo4j::Driver
|
|
3
3
|
module Messaging
|
4
4
|
module Encode
|
5
5
|
# Encodes the ROUTE message to the stream
|
6
|
-
class RouteV44MessageEncoder
|
7
|
-
|
8
|
-
Util::Preconditions.check_argument(message, Request::RouteMessage)
|
9
|
-
packer.pack_struct_header(3, message.signature)
|
10
|
-
packer.pack(message.routing_context)
|
11
|
-
packer.pack(message.bookmark.present? ? Values.value(message.bookmark.values) : Values.value(java.util.Collections.empty_list))
|
6
|
+
class RouteV44MessageEncoder < RouteMessageEncoder
|
7
|
+
private
|
12
8
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
9
|
+
def option(message)
|
10
|
+
if message.impersonated_user && !message.database_name
|
11
|
+
{ imp_user: message.impersonated_user }
|
12
|
+
elsif message.database_name
|
13
|
+
{ db: message.database_name }
|
17
14
|
else
|
18
|
-
|
15
|
+
{}
|
19
16
|
end
|
20
|
-
|
21
|
-
packer.pack(params)
|
22
17
|
end
|
23
18
|
end
|
24
19
|
end
|
@@ -7,9 +7,8 @@ module Neo4j::Driver
|
|
7
7
|
|
8
8
|
def initialize(bookmark, config, database_name, mode, impersonated_user)
|
9
9
|
super(Request::TransactionMetadataBuilder.build_metadata(
|
10
|
-
|
11
|
-
|
12
|
-
impersonated_user: impersonated_user))
|
10
|
+
timeout: config[:timeout], tx_metadata: config[:metadata], database_name: database_name, mode: mode,
|
11
|
+
bookmark: bookmark, impersonated_user: impersonated_user))
|
13
12
|
end
|
14
13
|
|
15
14
|
def signature
|
@@ -10,12 +10,12 @@ module Neo4j::Driver
|
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
|
-
def supports_multi_database(connection)
|
13
|
+
def supports_multi_database?(connection)
|
14
14
|
connection.server_version >= Util::ServerVersion::V4_0_0 &&
|
15
15
|
connection.protocol.version >= V4::BoltProtocolV4::VERSION
|
16
16
|
end
|
17
17
|
|
18
|
-
def supports_route_message(connection)
|
18
|
+
def supports_route_message?(connection)
|
19
19
|
connection.protocol.version >= V43::BoltProtocolV43::VERSION
|
20
20
|
end
|
21
21
|
end
|
@@ -6,19 +6,14 @@ module Neo4j::Driver
|
|
6
6
|
# instance can provide the wanted service.
|
7
7
|
# <p>
|
8
8
|
# This message is used to fetch this routing information.
|
9
|
+
#
|
10
|
+
# @param routingContext The routing context used to define the routing table. Multi-datacenter deployments is one of its use cases.
|
11
|
+
# @param bookmark The bookmark used when getting the routing table.
|
12
|
+
# @param databaseName The name of the database to get the routing table for.
|
13
|
+
# @param impersonatedUser The name of the impersonated user to get the routing table for, should be {@code null} for non-impersonated requests
|
9
14
|
class RouteMessage < Struct.new(:routing_context, :bookmark, :database_name, :impersonated_user)
|
10
15
|
SIGNATURE = 0x66
|
11
16
|
|
12
|
-
# Constructor
|
13
|
-
|
14
|
-
# @param routingContext The routing context used to define the routing table. Multi-datacenter deployments is one of its use cases.
|
15
|
-
# @param bookmark The bookmark used when getting the routing table.
|
16
|
-
# @param databaseName The name of the database to get the routing table for.
|
17
|
-
# @param impersonatedUser The name of the impersonated user to get the routing table for, should be {@code null} for non-impersonated requests
|
18
|
-
def initialize(routing_context, bookmark, database_name, impersonated_user)
|
19
|
-
super(routing_context.freeze, bookmark, database_name, impersonated_user)
|
20
|
-
end
|
21
|
-
|
22
17
|
def signature
|
23
18
|
SIGNATURE
|
24
19
|
end
|