neo4j-ruby-driver 4.4.0.alpha.4 → 4.4.0.alpha.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -0
  3. data/lib/neo4j/driver/exceptions/protocol_exception.rb +2 -2
  4. data/lib/neo4j/driver/internal/bolt_server_address.rb +6 -6
  5. data/lib/neo4j/driver/types/time.rb +4 -2
  6. data/ruby/neo4j/driver/config.rb +1 -1
  7. data/ruby/neo4j/driver/internal/async/inbound/inbound_message_dispatcher.rb +1 -1
  8. data/ruby/neo4j/driver/internal/async/network_connection.rb +15 -22
  9. data/ruby/neo4j/driver/internal/async/network_session.rb +4 -3
  10. data/ruby/neo4j/driver/internal/async/pool/channel.rb +1 -0
  11. data/ruby/neo4j/driver/internal/async/pool/{netty_channel_tracker.rb → channel_tracker.rb} +6 -8
  12. data/ruby/neo4j/driver/internal/async/pool/connection_pool_impl.rb +4 -3
  13. data/ruby/neo4j/driver/internal/cluster/cluster_composition.rb +10 -20
  14. data/ruby/neo4j/driver/internal/cluster/cluster_composition_lookup_result.rb +2 -2
  15. data/ruby/neo4j/driver/internal/cluster/cluster_routing_table.rb +37 -54
  16. data/ruby/neo4j/driver/internal/cluster/identity_resolver.rb +1 -4
  17. data/ruby/neo4j/driver/internal/cluster/loadbalancing/least_connected_load_balancing_strategy.rb +6 -6
  18. data/ruby/neo4j/driver/internal/cluster/loadbalancing/load_balancer.rb +44 -80
  19. data/ruby/neo4j/driver/internal/cluster/multi_databases_routing_procedure_runner.rb +6 -9
  20. data/ruby/neo4j/driver/internal/cluster/rediscovery_impl.rb +65 -155
  21. data/ruby/neo4j/driver/internal/cluster/route_message_routing_procedure_runner.rb +2 -2
  22. data/ruby/neo4j/driver/internal/cluster/routing_procedure_cluster_composition_provider.rb +8 -12
  23. data/ruby/neo4j/driver/internal/cluster/routing_procedure_response.rb +19 -3
  24. data/ruby/neo4j/driver/internal/cluster/routing_table_handler_impl.rb +46 -67
  25. data/ruby/neo4j/driver/internal/cluster/routing_table_registry_impl.rb +42 -61
  26. data/ruby/neo4j/driver/internal/cluster/single_database_routing_procedure_runner.rb +8 -10
  27. data/ruby/neo4j/driver/internal/cursor/async_result_cursor_impl.rb +2 -1
  28. data/ruby/neo4j/driver/internal/cursor/disposable_async_result_cursor.rb +11 -14
  29. data/ruby/neo4j/driver/internal/database_name_util.rb +3 -3
  30. data/ruby/neo4j/driver/internal/default_bookmark_holder.rb +1 -7
  31. data/ruby/neo4j/driver/internal/direct_connection_provider.rb +1 -1
  32. data/ruby/neo4j/driver/internal/driver_factory.rb +4 -4
  33. data/ruby/neo4j/driver/internal/handlers/channel_releasing_reset_response_handler.rb +11 -10
  34. data/ruby/neo4j/driver/internal/handlers/legacy_pull_all_response_handler.rb +35 -25
  35. data/ruby/neo4j/driver/internal/handlers/pulln/auto_pull_response_handler.rb +1 -2
  36. data/ruby/neo4j/driver/internal/handlers/reset_response_handler.rb +1 -1
  37. data/ruby/neo4j/driver/internal/impersonation_util.rb +2 -2
  38. data/ruby/neo4j/driver/internal/internal_bookmark.rb +1 -1
  39. data/ruby/neo4j/driver/internal/internal_database_name.rb +3 -5
  40. data/ruby/neo4j/driver/internal/internal_driver.rb +1 -1
  41. data/ruby/neo4j/driver/internal/messaging/bolt_protocol_version.rb +3 -1
  42. data/ruby/neo4j/driver/internal/messaging/encode/route_message_encoder.rb +8 -2
  43. data/ruby/neo4j/driver/internal/messaging/encode/route_v44_message_encoder.rb +8 -13
  44. data/ruby/neo4j/driver/internal/messaging/request/begin_message.rb +2 -3
  45. data/ruby/neo4j/driver/internal/messaging/request/multi_database_util.rb +2 -2
  46. data/ruby/neo4j/driver/internal/messaging/request/route_message.rb +5 -10
  47. data/ruby/neo4j/driver/internal/messaging/request/run_with_metadata_message.rb +5 -3
  48. data/ruby/neo4j/driver/internal/messaging/request/transaction_metadata_builder.rb +2 -2
  49. data/ruby/neo4j/driver/internal/messaging/v3/bolt_protocol_v3.rb +1 -1
  50. data/ruby/neo4j/driver/internal/messaging/v44/message_writer_v44.rb +1 -1
  51. data/ruby/neo4j/driver/internal/read_only_bookmark_holder.rb +13 -0
  52. data/ruby/neo4j/driver/internal/resolved_bolt_server_address.rb +35 -0
  53. data/ruby/neo4j/driver/internal/security/security_plan_impl.rb +14 -9
  54. data/ruby/neo4j/driver/internal/util/error_util.rb +1 -1
  55. data/ruby/neo4j/driver/net/{server_address1.rb → server_address.rb} +2 -2
  56. data/ruby/neo4j/driver/query.rb +1 -1
  57. data/ruby/neo4j/driver/transaction_config.rb +5 -1
  58. data/ruby/neo4j/driver/values.rb +3 -3
  59. data/ruby/neo4j/driver/version.rb +1 -1
  60. metadata +11 -24
  61. data/ruby/neo4j/driver/internal/database_name.rb +0 -12
