neo4j-ruby-driver 1.7.4 → 4.4.0
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 +37 -42
- data/lib/loader.rb +5 -3
- data/lib/neo4j/driver/auto_closable.rb +2 -2
- data/lib/neo4j/driver/exceptions/authentication_exception.rb +6 -1
- data/lib/neo4j/driver/exceptions/authorization_expired_exception.rb +14 -0
- data/lib/neo4j/driver/{types/bytes.rb → exceptions/certificate_exception.rb} +2 -2
- data/lib/neo4j/driver/exceptions/client_exception.rb +3 -0
- data/lib/neo4j/driver/exceptions/connection_read_timeout_exception.rb +14 -0
- data/lib/neo4j/driver/exceptions/database_exception.rb +3 -0
- data/lib/neo4j/driver/exceptions/discovery_exception.rb +16 -0
- data/lib/neo4j/driver/exceptions/fatal_discovery_exception.rb +13 -0
- data/lib/neo4j/driver/exceptions/protocol_exception.rb +7 -0
- data/lib/neo4j/driver/exceptions/result_consumed_exception.rb +13 -0
- data/lib/neo4j/driver/exceptions/security_exception.rb +5 -1
- data/lib/neo4j/driver/exceptions/service_unavailable_exception.rb +2 -0
- data/lib/neo4j/driver/exceptions/session_expired_exception.rb +4 -0
- data/lib/neo4j/driver/exceptions/token_expired_exception.rb +15 -0
- data/lib/neo4j/driver/exceptions/transaction_nesting_exception.rb +11 -0
- data/lib/neo4j/driver/exceptions/transient_exception.rb +3 -0
- data/lib/neo4j/driver/exceptions/untrusted_server_exception.rb +1 -0
- data/lib/neo4j/driver/exceptions/value/lossy_coercion.rb +15 -0
- data/lib/neo4j/driver/exceptions/value/not_multi_valued.rb +13 -0
- data/lib/neo4j/driver/exceptions/value/uncoercible.rb +15 -0
- data/lib/neo4j/driver/exceptions/value/unsizable.rb +12 -0
- data/lib/neo4j/driver/exceptions/value/value_exception.rb +12 -0
- data/lib/neo4j/driver/internal/bolt_server_address.rb +97 -0
- data/lib/neo4j/driver/internal/duration_normalizer.rb +1 -1
- data/lib/neo4j/driver/internal/validator.rb +5 -4
- data/{ffi/neo4j/driver/summary/statement_type.rb → lib/neo4j/driver/summary/query_type.rb} +1 -3
- data/lib/neo4j/driver/synchronizable.rb +23 -0
- data/lib/neo4j/driver/types/time.rb +4 -2
- data/lib/neo4j_ruby_driver.rb +5 -10
- data/{ffi → ruby}/neo4j/driver/access_mode.rb +2 -2
- data/ruby/neo4j/driver/auth_tokens.rb +34 -0
- data/ruby/neo4j/driver/bookmark.rb +21 -0
- data/ruby/neo4j/driver/config.rb +89 -0
- data/ruby/neo4j/driver/graph_database.rb +80 -0
- data/ruby/neo4j/driver/internal/async/connection/bolt_protocol_util.rb +51 -0
- data/ruby/neo4j/driver/internal/async/connection/bootstrap_factory.rb +22 -0
- data/ruby/neo4j/driver/internal/async/connection/channel_attributes.rb +31 -0
- data/ruby/neo4j/driver/internal/async/connection/channel_connected_listener.rb +32 -0
- data/ruby/neo4j/driver/internal/async/connection/channel_connector_impl.rb +83 -0
- data/ruby/neo4j/driver/internal/async/connection/channel_pipeline_builder_impl.rb +22 -0
- data/ruby/neo4j/driver/internal/async/connection/direct_connection.rb +30 -0
- data/ruby/neo4j/driver/internal/async/connection/event_loop_group_factory.rb +83 -0
- data/ruby/neo4j/driver/internal/async/connection/handshake_completed_listener.rb +27 -0
- data/ruby/neo4j/driver/internal/async/connection/handshake_handler.rb +113 -0
- data/ruby/neo4j/driver/internal/async/connection/netty_channel_initializer.rb +57 -0
- data/ruby/neo4j/driver/internal/async/connection/netty_domain_name_resolver.rb +26 -0
- data/ruby/neo4j/driver/internal/async/connection/netty_domain_name_resolver_group.rb +19 -0
- data/ruby/neo4j/driver/internal/async/connection/routing_connection.rb +36 -0
- data/ruby/neo4j/driver/internal/async/connection/stream.rb +12 -0
- data/ruby/neo4j/driver/internal/async/connection/stream_reader.rb +16 -0
- data/ruby/neo4j/driver/internal/async/connection_context.rb +10 -0
- data/ruby/neo4j/driver/internal/async/immutable_connection_context.rb +24 -0
- data/ruby/neo4j/driver/internal/async/inbound/byte_buf_input.rb +30 -0
- data/ruby/neo4j/driver/internal/async/inbound/channel_error_handler.rb +77 -0
- data/ruby/neo4j/driver/internal/async/inbound/chunk_decoder.rb +41 -0
- data/ruby/neo4j/driver/internal/async/inbound/connect_timeout_handler.rb +32 -0
- data/ruby/neo4j/driver/internal/async/inbound/connection_read_timeout_handler.rb +17 -0
- data/ruby/neo4j/driver/internal/async/inbound/inbound_message_dispatcher.rb +171 -0
- data/ruby/neo4j/driver/internal/async/inbound/inbound_message_handler.rb +42 -0
- data/ruby/neo4j/driver/internal/async/inbound/message_decoder.rb +51 -0
- data/ruby/neo4j/driver/internal/async/internal_async_session.rb +98 -0
- data/ruby/neo4j/driver/internal/async/internal_async_transaction.rb +13 -0
- data/ruby/neo4j/driver/internal/async/leak_logging_network_session.rb +34 -0
- data/ruby/neo4j/driver/internal/async/network_connection.rb +194 -0
- data/ruby/neo4j/driver/internal/async/network_session.rb +150 -0
- data/ruby/neo4j/driver/internal/async/outbound/chunk_aware_byte_buf_output.rb +110 -0
- data/ruby/neo4j/driver/internal/async/outbound/outbound_message_handler.rb +39 -0
- data/ruby/neo4j/driver/internal/async/pool/channel.rb +62 -0
- data/ruby/neo4j/driver/internal/async/pool/channel_pool.rb +31 -0
- data/ruby/neo4j/driver/internal/async/pool/channel_tracker.rb +135 -0
- data/ruby/neo4j/driver/internal/async/pool/connection_pool_impl.rb +156 -0
- data/ruby/neo4j/driver/internal/async/pool/netty_channel_health_checker.rb +87 -0
- data/ruby/neo4j/driver/internal/async/pool/netty_channel_pool.rb +52 -0
- data/ruby/neo4j/driver/internal/async/pool/network_connection_factory.rb +21 -0
- data/ruby/neo4j/driver/internal/async/pool/pool_settings.rb +34 -0
- data/ruby/neo4j/driver/internal/async/pool/timed_stack.rb +15 -0
- data/ruby/neo4j/driver/internal/async/result_cursors_holder.rb +17 -0
- data/ruby/neo4j/driver/internal/async/unmanaged_transaction.rb +212 -0
- data/ruby/neo4j/driver/internal/bookmark_holder.rb +9 -0
- data/ruby/neo4j/driver/internal/cluster/cluster_composition.rb +48 -0
- data/ruby/neo4j/driver/internal/cluster/cluster_composition_lookup_result.rb +14 -0
- data/ruby/neo4j/driver/internal/cluster/cluster_routing_table.rb +122 -0
- data/ruby/neo4j/driver/internal/cluster/identity_resolver.rb +10 -0
- data/ruby/neo4j/driver/internal/cluster/loadbalancing/least_connected_load_balancing_strategy.rb +68 -0
- data/ruby/neo4j/driver/internal/cluster/loadbalancing/load_balancer.rb +125 -0
- data/ruby/neo4j/driver/internal/cluster/loadbalancing/round_robin_array_index.rb +13 -0
- data/ruby/neo4j/driver/internal/cluster/multi_databases_routing_procedure_runner.rb +31 -0
- data/ruby/neo4j/driver/internal/cluster/rediscovery_impl.rb +147 -0
- data/ruby/neo4j/driver/internal/cluster/route_message_routing_procedure_runner.rb +43 -0
- data/ruby/neo4j/driver/internal/cluster/routing_context.rb +77 -0
- data/ruby/neo4j/driver/internal/cluster/routing_procedure_cluster_composition_provider.rb +60 -0
- data/ruby/neo4j/driver/internal/cluster/routing_procedure_response.rb +35 -0
- data/ruby/neo4j/driver/internal/cluster/routing_settings.rb +24 -0
- data/ruby/neo4j/driver/internal/cluster/routing_table_handler_impl.rb +95 -0
- data/ruby/neo4j/driver/internal/cluster/routing_table_registry_impl.rb +121 -0
- data/ruby/neo4j/driver/internal/cluster/single_database_routing_procedure_runner.rb +73 -0
- data/ruby/neo4j/driver/internal/connection_settings.rb +16 -0
- data/ruby/neo4j/driver/internal/cursor/async_result_cursor_impl.rb +55 -0
- data/ruby/neo4j/driver/internal/cursor/async_result_cursor_only_factory.rb +24 -0
- data/ruby/neo4j/driver/internal/cursor/disposable_async_result_cursor.rb +61 -0
- data/ruby/neo4j/driver/internal/cursor/result_cursor_factory_impl.rb +24 -0
- data/ruby/neo4j/driver/internal/cursor/rx_result_cursor_impl.rb +110 -0
- data/ruby/neo4j/driver/internal/database_name_util.rb +37 -0
- data/ruby/neo4j/driver/internal/default_bookmark_holder.rb +9 -0
- data/ruby/neo4j/driver/internal/default_domain_name_resolver.rb +11 -0
- data/ruby/neo4j/driver/internal/direct_connection_provider.rb +40 -0
- data/ruby/neo4j/driver/internal/driver_factory.rb +126 -0
- data/ruby/neo4j/driver/internal/handlers/begin_tx_response_handler.rb +20 -0
- data/ruby/neo4j/driver/internal/handlers/channel_releasing_reset_response_handler.rb +30 -0
- data/ruby/neo4j/driver/internal/handlers/commit_tx_response_handler.rb +25 -0
- data/ruby/neo4j/driver/internal/handlers/hello_response_handler.rb +65 -0
- data/ruby/neo4j/driver/internal/handlers/init_response_handler.rb +34 -0
- data/ruby/neo4j/driver/internal/handlers/legacy_pull_all_response_handler.rb +199 -0
- data/ruby/neo4j/driver/internal/handlers/no_op_response_handler.rb +16 -0
- data/ruby/neo4j/driver/internal/handlers/ping_response_handler.rb +29 -0
- data/ruby/neo4j/driver/internal/handlers/pull_handlers.rb +32 -0
- data/ruby/neo4j/driver/internal/handlers/pulln/auto_pull_response_handler.rb +168 -0
- data/ruby/neo4j/driver/internal/handlers/pulln/basic_pull_response_handler.rb +298 -0
- data/ruby/neo4j/driver/internal/handlers/pulln/fetch_size_util.rb +20 -0
- data/ruby/neo4j/driver/internal/handlers/reset_response_handler.rb +34 -0
- data/ruby/neo4j/driver/internal/handlers/rollback_tx_response_handler.rb +25 -0
- data/ruby/neo4j/driver/internal/handlers/route_message_response_handler.rb +21 -0
- data/ruby/neo4j/driver/internal/handlers/routing_response_handler.rb +70 -0
- data/ruby/neo4j/driver/internal/handlers/run_response_handler.rb +38 -0
- data/ruby/neo4j/driver/internal/handlers/session_pull_response_completion_listener.rb +34 -0
- data/ruby/neo4j/driver/internal/handlers/transaction_pull_response_completion_listener.rb +20 -0
- data/ruby/neo4j/driver/internal/impersonation_util.rb +22 -0
- data/ruby/neo4j/driver/internal/internal_bookmark.rb +36 -0
- data/ruby/neo4j/driver/internal/internal_database_name.rb +9 -0
- data/ruby/neo4j/driver/internal/internal_driver.rb +74 -0
- data/ruby/neo4j/driver/internal/internal_entity.rb +20 -0
- data/ruby/neo4j/driver/internal/internal_node.rb +21 -0
- data/ruby/neo4j/driver/internal/internal_pair.rb +9 -0
- data/ruby/neo4j/driver/internal/internal_path.rb +35 -0
- data/ruby/neo4j/driver/internal/internal_point2_d.rb +9 -0
- data/ruby/neo4j/driver/internal/internal_point3_d.rb +6 -0
- data/{ffi → ruby}/neo4j/driver/internal/internal_record.rb +2 -1
- data/ruby/neo4j/driver/internal/internal_relationship.rb +26 -0
- data/ruby/neo4j/driver/internal/internal_result.rb +49 -0
- data/ruby/neo4j/driver/internal/internal_session.rb +81 -0
- data/ruby/neo4j/driver/internal/internal_transaction.rb +48 -0
- data/ruby/neo4j/driver/internal/logging/channel_activity_logger.rb +29 -0
- data/ruby/neo4j/driver/internal/logging/channel_error_logger.rb +17 -0
- data/ruby/neo4j/driver/internal/logging/prefixed_logger.rb +19 -0
- data/ruby/neo4j/driver/internal/logging/reformatted_logger.rb +17 -0
- data/ruby/neo4j/driver/internal/messaging/abstract_message_writer.rb +23 -0
- data/ruby/neo4j/driver/internal/messaging/bolt_protocol.rb +30 -0
- data/ruby/neo4j/driver/internal/messaging/bolt_protocol_version.rb +48 -0
- data/ruby/neo4j/driver/internal/messaging/common/common_message_reader.rb +51 -0
- data/ruby/neo4j/driver/internal/messaging/common/common_value.rb +31 -0
- data/ruby/neo4j/driver/internal/messaging/common/common_value_packer.rb +101 -0
- data/ruby/neo4j/driver/internal/messaging/common/common_value_unpacker.rb +234 -0
- data/ruby/neo4j/driver/internal/messaging/encode/begin_message_encoder.rb +15 -0
- data/ruby/neo4j/driver/internal/messaging/encode/commit_message_encoder.rb +14 -0
- data/ruby/neo4j/driver/internal/messaging/encode/discard_all_message_encoder.rb +14 -0
- data/ruby/neo4j/driver/internal/messaging/encode/discard_message_encoder.rb +15 -0
- data/ruby/neo4j/driver/internal/messaging/encode/goodbye_message_encoder.rb +14 -0
- data/ruby/neo4j/driver/internal/messaging/encode/hello_message_encoder.rb +15 -0
- data/ruby/neo4j/driver/internal/messaging/encode/init_message_encoder.rb +16 -0
- data/ruby/neo4j/driver/internal/messaging/encode/pull_all_message_encoder.rb +14 -0
- data/ruby/neo4j/driver/internal/messaging/encode/pull_message_encoder.rb +15 -0
- data/ruby/neo4j/driver/internal/messaging/encode/reset_message_encoder.rb +14 -0
- data/ruby/neo4j/driver/internal/messaging/encode/rollback_message_encoder.rb +14 -0
- data/ruby/neo4j/driver/internal/messaging/encode/route_message_encoder.rb +24 -0
- data/ruby/neo4j/driver/internal/messaging/encode/route_v44_message_encoder.rb +22 -0
- data/ruby/neo4j/driver/internal/messaging/encode/run_message_encoder.rb +16 -0
- data/ruby/neo4j/driver/internal/messaging/encode/run_with_metadata_message_encoder.rb +17 -0
- data/ruby/neo4j/driver/internal/messaging/request/abstract_streaming_message.rb +25 -0
- data/ruby/neo4j/driver/internal/messaging/request/begin_message.rb +25 -0
- data/ruby/neo4j/driver/internal/messaging/request/commit_message.rb +20 -0
- data/ruby/neo4j/driver/internal/messaging/request/discard_all_message.rb +20 -0
- data/ruby/neo4j/driver/internal/messaging/request/discard_message.rb +23 -0
- data/ruby/neo4j/driver/internal/messaging/request/goodbye_message.rb +20 -0
- data/ruby/neo4j/driver/internal/messaging/request/hello_message.rb +31 -0
- data/ruby/neo4j/driver/internal/messaging/request/init_message.rb +19 -0
- data/ruby/neo4j/driver/internal/messaging/request/message_with_metadata.rb +10 -0
- data/ruby/neo4j/driver/internal/messaging/request/multi_database_util.rb +26 -0
- data/ruby/neo4j/driver/internal/messaging/request/pull_all_message.rb +23 -0
- data/ruby/neo4j/driver/internal/messaging/request/pull_message.rb +22 -0
- data/ruby/neo4j/driver/internal/messaging/request/reset_message.rb +32 -0
- data/ruby/neo4j/driver/internal/messaging/request/rollback_message.rb +20 -0
- data/ruby/neo4j/driver/internal/messaging/request/route_message.rb +28 -0
- data/ruby/neo4j/driver/internal/messaging/request/run_message.rb +23 -0
- data/ruby/neo4j/driver/internal/messaging/request/run_with_metadata_message.rb +49 -0
- data/ruby/neo4j/driver/internal/messaging/request/transaction_metadata_builder.rb +24 -0
- data/ruby/neo4j/driver/internal/messaging/response/failure_message.rb +40 -0
- data/ruby/neo4j/driver/internal/messaging/response/ignored_message.rb +29 -0
- data/ruby/neo4j/driver/internal/messaging/response/record_message.rb +33 -0
- data/ruby/neo4j/driver/internal/messaging/response/success_message.rb +34 -0
- data/ruby/neo4j/driver/internal/messaging/v3/bolt_protocol_v3.rb +82 -0
- data/ruby/neo4j/driver/internal/messaging/v3/message_format_v3.rb +17 -0
- data/ruby/neo4j/driver/internal/messaging/v3/message_writer_v3.rb +27 -0
- data/ruby/neo4j/driver/internal/messaging/v4/bolt_protocol_v4.rb +29 -0
- data/ruby/neo4j/driver/internal/messaging/v4/message_format_v4.rb +17 -0
- data/ruby/neo4j/driver/internal/messaging/v4/message_writer_v4.rb +17 -0
- data/ruby/neo4j/driver/internal/messaging/v41/bolt_protocol_v41.rb +25 -0
- data/ruby/neo4j/driver/internal/messaging/v42/bolt_protocol_v42.rb +13 -0
- data/ruby/neo4j/driver/internal/messaging/v43/bolt_protocol_v43.rb +19 -0
- data/ruby/neo4j/driver/internal/messaging/v43/message_format_v43.rb +18 -0
- data/ruby/neo4j/driver/internal/messaging/v43/message_writer_v43.rb +20 -0
- data/ruby/neo4j/driver/internal/messaging/v44/bolt_protocol_v44.rb +17 -0
- data/ruby/neo4j/driver/internal/messaging/v44/message_format_v44.rb +18 -0
- data/ruby/neo4j/driver/internal/messaging/v44/message_writer_v44.rb +15 -0
- data/ruby/neo4j/driver/internal/metrics/connection_pool_metrics_listener.rb +34 -0
- data/ruby/neo4j/driver/internal/metrics/internal_abstract_metrics.rb +46 -0
- data/ruby/neo4j/driver/internal/metrics/internal_connection_pool_metrics.rb +105 -0
- data/ruby/neo4j/driver/internal/metrics/internal_metrics.rb +82 -0
- data/ruby/neo4j/driver/internal/metrics/internal_metrics_provider.rb +18 -0
- data/ruby/neo4j/driver/internal/metrics/listener_event.rb +17 -0
- data/ruby/neo4j/driver/internal/metrics/metrics_provider.rb +24 -0
- data/ruby/neo4j/driver/internal/metrics/time_recorder_listener_event.rb +15 -0
- data/ruby/neo4j/driver/internal/packstream/byte_array_incompatible_packer.rb +12 -0
- data/ruby/neo4j/driver/internal/packstream/pack_input.rb +47 -0
- data/ruby/neo4j/driver/internal/packstream/pack_output.rb +39 -0
- data/ruby/neo4j/driver/internal/packstream/pack_stream.rb +326 -0
- data/ruby/neo4j/driver/internal/packstream/pack_type.rb +17 -0
- 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/retry/exponential_backoff_retry_logic.rb +151 -0
- data/ruby/neo4j/driver/internal/revocation_strategy.rb +19 -0
- data/ruby/neo4j/driver/internal/scheme.rb +32 -0
- data/ruby/neo4j/driver/internal/security/internal_auth_token.rb +15 -0
- data/ruby/neo4j/driver/internal/security/security_plan_impl.rb +48 -0
- data/ruby/neo4j/driver/internal/security_setting.rb +66 -0
- data/ruby/neo4j/driver/internal/session_factory_impl.rb +32 -0
- data/ruby/neo4j/driver/internal/spi/connection.rb +19 -0
- data/ruby/neo4j/driver/internal/spi/connection_pool.rb +9 -0
- data/ruby/neo4j/driver/internal/spi/response_handler.rb +23 -0
- data/ruby/neo4j/driver/internal/summary/internal_database_info.rb +7 -0
- data/ruby/neo4j/driver/internal/summary/internal_input_position.rb +11 -0
- data/ruby/neo4j/driver/internal/summary/internal_notification.rb +16 -0
- data/ruby/neo4j/driver/internal/summary/internal_plan.rb +41 -0
- data/ruby/neo4j/driver/internal/summary/internal_profiled_plan.rb +32 -0
- data/ruby/neo4j/driver/internal/summary/internal_result_summary.rb +33 -0
- data/ruby/neo4j/driver/internal/summary/internal_server_info.rb +6 -0
- data/ruby/neo4j/driver/internal/summary/internal_summary_counters.rb +18 -0
- data/ruby/neo4j/driver/internal/svm/netty_substitutions.rb +196 -0
- data/ruby/neo4j/driver/internal/svm/z_lib_substitutions.rb +21 -0
- data/ruby/neo4j/driver/internal/util/certificate_tool.rb +65 -0
- data/ruby/neo4j/driver/internal/util/clock.rb +29 -0
- data/ruby/neo4j/driver/internal/util/error_util.rb +104 -0
- data/ruby/neo4j/driver/internal/util/extract.rb +123 -0
- data/ruby/neo4j/driver/internal/util/format.rb +39 -0
- data/ruby/neo4j/driver/internal/util/futures.rb +99 -0
- data/ruby/neo4j/driver/internal/util/iterables.rb +35 -0
- data/ruby/neo4j/driver/internal/util/lock_util.rb +23 -0
- data/ruby/neo4j/driver/internal/util/metadata_extractor.rb +107 -0
- data/ruby/neo4j/driver/internal/util/mutex.rb +9 -0
- data/ruby/neo4j/driver/internal/util/preconditions.rb +16 -0
- data/ruby/neo4j/driver/internal/util/result_holder.rb +72 -0
- data/ruby/neo4j/driver/internal/util/server_version.rb +60 -0
- data/ruby/neo4j/driver/logging1.rb +51 -0
- data/ruby/neo4j/driver/net/server_address.rb +9 -0
- data/ruby/neo4j/driver/query.rb +48 -0
- data/ruby/neo4j/driver/records.rb +13 -0
- data/ruby/neo4j/driver/transaction_config.rb +50 -0
- data/ruby/neo4j/driver/values.rb +26 -0
- data/{lib → ruby}/neo4j/driver/version.rb +1 -1
- data/ruby/neo4j/driver.rb +29 -0
- metadata +264 -101
- data/ffi/bolt/address.rb +0 -11
- data/ffi/bolt/address_resolver.rb +0 -12
- data/ffi/bolt/address_set.rb +0 -9
- data/ffi/bolt/auth.rb +0 -10
- data/ffi/bolt/auto_releasable.rb +0 -22
- data/ffi/bolt/boolean.rb +0 -9
- data/ffi/bolt/bytes.rb +0 -10
- data/ffi/bolt/config.rb +0 -45
- data/ffi/bolt/connection.rb +0 -44
- data/ffi/bolt/connector.rb +0 -17
- data/ffi/bolt/dictionary.rb +0 -15
- data/ffi/bolt/error.rb +0 -74
- data/ffi/bolt/float.rb +0 -9
- data/ffi/bolt/integer.rb +0 -9
- data/ffi/bolt/library.rb +0 -12
- data/ffi/bolt/lifecycle.rb +0 -9
- data/ffi/bolt/list.rb +0 -10
- data/ffi/bolt/log.rb +0 -16
- data/ffi/bolt/socket_options.rb +0 -14
- data/ffi/bolt/status.rb +0 -25
- data/ffi/bolt/string.rb +0 -9
- data/ffi/bolt/structure.rb +0 -10
- data/ffi/bolt/value.rb +0 -35
- data/ffi/neo4j/driver/auth_tokens.rb +0 -18
- data/ffi/neo4j/driver/config.rb +0 -40
- data/ffi/neo4j/driver/graph_database.rb +0 -52
- data/ffi/neo4j/driver/internal/async/access_mode_connection.rb +0 -19
- data/ffi/neo4j/driver/internal/async/direct_connection.rb +0 -106
- data/ffi/neo4j/driver/internal/bolt_server_address.rb +0 -18
- data/ffi/neo4j/driver/internal/bookmarks_holder.rb +0 -30
- data/ffi/neo4j/driver/internal/direct_connection_provider.rb +0 -28
- data/ffi/neo4j/driver/internal/driver_factory.rb +0 -125
- data/ffi/neo4j/driver/internal/error_handling.rb +0 -112
- data/ffi/neo4j/driver/internal/explicit_transaction.rb +0 -146
- data/ffi/neo4j/driver/internal/handlers/pull_all_response_handler.rb +0 -104
- data/ffi/neo4j/driver/internal/handlers/response_handler.rb +0 -49
- data/ffi/neo4j/driver/internal/handlers/run_response_handler.rb +0 -32
- data/ffi/neo4j/driver/internal/handlers/session_pull_all_response_handler.rb +0 -32
- data/ffi/neo4j/driver/internal/handlers/transaction_pull_all_response_handler.rb +0 -23
- data/ffi/neo4j/driver/internal/internal_driver.rb +0 -45
- data/ffi/neo4j/driver/internal/internal_logger.rb +0 -32
- data/ffi/neo4j/driver/internal/internal_resolver.rb +0 -31
- data/ffi/neo4j/driver/internal/internal_statement_result.rb +0 -52
- data/ffi/neo4j/driver/internal/messaging/bolt_protocol.rb +0 -24
- data/ffi/neo4j/driver/internal/messaging/v1/bolt_protocol_v1.rb +0 -59
- data/ffi/neo4j/driver/internal/messaging/v2/bolt_protocol_v2.rb +0 -16
- data/ffi/neo4j/driver/internal/messaging/v3/bolt_protocol_v3.rb +0 -63
- data/ffi/neo4j/driver/internal/network_session.rb +0 -129
- data/ffi/neo4j/driver/internal/retry/exponential_backoff_retry_logic.rb +0 -80
- data/ffi/neo4j/driver/internal/session_factory_impl.rb +0 -28
- data/ffi/neo4j/driver/internal/summary/internal_result_summary.rb +0 -67
- data/ffi/neo4j/driver/internal/summary/internal_server_info.rb +0 -19
- data/ffi/neo4j/driver/internal/summary/internal_summary_counters.rb +0 -23
- data/ffi/neo4j/driver/internal/util/metadata_extractor.rb +0 -15
- data/ffi/neo4j/driver/internal/value/base_time_value.rb +0 -22
- data/ffi/neo4j/driver/internal/value/date_value.rb +0 -25
- data/ffi/neo4j/driver/internal/value/duration_value.rb +0 -27
- data/ffi/neo4j/driver/internal/value/local_date_time_value.rb +0 -24
- data/ffi/neo4j/driver/internal/value/local_time_value.rb +0 -19
- data/ffi/neo4j/driver/internal/value/node_value.rb +0 -18
- data/ffi/neo4j/driver/internal/value/offset_time_value.rb +0 -25
- data/ffi/neo4j/driver/internal/value/path_value.rb +0 -41
- data/ffi/neo4j/driver/internal/value/point2_d_value.rb +0 -24
- data/ffi/neo4j/driver/internal/value/point3_d_value.rb +0 -24
- data/ffi/neo4j/driver/internal/value/relationship_value.rb +0 -18
- data/ffi/neo4j/driver/internal/value/structure_value.rb +0 -42
- data/ffi/neo4j/driver/internal/value/time_with_zone_id_value.rb +0 -25
- data/ffi/neo4j/driver/internal/value/time_with_zone_offset_value.rb +0 -28
- data/ffi/neo4j/driver/internal/value/unbound_relationship_value.rb +0 -18
- data/ffi/neo4j/driver/internal/value/value_adapter.rb +0 -101
- data/ffi/neo4j/driver/net/server_address.rb +0 -13
- data/ffi/neo4j/driver/statement.rb +0 -15
- data/ffi/neo4j/driver/types/entity.rb +0 -21
- data/ffi/neo4j/driver/types/node.rb +0 -16
- data/ffi/neo4j/driver/types/path.rb +0 -35
- data/ffi/neo4j/driver/types/relationship.rb +0 -19
- data/ffi/neo4j/driver.rb +0 -61
- data/lib/neo4j/driver/internal/ruby_signature.rb +0 -18
@@ -0,0 +1,150 @@
|
|
1
|
+
module Neo4j::Driver
|
2
|
+
module Internal
|
3
|
+
module Async
|
4
|
+
class NetworkSession
|
5
|
+
attr_reader :retry_logic
|
6
|
+
|
7
|
+
def initialize(connection_provider, retry_logic, database_name, mode, bookmark_holder, impersonated_user, fetch_size, logger)
|
8
|
+
@connection_provider = connection_provider
|
9
|
+
@mode = mode
|
10
|
+
@retry_logic = retry_logic
|
11
|
+
@log = Logging::PrefixedLogger.new("[#{hash}]", logger)
|
12
|
+
@bookmark_holder = bookmark_holder
|
13
|
+
# @database_name = database_name.database_name
|
14
|
+
@connection_context = NetworkSessionConnectionContext.new(database_name, @bookmark_holder.bookmark, impersonated_user)
|
15
|
+
@fetch_size = fetch_size
|
16
|
+
@open = Concurrent::AtomicBoolean.new(true)
|
17
|
+
end
|
18
|
+
|
19
|
+
def run_async(query, **config)
|
20
|
+
new_result_cursor = build_result_cursor_factory(query, config).async_result
|
21
|
+
@result_cursor = new_result_cursor
|
22
|
+
new_result_cursor.map_successful_run_completion_async
|
23
|
+
end
|
24
|
+
|
25
|
+
def begin_transaction_async(mode = @mode, **config)
|
26
|
+
ensure_session_is_open
|
27
|
+
ensure_no_open_tx_before_starting_tx
|
28
|
+
acquire_connection(mode).then do |connection|
|
29
|
+
ImpersonationUtil.ensure_impersonation_support(connection, connection.impersonated_user)
|
30
|
+
tx = UnmanagedTransaction.new(connection, @bookmark_holder, @fetch_size)
|
31
|
+
tx.begin_async(@bookmark_holder.bookmark, config)
|
32
|
+
end&.tap { |new_transaction| @transaction = new_transaction }
|
33
|
+
end
|
34
|
+
|
35
|
+
def reset_async
|
36
|
+
existing_transaction_or_null
|
37
|
+
.then_accept { |tx| tx&.mark_terminated }
|
38
|
+
.then_flat { @connection_stage }
|
39
|
+
.then_flat do |connection|
|
40
|
+
# there exists an active connection, send a RESET message over it
|
41
|
+
connection&.reset || Util::Futures.completed_with_null
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def last_bookmark
|
46
|
+
@bookmark_holder.bookmark
|
47
|
+
end
|
48
|
+
|
49
|
+
def release_connection_async
|
50
|
+
@connection&.release
|
51
|
+
end
|
52
|
+
|
53
|
+
def connection_async
|
54
|
+
@connection
|
55
|
+
end
|
56
|
+
|
57
|
+
def open?
|
58
|
+
@open.true?
|
59
|
+
end
|
60
|
+
|
61
|
+
def close_async
|
62
|
+
return unless @open.make_false
|
63
|
+
# there exists a cursor with potentially unconsumed error, try to extract and propagate it
|
64
|
+
error = @result_cursor&.discard_all_failure_async
|
65
|
+
close_transaction_and_release_connection
|
66
|
+
rescue => tx_close_error
|
67
|
+
error = Util::Futures.combine_errors(error, tx_close_error)
|
68
|
+
ensure
|
69
|
+
raise error if error
|
70
|
+
end
|
71
|
+
|
72
|
+
def current_connection_open?
|
73
|
+
@connection&.open? # some connection has actually been acquired and it's still open
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def build_result_cursor_factory(query, config)
|
79
|
+
ensure_session_is_open
|
80
|
+
ensure_no_open_tx_before_running_query
|
81
|
+
connection = acquire_connection(@mode)
|
82
|
+
ImpersonationUtil.ensure_impersonation_support(connection, connection.impersonated_user)
|
83
|
+
connection.protocol.run_in_auto_commit_transaction(connection, query, @bookmark_holder, config,
|
84
|
+
@fetch_size)
|
85
|
+
end
|
86
|
+
|
87
|
+
def acquire_connection(mode)
|
88
|
+
# make sure previous result is fully consumed and connection is released back to the pool
|
89
|
+
@result_cursor&.pull_all_failure_async&.result!&.then(&method(:raise))
|
90
|
+
if @connection&.open?
|
91
|
+
# there somehow is an existing open connection, this should not happen, just a precondition
|
92
|
+
raise Neo4j::Driver::Exceptions::IllegalStateException.new('Existing open connection detected')
|
93
|
+
end
|
94
|
+
|
95
|
+
@connection = @connection_provider.acquire_connection(@connection_context.context_with_mode(mode))
|
96
|
+
end
|
97
|
+
|
98
|
+
def close_transaction_and_release_connection
|
99
|
+
existing_transaction_or_null&.close_async
|
100
|
+
ensure
|
101
|
+
release_connection_async
|
102
|
+
end
|
103
|
+
|
104
|
+
def ensure_no_open_tx_before_running_query
|
105
|
+
ensure_no_open_tx('Queries cannot be run directly on a session with an open transaction; either run from within the transaction or use a different session.')
|
106
|
+
end
|
107
|
+
|
108
|
+
def ensure_no_open_tx_before_starting_tx
|
109
|
+
ensure_no_open_tx('You cannot begin a transaction on a session with an open transaction; either run from within the transaction or use a different session.')
|
110
|
+
end
|
111
|
+
|
112
|
+
def ensure_no_open_tx(error_message)
|
113
|
+
existing_transaction_or_null&.then do
|
114
|
+
raise Neo4j::Driver::Exceptions::TransactionNestingException.new(error_message)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def existing_transaction_or_null
|
119
|
+
@transaction if @transaction&.open?
|
120
|
+
end
|
121
|
+
|
122
|
+
def ensure_session_is_open
|
123
|
+
unless @open.true?
|
124
|
+
raise Neo4j::Driver::Exceptions::ClientException.new('No more interaction with this session are allowed as the current session is already closed.')
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
# The {@link NetworkSessionConnectionContext#mode} can be mutable for a session connection context
|
129
|
+
class NetworkSessionConnectionContext
|
130
|
+
# This bookmark is only used for rediscovery.
|
131
|
+
# It has to be the initial bookmark given at the creation of the session.
|
132
|
+
# As only that bookmark could carry extra system bookmarks
|
133
|
+
attr_accessor :database_name
|
134
|
+
attr :mode, :rediscovery_bookmark, :impersonated_user
|
135
|
+
|
136
|
+
def initialize(database_name, bookmark, impersonated_user)
|
137
|
+
@database_name = database_name
|
138
|
+
@rediscovery_bookmark = bookmark
|
139
|
+
@impersonated_user = impersonated_user
|
140
|
+
end
|
141
|
+
|
142
|
+
def context_with_mode(mode)
|
143
|
+
@mode = mode
|
144
|
+
self
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
module Neo4j::Driver
|
2
|
+
module Internal
|
3
|
+
module Async
|
4
|
+
module Outbound
|
5
|
+
class ChunkAwareByteBufOutput
|
6
|
+
include Packstream::PackStream::Packer
|
7
|
+
include Messaging::Common::CommonValuePacker
|
8
|
+
|
9
|
+
class ChunkBuffer < ::Async::IO::Buffer
|
10
|
+
include Packstream::PackOutput
|
11
|
+
alias write <<
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(output, max_chunk_size: Connection::BoltProtocolUtil::DEFAULT_MAX_OUTBOUND_CHUNK_SIZE_BYTES)
|
15
|
+
@output = output
|
16
|
+
@max_chunk_size = verify_max_chunk_size(max_chunk_size)
|
17
|
+
@chunk = ChunkBuffer.new
|
18
|
+
end
|
19
|
+
|
20
|
+
def start
|
21
|
+
assert_not_started
|
22
|
+
@chunk.clear
|
23
|
+
end
|
24
|
+
|
25
|
+
def write_byte(value)
|
26
|
+
ensure_can_fit_in_current_chunk(1)
|
27
|
+
@chunk.write_byte(value)
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
31
|
+
def write(data)
|
32
|
+
offset = 0
|
33
|
+
length = data.bytesize
|
34
|
+
|
35
|
+
while offset < length
|
36
|
+
# Ensure there is an open chunk, and that it has at least one byte of space left
|
37
|
+
ensure_can_fit_in_current_chunk(1)
|
38
|
+
|
39
|
+
# Write as much as we can into the current chunk
|
40
|
+
amount_to_write = [available_bytes_in_current_chunk, length - offset].min
|
41
|
+
|
42
|
+
@chunk.write(data.byteslice(offset, amount_to_write))
|
43
|
+
offset += amount_to_write
|
44
|
+
end
|
45
|
+
|
46
|
+
self
|
47
|
+
end
|
48
|
+
|
49
|
+
def write_short(value)
|
50
|
+
ensure_can_fit_in_current_chunk(2)
|
51
|
+
@chunk.write_short(value)
|
52
|
+
self
|
53
|
+
end
|
54
|
+
|
55
|
+
def write_int(value)
|
56
|
+
ensure_can_fit_in_current_chunk(4)
|
57
|
+
@chunk.write_int(value)
|
58
|
+
self
|
59
|
+
end
|
60
|
+
|
61
|
+
def write_long(value)
|
62
|
+
ensure_can_fit_in_current_chunk(8)
|
63
|
+
@chunk.write_long(value)
|
64
|
+
self
|
65
|
+
end
|
66
|
+
|
67
|
+
def write_double(value)
|
68
|
+
ensure_can_fit_in_current_chunk(8)
|
69
|
+
@chunk.write_double(value)
|
70
|
+
self
|
71
|
+
end
|
72
|
+
|
73
|
+
def write_message_boundary
|
74
|
+
@output.write_short(0)
|
75
|
+
end
|
76
|
+
|
77
|
+
def write_chunk
|
78
|
+
@output.write_short(@chunk.bytesize)
|
79
|
+
@output.write(@chunk)
|
80
|
+
@chunk.clear
|
81
|
+
end
|
82
|
+
|
83
|
+
alias stop write_chunk
|
84
|
+
|
85
|
+
private
|
86
|
+
|
87
|
+
def ensure_can_fit_in_current_chunk(number_of_bytes)
|
88
|
+
write_chunk if @chunk.bytesize + number_of_bytes > @max_chunk_size
|
89
|
+
end
|
90
|
+
|
91
|
+
def available_bytes_in_current_chunk
|
92
|
+
@max_chunk_size - @chunk.bytesize
|
93
|
+
end
|
94
|
+
|
95
|
+
def assert_not_started
|
96
|
+
raise Neo4j::Driver::Exceptions::IllegalStateException.new('Already started') unless @chunk.empty?
|
97
|
+
end
|
98
|
+
|
99
|
+
def verify_max_chunk_size(max_chunk_size)
|
100
|
+
if max_chunk_size <= 0
|
101
|
+
raise ArgumentError.new("Max chunk size should be > 0, given: #{max_chunk_size}")
|
102
|
+
end
|
103
|
+
|
104
|
+
max_chunk_size
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Neo4j::Driver
|
2
|
+
module Internal
|
3
|
+
module Async
|
4
|
+
module Outbound
|
5
|
+
class OutboundMessageHandler
|
6
|
+
NAME = self.class.name
|
7
|
+
|
8
|
+
def initialize(output, message_format, logger)
|
9
|
+
@output = output
|
10
|
+
@writer = message_format.new_writer(output)
|
11
|
+
@log = logger
|
12
|
+
end
|
13
|
+
|
14
|
+
def handler_added(ctx)
|
15
|
+
@log = Logging::ChannelActivityLogger.new(ctx.channel, @log, self.class)
|
16
|
+
end
|
17
|
+
|
18
|
+
def handler_removed(ctx)
|
19
|
+
@log = nil
|
20
|
+
end
|
21
|
+
|
22
|
+
def encode(msg)
|
23
|
+
@log.debug("C: #{msg}")
|
24
|
+
|
25
|
+
@output.start
|
26
|
+
begin
|
27
|
+
@writer.write(msg)
|
28
|
+
ensure
|
29
|
+
@output.stop
|
30
|
+
end
|
31
|
+
|
32
|
+
@output.write_message_boundary
|
33
|
+
# @log.debug( "C: #{}") if @log.debug_enabled?
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Neo4j::Driver
|
2
|
+
module Internal
|
3
|
+
module Async
|
4
|
+
module Pool
|
5
|
+
class Channel
|
6
|
+
attr :stream
|
7
|
+
attr_accessor :version, :protocol, :message_format, :message_dispatcher
|
8
|
+
attr :attributes # should be attr
|
9
|
+
attr_accessor :auto_read
|
10
|
+
|
11
|
+
def initialize(address, connector, logger)
|
12
|
+
@attributes = Connection::ChannelAttributes.new
|
13
|
+
@stream = Connection::Stream.new(connector.connect(address))
|
14
|
+
@stream.write(Connection::BoltProtocolUtil.handshake_buf)
|
15
|
+
@stream.flush
|
16
|
+
Connection::HandshakeHandler.new(logger).decode(self)
|
17
|
+
stream_reader = Connection::StreamReader.new(@stream)
|
18
|
+
stream_writer = Outbound::ChunkAwareByteBufOutput.new(@stream)
|
19
|
+
@message_dispatcher = Inbound::InboundMessageDispatcher.new(self, logger)
|
20
|
+
@attributes[:message_dispatcher] = @message_dispatcher
|
21
|
+
@outbound_handler = Outbound::OutboundMessageHandler.new(stream_writer, message_format, logger)
|
22
|
+
@common_message_reader = Messaging::Common::CommonMessageReader.new(stream_reader)
|
23
|
+
connector.initialize_channel(self, protocol)
|
24
|
+
end
|
25
|
+
|
26
|
+
def close
|
27
|
+
@stream.close
|
28
|
+
end
|
29
|
+
|
30
|
+
def write(message)
|
31
|
+
@outbound_handler.encode(message)
|
32
|
+
end
|
33
|
+
|
34
|
+
def write_and_flush(message)
|
35
|
+
write(message)
|
36
|
+
@stream.flush
|
37
|
+
ensure_response_handling
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def bracketless(host)
|
43
|
+
host.delete_prefix('[').delete_suffix(']')
|
44
|
+
end
|
45
|
+
|
46
|
+
def ensure_response_handling
|
47
|
+
# probably should be synchronized
|
48
|
+
return if @handling_active
|
49
|
+
@handling_active = true
|
50
|
+
while @message_dispatcher.queued_handlers_count > 0 do
|
51
|
+
@common_message_reader.read(@message_dispatcher)
|
52
|
+
end
|
53
|
+
@handling_active = false
|
54
|
+
rescue
|
55
|
+
@handling_active = false
|
56
|
+
raise
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Neo4j::Driver
|
2
|
+
module Internal
|
3
|
+
module Async
|
4
|
+
module Pool
|
5
|
+
class ChannelPool < ConnectionPool
|
6
|
+
def initialize(limit: nil, acquisition_timeout: nil, &block)
|
7
|
+
super(size: limit, timeout: acquisition_timeout, &block)
|
8
|
+
@available = TimedStack.new(@size, &block)
|
9
|
+
end
|
10
|
+
|
11
|
+
def acquire(options = {})
|
12
|
+
@available.pop(options[:timeout] || @timeout)
|
13
|
+
end
|
14
|
+
|
15
|
+
def release(resource)
|
16
|
+
@available.push(resource)
|
17
|
+
nil
|
18
|
+
end
|
19
|
+
|
20
|
+
def close
|
21
|
+
@available.shutdown(&:close)
|
22
|
+
end
|
23
|
+
|
24
|
+
def busy?
|
25
|
+
@available.any_resource_busy?
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
module Neo4j::Driver
|
2
|
+
module Internal
|
3
|
+
module Async
|
4
|
+
module Pool
|
5
|
+
class ChannelTracker
|
6
|
+
attr_reader :lock, :read, :write, :address_to_in_use_channel_count, :address_to_idle_channel_count, :log,
|
7
|
+
:metrics_listener, :close_listener, :all_channels
|
8
|
+
|
9
|
+
def initialize(metrics_listener, logger, **options)
|
10
|
+
@metrics_listener = metrics_listener
|
11
|
+
@log = logger
|
12
|
+
@all_channels = options[:channels]
|
13
|
+
@lock = Concurrent::ReentrantReadWriteLock.new
|
14
|
+
@close_listener = method(:channel_closed)
|
15
|
+
end
|
16
|
+
|
17
|
+
def channel_released(channel)
|
18
|
+
@lock.with_write_lock do
|
19
|
+
decrement_in_use(channel)
|
20
|
+
increment_idle(channel)
|
21
|
+
channel.close_future.add_listener(close_listener)
|
22
|
+
end
|
23
|
+
|
24
|
+
log.debug("Channel [0x#{channel.id}] acquired from the pool. Local address: #{channel.local_address}, remote address: #{channel.remote_address}")
|
25
|
+
end
|
26
|
+
|
27
|
+
def channel_created(channel, creating_event = nil)
|
28
|
+
if creating_event.nil?
|
29
|
+
raise Neo4j::Driver::Exceptions::IllegalStateException.new('Untraceable channel created.')
|
30
|
+
else
|
31
|
+
# when it is created, we count it as idle as it has not been acquired out of the pool
|
32
|
+
do_in_write_lock(->() { increment_idle(channel) })
|
33
|
+
|
34
|
+
metrics_listener.after_created(Connection::ChannelAttributes.pool_id(channel), creating_event)
|
35
|
+
all_channels.add(channel)
|
36
|
+
log.debug( "Channel [0x#{channel.id}] created. Local address: #{channel.local_address}, remote address: #{channel.remote_address}")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def channel_creating(pool_id)
|
41
|
+
creating_event = metrics_listener.create_listener_event
|
42
|
+
metrics_listener.before_creating(pool_id, creating_event)
|
43
|
+
creating_event
|
44
|
+
end
|
45
|
+
|
46
|
+
def channel_failed_to_create(pool_id)
|
47
|
+
metrics_listener.after_failed_to_create(pool_id)
|
48
|
+
end
|
49
|
+
|
50
|
+
def channel_closed(channel)
|
51
|
+
do_in_write_lock(-> () { decrement_idle(channel) })
|
52
|
+
metrics_listener.after_closed(Connection::ChannelAttributes.pool_id(channel))
|
53
|
+
end
|
54
|
+
|
55
|
+
def in_use_channel_count(address)
|
56
|
+
retrieve_in_read_lock(-> () { address_to_in_use_channel_count.get_or_default(address, 0) })
|
57
|
+
end
|
58
|
+
|
59
|
+
def idle_channel_count(address)
|
60
|
+
retrieve_in_read_lock(-> () { address_to_idle_channel_count.get_or_default(address, 0) })
|
61
|
+
end
|
62
|
+
|
63
|
+
def prepare_to_close_channels
|
64
|
+
all_channels.each do |channel|
|
65
|
+
protocol = Messaging::BoltProtocol.for_channel(channel)
|
66
|
+
begin
|
67
|
+
protocol.prepare_to_close_channel(channel)
|
68
|
+
rescue Exception => e
|
69
|
+
# only logging it
|
70
|
+
log.debug( "Failed to prepare to close Channel #{channel} due to error #{e.get_message}. It is safe to ignore this error as the channel will be closed despite if it is successfully prepared to close or not.")
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def increment_in_use(channel)
|
79
|
+
increment(channel, address_to_in_use_channel_count)
|
80
|
+
end
|
81
|
+
|
82
|
+
def decrement_in_use(channel)
|
83
|
+
address = Connection::ChannelAttributes.server_address(channel)
|
84
|
+
|
85
|
+
unless address_to_in_use_channel_count.contains_key(address)
|
86
|
+
raise Neo4j::Driver::Exceptions::IllegalStateException.new("No count exists for address '#{address}' in the 'in use' count")
|
87
|
+
end
|
88
|
+
|
89
|
+
count = address_to_in_use_channel_count.get(address)
|
90
|
+
address_to_in_use_channel_count.put(address, count - 1)
|
91
|
+
end
|
92
|
+
|
93
|
+
def increment_idle(channel)
|
94
|
+
increment(channel, address_to_idle_channel_count)
|
95
|
+
end
|
96
|
+
|
97
|
+
def decrement_idle(channel)
|
98
|
+
address = Connection::ChannelAttributes.server_address(channel)
|
99
|
+
|
100
|
+
unless address_to_idle_channel_count.contains_key(address)
|
101
|
+
raise Neo4j::Driver::Exceptions::IllegalStateException.new("No count exists for address '#{address}' in the 'idle' count")
|
102
|
+
end
|
103
|
+
|
104
|
+
count = address_to_idle_channel_count.get(address)
|
105
|
+
address_to_idle_channel_count.put(address, count - 1)
|
106
|
+
end
|
107
|
+
|
108
|
+
def increment(channel, count_map)
|
109
|
+
address = Connection::ChannelAttributes.server_address(channel)
|
110
|
+
count = count_map.compute_if_absent(address, -> (k) { 0 })
|
111
|
+
count_map.put(address, count + 1)
|
112
|
+
end
|
113
|
+
|
114
|
+
def do_in_write_lock(work)
|
115
|
+
begin
|
116
|
+
write.lock
|
117
|
+
work.run
|
118
|
+
ensure
|
119
|
+
write.unlock
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def retrieve_in_read_lock(work)
|
124
|
+
begin
|
125
|
+
read.lock
|
126
|
+
work.get
|
127
|
+
ensure
|
128
|
+
read.unlock
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
@@ -0,0 +1,156 @@
|
|
1
|
+
module Neo4j::Driver
|
2
|
+
module Internal
|
3
|
+
module Async
|
4
|
+
module Pool
|
5
|
+
class ConnectionPoolImpl
|
6
|
+
def initialize(connector, settings, logger)
|
7
|
+
@connector = connector
|
8
|
+
@settings = settings
|
9
|
+
@log = logger
|
10
|
+
@address_to_pool_lock = Concurrent::ReentrantReadWriteLock.new
|
11
|
+
@address_to_pool = {}
|
12
|
+
@closed = Concurrent::AtomicBoolean.new
|
13
|
+
end
|
14
|
+
|
15
|
+
def acquire(address)
|
16
|
+
@log.debug("Acquiring a connection from pool towards #{address}")
|
17
|
+
|
18
|
+
assert_not_closed
|
19
|
+
pool = get_or_create_pool(address)
|
20
|
+
|
21
|
+
begin
|
22
|
+
channel = pool.acquire
|
23
|
+
@log.debug { "Channel #{channel.object_id} acquired" }
|
24
|
+
rescue => error
|
25
|
+
process_acquisition_error(pool, address, error)
|
26
|
+
end
|
27
|
+
assert_not_closed(address, channel, pool)
|
28
|
+
NetworkConnection.new(channel, pool, @log) { remove(pool) }
|
29
|
+
end
|
30
|
+
|
31
|
+
def retain_all(addresses_to_retain)
|
32
|
+
@address_to_pool_lock.with_write_lock do
|
33
|
+
@address_to_pool.each do |address, pool|
|
34
|
+
unless addresses_to_retain.include?(address)
|
35
|
+
unless pool.busy?
|
36
|
+
# address is not present in updated routing table and has no active connections
|
37
|
+
# it's now safe to terminate corresponding connection pool and forget about it
|
38
|
+
@address_to_pool.delete(address)
|
39
|
+
if pool
|
40
|
+
@log.info("Closing connection pool towards #{address}, it has no active connections and is not in the routing table registry.")
|
41
|
+
close_pool_in_background(address, pool)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def remove(pool)
|
50
|
+
@address_to_pool_lock.with_write_lock do
|
51
|
+
@address_to_pool.each { |address, value| @address_to_pool.delete(address) if value == pool }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def in_use_connections(address)
|
56
|
+
@address_to_pool[address]&.size || 0
|
57
|
+
# @netty_channel_tracker.in_use_channel_count(address)
|
58
|
+
end
|
59
|
+
|
60
|
+
def idle_connections(address)
|
61
|
+
@netty_channel_tracker.idle_channel_count(address)
|
62
|
+
end
|
63
|
+
|
64
|
+
def close
|
65
|
+
if @closed.make_true
|
66
|
+
@address_to_pool_lock.with_write_lock do
|
67
|
+
# We can only shutdown event loop group when all netty pools are fully closed,
|
68
|
+
# otherwise the netty pools might missing threads (from event loop group) to execute clean ups.
|
69
|
+
close_all_pools
|
70
|
+
@address_to_pool.clear
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def open?(address)
|
76
|
+
@address_to_pool_lock.with_read_lock { @address_to_pool.key?(address) }
|
77
|
+
end
|
78
|
+
|
79
|
+
def to_string
|
80
|
+
@address_to_pool_lock.with_read_lock { "ConnectionPoolImpl{ pools=#{@address_to_pool}}" }
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def process_acquisition_error(pool, server_address, error)
|
86
|
+
if error.is_a?(ConnectionPool::TimeoutError)
|
87
|
+
# NettyChannelPool returns future failed with TimeoutException if acquire operation takes more than
|
88
|
+
# configured time, translate this exception to a prettier one and re-throw
|
89
|
+
raise Neo4j::Driver::Exceptions::ClientException.new("Unable to acquire connection from the pool within configured maximum time of #{@settings.connection_acquisition_timeout.inspect}")
|
90
|
+
# elsif pool.closed?
|
91
|
+
# There is a race condition where a thread tries to acquire a connection while the pool is closed by another concurrent thread.
|
92
|
+
# Treat as failed to obtain connection for a direct driver. For a routing driver, this error should be retried.
|
93
|
+
# raise Neo4j::Driver::Exceptions::ServiceUnavailableException, "Connection pool for server #{server_address} is closed while acquiring a connection."
|
94
|
+
else
|
95
|
+
# some unknown error happened during connection acquisition, propagate it
|
96
|
+
raise error
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def assert_not_closed(address = nil, channel = nil, pool = nil)
|
101
|
+
if @closed.true?
|
102
|
+
if address
|
103
|
+
pool.release(channel)
|
104
|
+
close_pool_in_background(address, pool)
|
105
|
+
@address_to_pool_lock.with_write_lock { @address_to_pool.delete(address) }
|
106
|
+
assert_not_closed
|
107
|
+
end
|
108
|
+
raise Exceptions::IllegalStateException, Spi::ConnectionPool::CONNECTION_POOL_CLOSED_ERROR_MESSAGE
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# for testing only
|
113
|
+
protected def pool(address)
|
114
|
+
@address_to_pool_lock.with_read_lock { @address_to_pool[address] }
|
115
|
+
end
|
116
|
+
|
117
|
+
def new_pool(address)
|
118
|
+
ChannelPool.new(limit: @settings.max_connection_pool_size, acquisition_timeout: @settings.connection_acquisition_timeout) { Channel.new(address, @connector, @log) }
|
119
|
+
end
|
120
|
+
|
121
|
+
def get_or_create_pool(address)
|
122
|
+
@address_to_pool_lock.with_read_lock { @address_to_pool[address] } ||
|
123
|
+
@address_to_pool_lock.with_write_lock do
|
124
|
+
new_pool(address)&.tap do |pool|
|
125
|
+
# before the connection pool is added I can add the metrics for the pool.
|
126
|
+
# @metrics_listener.put_pool_metrics(pool.object_id, address, self)
|
127
|
+
@address_to_pool[address] = pool
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def close_pool(pool)
|
133
|
+
pool.close
|
134
|
+
end
|
135
|
+
|
136
|
+
def close_pool_in_background(address, pool)
|
137
|
+
Async do
|
138
|
+
# Close in the background
|
139
|
+
close_pool(pool)
|
140
|
+
rescue => error
|
141
|
+
@log.warn("An error occurred while closing connection pool towards #{address}.", error)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def close_all_pools
|
146
|
+
@address_to_pool.map do |address, pool|
|
147
|
+
@log.info("Closing connection pool towards #{address}")
|
148
|
+
# Wait for all pools to be closed.
|
149
|
+
close_pool(pool)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|