@@ -6,109 +6,88 @@ module Neo4j::Driver
6
6
 
7
7
  delegate :servers, to: :routing_table
8
8
 
9
- def initialize(routing_table, rediscovery, connection_pool, routing_table_registry, logger, routing_table_purge_delay_ms)
9
+ def initialize(routing_table, rediscovery, connection_pool, routing_table_registry, logger, routing_table_purge_delay)
10
10
  @routing_table = routing_table
11
11
  @database_name = routing_table.database
12
12
  @rediscovery = rediscovery
13
13
  @connection_pool = connection_pool
14
14
  @routing_table_registry = routing_table_registry
15
15
  @log = logger
16
- @routing_table_purge_delay_ms = routing_table_purge_delay_ms
17
- @resolved_initial_routers = []
18
- @refresh_routing_table_future = nil
16
+ @routing_table_purge_delay = routing_table_purge_delay
17
+ @mutex = Concurrent::ReentrantReadWriteLock.new
19
18
  end
20
19
 
21
20
  def on_connection_failure(address)
22
21
  # remove server from the routing table, to prevent concurrent threads from making connections to this address
23
- routing_table.forget(address)
22
+ @routing_table.forget(address)
24
23
  end
25
24
 
26
25
  def on_write_failure(address)
27
- routing_table.forget_writer(address)
26
+ @routing_table.forget_writer(address)
28
27
  end
29
28
 
30
29
  def ensure_routing_table(context)
31
- # refresh is already happening concurrently, just use it's result
32
- return @refresh_routing_table_future unless @refresh_routing_table_future.nil?
33
-
34
- if routing_table.stale_for?(context.mode)
35
- # existing routing table is not fresh and should be updated
36
- @log.debug( "Routing table for database '#{@database_name.description}' is stale. #{routing_table}")
37
-
38
- result_future = java.util.concurrent.CompletableFuture.new
39
- @refresh_routing_table_future = result_future
40
-
41
- @rediscovery.lookup_cluster_composition(routing_table, @connection_pool, context.rediscovery_bookmark, nil).when_complete do |composition, completion_error|
42
- error = Util::Futures.completion_exception_cause(completion_error)
43
-
44
- if error.nil?
45
- fresh_cluster_composition_fetched(composition)
46
- else
47
- cluster_composition_lookup_failed(error)
48
- end
30
+ @mutex.with_write_lock do
31
+ if @routing_table.stale_for?(context.mode)
32
+ # existing routing table is not fresh and should be updated
33
+ @log.debug("Routing table for database '#{@database_name.description}' is stale. #{@routing_table}")
34
+
35
+ fresh_cluster_composition_fetched(
36
+ @rediscovery.lookup_cluster_composition(@routing_table, @connection_pool, context.rediscovery_bookmark,
37
+ nil))
38
+ else
39
+ # existing routing table is fresh, use it
40
+ @routing_table
49
41
  end
50
-
51
- result_future
52
- else
53
- # existing routing table is fresh, use it
54
- java.util.concurrent.CompletableFuture.completed_future(routing_table)
42
+ rescue => error
43
+ cluster_composition_lookup_failed(error)
55
44
  end
56
45
  end
57
46
 
58
47
  def update_routing_table(composition_lookup_result)
59
- if !@refresh_routing_table_future.nil?
60
- # refresh is already happening concurrently, just use its result
61
- @refresh_routing_table_future
62
- else
63
- if composition_lookup_result.get_cluster_composition.expiration_timestamp < routing_table.expiration_timestamp
64
- return java.util.concurrent.CompletableFuture.completed_future(routing_table)
48
+ @mutex.with_write_lock do
49
+ if composition_lookup_result.cluster_composition.expiration_timestamp < @routing_table.expiration_timestamp
50
+ @routing_table
51
+ else
52
+ fresh_cluster_composition_fetched(composition_lookup_result)
65
53
  end
66
-
67
- result_future = java.util.concurrent.CompletableFuture.new
68
- @refresh_routing_table_future = result_future
69
- fresh_cluster_composition_fetched(composition_lookup_result)
70
- result_future
71
54
  end
72
55
  end
73
56
 
74
- private def fresh_cluster_composition_fetched(composition_lookup_result)
75
- begin
76
- @log.debug("Fetched cluster composition for database '#{@database_name.description}'. #{composition_lookup_result.cluster_composition}")
77
- routing_table.update(composition_lookup_result.cluster_composition)
78
- @routing_table_registry.remove_aged
57
+ private
79
58
 
80
- addresses_to_retain = []
81
- @routing_table_registry.all_servers.stream.flat_map(BoltServerAddress::unicast_stream).for_each(addresses_to_retain::add)
59
+ def fresh_cluster_composition_fetched(composition_lookup_result)
60
+ @log.debug("Fetched cluster composition for database '#{@database_name.description}'. #{composition_lookup_result.cluster_composition}")
61
+ @routing_table.update(composition_lookup_result.cluster_composition)
62
+ @routing_table_registry.remove_aged
63
+ addresses_to_retain = @routing_table_registry.all_servers.map(&:unicast_stream).reduce(&:+)
82
64
 
83
- composition_lookup_result.resolved_initial_routers.if_present do |addresses|
84
- @resolved_initial_routers.clear
85
- @resolved_initial_routers << addresses
86
- end
65
+ composition_lookup_result.resolved_initial_routers&.then do |addresses|
66
+ addresses_to_retain << addresses
67
+ end
87
68
 
88
- addresses_to_retain << @resolved_initial_routers
89
- @connection_pool.retain_all(addresses_to_retain)
69
+ @connection_pool.retain_all(addresses_to_retain)
90
70
 
91
- @log.debug("Updated routing table for database '#{@database_name.description}'. #{routing_table}")
71
+ @log.debug("Updated routing table for database '#{@database_name.description}'. #{routing_table}")
72
+ @routing_table
73
+ rescue => error
74
+ cluster_composition_lookup_failed(error)
75
+ end
92
76
 
93
- routing_table_future = @refresh_routing_table_future
94
- @refresh_routing_table_future = nil
95
- routing_table_future.complete( routing_table)
96
- rescue StandardError => error
97
- cluster_composition_lookup_failed(error)
77
+ def cluster_composition_lookup_failed(error)
78
+ @log.error do
79
+ "Failed to update routing table for database '#{@database_name.description}'. Current routing table: #{@routing_table}."
98
80
  end
81
+ @log.error(error)
82
+ @routing_table_registry.remove(@database_name)
83
+ raise error
99
84
  end
100
85
 
101
- private def cluster_composition_lookup_failed(error)
102
- @log.error("Failed to update routing table for database '#{database_name.description}'. Current routing table: #{routing_table}.", error)
103
- @routing_table_registry.remove(database_name)
104
- routing_table_future = @refresh_routing_table_future
105
- @refresh_routing_table_future = nil
106
- routing_table_future.complete_exceptionally(error)
107
- end
86
+ public
108
87
 
109
88
  # This method cannot be synchronized as it will be visited by all routing table handler's threads concurrently
110
89
  def routing_table_aged?
111
- @refresh_routing_table_future.nil? && routing_table.has_been_stale_for?(@routing_table_purge_delay_ms)
90
+ @mutex.with_read_lock { @routing_table.has_been_stale_for?(@routing_table_purge_delay) }
112
91
  end
113
92
  end
114
93
  end
@@ -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, routing_table_purge_delay_ms)
6
- @factory = RoutingTableHandlerFactory.new(connection_pool, rediscovery, clock, logger, routing_table_purge_delay_ms)
7
- @routing_table_handlers = Concurrent::Hash.new
8
- @principal_to_database_name_stage = {}
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).then_compose do |ctx_and_handler|
17
- completed_context = ctx_and_handler.context
18
- handler = ctx_and_handler.handler.nil? ? get_or_create(Util::Futures.join_now_or_else_throw(completed_context.database_name_future, Async::ConnectionContext::PENDING_DATABASE_NAME_EXCEPTION_SUPPLIER)) : ctx_and_handler.handler
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
- context_database_name_future = context.database_name_future
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
- database_name_stage = @principal_to_database_name_stage[principal]
32
- handler_ref = java.util.concurrent.atomic.AtomicReference.new
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
- context_and_handler_stage =
58
- database_name_stage.then_apply do |database_name|
59
- context_database_name_future.complete(database_name)
60
- ConnectionContextAndHandler.new(context, handler_ref)
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
- context_and_handler_stage
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 get_routing_table_handler(database_name)
94
- java.util.Optional.of_nullable(@routing_table_handlers[database_name])
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
- def contains(database_name)
98
- @routing_table_handlers.keys.include?(database_name)
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 |name|
103
- handler = @factory.new_instance(name, self)
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, routing_table_purge_delay_ms)
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
- @routing_table_purge_delay_ms = routing_table_purge_delay_ms
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, @routing_table_purge_delay_ms)
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 = '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).then_compose do |records|
20
- release_connection(delegate, records).handle do |records, error|
21
- process_procedure_response(procedure, records, error)
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.then_compose(Async::ResultCursor::list_async)
46
+ .async_result.to_a
49
47
  end
50
48
 
51
- def release_connection(connection, records)
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.then_apply(->(_ignore) { records } )
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 each_async(&action)
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.then_compose(-> (_ignored) { @delegate.next_async })
18
+ assert_not_disposed
19
+ @delegate.next_async
18
20
  end
19
21
 
20
22
  def peek_async
21
- assert_not_disposed.then_compose(-> (_ignored) { @delegate.peek_async })
23
+ assert_not_disposed
24
+ @delegate.peek_async
22
25
  end
23
26
 
24
27
  def single_async
25
- assert_not_disposed.then_compose(-> (_ignored) { @delegate.single_async })
28
+ assert_not_disposed
29
+ @delegate.single_async
26
30
  end
27
31
 
28
- def for_each_async(action)
29
- assert_not_disposed.then_compose(-> (_ignored) { @delegate.for_each_async(action) })
30
- end
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
- return Util::Futures.failed_future(new_result_consumed_error) if @disposed
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 = Struct.new(:database_name, :description).new(nil, '<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
@@ -22,7 +22,7 @@ module Neo4j::Driver
22
22
 
23
23
  def supports_multi_db?
24
24
  private_acquire_connection.then do |conn|
25
- supports_multi_database?(conn)
25
+ Messaging::Request::MultiDatabaseUtil.supports_multi_database?(conn)
26
26
  ensure
27
27
  conn.release
28
28
  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, routingSettings, retryLogic, metricsProvider, config)
87
- connection_provider = create_load_balancer(address, connection_pool, eventExecutorGroup, config, routingSettings)
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, routingSettings)
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, routingSettings, connection_pool, eventExecutorGroup,
102
+ address, routing_settings, connection_pool, eventExecutorGroup,
103
103
  config[:logger], load_balancing_strategy, resolver, &method(:domain_name_resolver))
104
104
  end
105
105
 
@@ -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