neo4j-ruby-driver 6.0.3.alpha.0 → 6.2.1.beta.2
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 +113 -411
- data/{ruby → lib}/neo4j/driver/access_mode.rb +2 -1
- data/lib/neo4j/driver/auth_token_managers.rb +31 -0
- data/lib/neo4j/driver/auth_tokens.rb +41 -0
- data/lib/neo4j/driver/auto_commit_retries_mode.rb +18 -0
- data/lib/neo4j/driver/bolt/bolt_version.rb +67 -0
- data/lib/neo4j/driver/bolt/connection.rb +1091 -0
- data/lib/neo4j/driver/bolt/handshake.rb +236 -0
- data/lib/neo4j/driver/bolt/message/failure.rb +139 -0
- data/lib/neo4j/driver/bolt/message/ignored.rb +27 -0
- data/lib/neo4j/driver/bolt/message/record.rb +30 -0
- data/lib/neo4j/driver/bolt/message/success.rb +34 -0
- data/lib/neo4j/driver/bolt/message.rb +112 -0
- data/lib/neo4j/driver/bolt/pool.rb +255 -0
- data/lib/neo4j/driver/bolt/protocol/base.rb +146 -0
- data/lib/neo4j/driver/bolt/protocol/v3.rb +43 -0
- data/lib/neo4j/driver/bolt/protocol/v4.rb +24 -0
- data/lib/neo4j/driver/bolt/protocol/v43.rb +28 -0
- data/lib/neo4j/driver/bolt/protocol/v44.rb +23 -0
- data/lib/neo4j/driver/bolt/protocol/v5.rb +27 -0
- data/lib/neo4j/driver/bolt/protocol/v51.rb +24 -0
- data/lib/neo4j/driver/bolt/protocol/v52.rb +28 -0
- data/lib/neo4j/driver/bolt/protocol/v53.rb +27 -0
- data/lib/neo4j/driver/bolt/protocol/v54.rb +14 -0
- data/lib/neo4j/driver/bolt/protocol/v55.rb +17 -0
- data/lib/neo4j/driver/bolt/protocol/v56.rb +14 -0
- data/lib/neo4j/driver/bolt/protocol/v57.rb +31 -0
- data/lib/neo4j/driver/bolt/protocol/v58.rb +15 -0
- data/lib/neo4j/driver/bolt/protocol/v6.rb +43 -0
- data/lib/neo4j/driver/bolt/protocol/v61.rb +21 -0
- data/lib/neo4j/driver/bolt/protocol_version_handler.rb +39 -0
- data/lib/neo4j/driver/bolt/record_buffer.rb +143 -0
- data/lib/neo4j/driver/bolt/stream_handler.rb +53 -0
- data/lib/neo4j/driver/bolt/tls_config.rb +129 -0
- data/lib/neo4j/driver/bolt/wire.rb +321 -0
- data/lib/neo4j/driver/bookmark.rb +15 -0
- data/lib/neo4j/driver/bookmark_managers.rb +39 -0
- data/lib/neo4j/driver/client_certificate.rb +19 -0
- data/lib/neo4j/driver/client_certificate_manager.rb +37 -0
- data/lib/neo4j/driver/client_certificate_managers.rb +15 -0
- data/lib/neo4j/driver/client_certificates.rb +14 -0
- data/lib/neo4j/driver/direct/connection_provider.rb +262 -0
- data/lib/neo4j/driver/driver.rb +268 -0
- data/lib/neo4j/driver/eager_result.rb +10 -0
- data/lib/neo4j/driver/exceptions/neo4j_exception.rb +16 -7
- data/lib/neo4j/driver/exceptions/no_such_record_exception.rb +1 -1
- data/lib/neo4j/driver/exceptions/protocol_exception.rb +0 -5
- data/lib/neo4j/driver/exceptions/security_retryable_exception.rb +14 -0
- data/lib/neo4j/driver/exceptions/transaction_terminated_exception.rb +13 -0
- data/lib/neo4j/driver/graph_database.rb +29 -0
- data/lib/neo4j/driver/internal/clock.rb +20 -0
- data/lib/neo4j/driver/internal/clock_adapter.rb +21 -0
- data/lib/neo4j/driver/internal/default_bookmark_manager.rb +54 -0
- data/lib/neo4j/driver/internal/deprecator.rb +9 -5
- data/lib/neo4j/driver/internal/driver_factory.rb +128 -0
- data/lib/neo4j/driver/internal/duration_normalizer.rb +14 -39
- data/lib/neo4j/driver/internal/extras.rb +23 -0
- data/lib/neo4j/driver/internal/home_db_cache.rb +57 -0
- data/lib/neo4j/driver/internal/internal_auth_token_manager.rb +37 -0
- data/lib/neo4j/driver/internal/metrics.rb +31 -0
- data/lib/neo4j/driver/internal/security/static_auth_token_manager.rb +25 -0
- data/lib/neo4j/driver/internal/validator.rb +16 -2
- data/lib/neo4j/driver/net.rb +29 -0
- data/lib/neo4j/driver/packstream/markers.rb +49 -0
- data/lib/neo4j/driver/packstream/packer.rb +335 -0
- data/lib/neo4j/driver/packstream/structure.rb +27 -0
- data/lib/neo4j/driver/packstream/unpacker.rb +170 -0
- data/lib/neo4j/driver/record.rb +43 -0
- data/lib/neo4j/driver/result.rb +282 -0
- data/lib/neo4j/driver/routing/load_balancer.rb +706 -0
- data/lib/neo4j/driver/routing/routed_connection.rb +132 -0
- data/lib/neo4j/driver/routing/routing_table.rb +127 -0
- data/lib/neo4j/driver/routing/server_address.rb +25 -0
- data/lib/neo4j/driver/routing_control.rb +13 -0
- data/lib/neo4j/driver/session.rb +577 -0
- data/lib/neo4j/driver/summary/database_info.rb +25 -0
- data/lib/neo4j/driver/summary/gql_notification.rb +38 -0
- data/lib/neo4j/driver/summary/gql_status_object.rb +35 -0
- data/lib/neo4j/driver/summary/notification.rb +46 -0
- data/lib/neo4j/driver/summary/plan.rb +23 -0
- data/lib/neo4j/driver/summary/profile.rb +28 -0
- data/lib/neo4j/driver/summary/query.rb +19 -0
- data/lib/neo4j/driver/summary/query_type.rb +5 -1
- data/lib/neo4j/driver/summary/result_summary.rb +215 -0
- data/lib/neo4j/driver/summary/server_info.rb +33 -0
- data/lib/neo4j/driver/summary/summary_counters.rb +72 -0
- data/lib/neo4j/driver/transaction.rb +344 -0
- data/lib/neo4j/driver/types/duration.rb +76 -0
- data/lib/neo4j/driver/types/entity.rb +40 -0
- data/lib/neo4j/driver/types/local_date_time.rb +77 -8
- data/lib/neo4j/driver/types/local_time.rb +50 -7
- data/lib/neo4j/driver/types/node.rb +18 -0
- data/lib/neo4j/driver/types/offset_time.rb +78 -7
- data/lib/neo4j/driver/types/path.rb +68 -0
- data/lib/neo4j/driver/types/point.rb +38 -18
- data/lib/neo4j/driver/types/relationship.rb +32 -0
- data/lib/neo4j/driver/types/temporal_value.rb +44 -0
- data/lib/neo4j/driver/types/unbound_relationship.rb +24 -0
- data/lib/neo4j/driver/types/unresolvable_zoned_date_time.rb +38 -0
- data/lib/neo4j/driver/types/unsupported_type.rb +25 -0
- data/lib/neo4j/driver/types/uuid.rb +29 -0
- data/{ruby → lib}/neo4j/driver/version.rb +1 -1
- data/lib/neo4j/driver.rb +15 -0
- data/lib/neo4j-ruby-driver_loader.rb +34 -20
- metadata +115 -441
- data/lib/neo4j/driver/internal/bolt_server_address.rb +0 -97
- data/lib/neo4j/driver/synchronizable.rb +0 -23
- data/lib/neo4j/driver/types/time.rb +0 -45
- data/ruby/neo4j/driver/auth_tokens.rb +0 -34
- data/ruby/neo4j/driver/bookmark.rb +0 -21
- data/ruby/neo4j/driver/config.rb +0 -89
- data/ruby/neo4j/driver/graph_database.rb +0 -78
- data/ruby/neo4j/driver/internal/async/connection/bolt_protocol_util.rb +0 -51
- data/ruby/neo4j/driver/internal/async/connection/bootstrap_factory.rb +0 -22
- data/ruby/neo4j/driver/internal/async/connection/channel_attributes.rb +0 -31
- data/ruby/neo4j/driver/internal/async/connection/channel_connected_listener.rb +0 -32
- data/ruby/neo4j/driver/internal/async/connection/channel_connector_impl.rb +0 -83
- data/ruby/neo4j/driver/internal/async/connection/channel_pipeline_builder_impl.rb +0 -22
- data/ruby/neo4j/driver/internal/async/connection/direct_connection.rb +0 -30
- data/ruby/neo4j/driver/internal/async/connection/event_loop_group_factory.rb +0 -83
- data/ruby/neo4j/driver/internal/async/connection/handshake_completed_listener.rb +0 -27
- data/ruby/neo4j/driver/internal/async/connection/handshake_handler.rb +0 -113
- data/ruby/neo4j/driver/internal/async/connection/netty_channel_initializer.rb +0 -57
- data/ruby/neo4j/driver/internal/async/connection/netty_domain_name_resolver.rb +0 -26
- data/ruby/neo4j/driver/internal/async/connection/netty_domain_name_resolver_group.rb +0 -19
- data/ruby/neo4j/driver/internal/async/connection/routing_connection.rb +0 -36
- data/ruby/neo4j/driver/internal/async/connection/stream.rb +0 -12
- data/ruby/neo4j/driver/internal/async/connection/stream_reader.rb +0 -16
- data/ruby/neo4j/driver/internal/async/connection_context.rb +0 -10
- data/ruby/neo4j/driver/internal/async/immutable_connection_context.rb +0 -24
- data/ruby/neo4j/driver/internal/async/inbound/byte_buf_input.rb +0 -30
- data/ruby/neo4j/driver/internal/async/inbound/channel_error_handler.rb +0 -77
- data/ruby/neo4j/driver/internal/async/inbound/chunk_decoder.rb +0 -41
- data/ruby/neo4j/driver/internal/async/inbound/connect_timeout_handler.rb +0 -32
- data/ruby/neo4j/driver/internal/async/inbound/connection_read_timeout_handler.rb +0 -17
- data/ruby/neo4j/driver/internal/async/inbound/inbound_message_dispatcher.rb +0 -171
- data/ruby/neo4j/driver/internal/async/inbound/inbound_message_handler.rb +0 -42
- data/ruby/neo4j/driver/internal/async/inbound/message_decoder.rb +0 -51
- data/ruby/neo4j/driver/internal/async/internal_async_session.rb +0 -92
- data/ruby/neo4j/driver/internal/async/internal_async_transaction.rb +0 -13
- data/ruby/neo4j/driver/internal/async/leak_logging_network_session.rb +0 -34
- data/ruby/neo4j/driver/internal/async/network_connection.rb +0 -194
- data/ruby/neo4j/driver/internal/async/network_session.rb +0 -150
- data/ruby/neo4j/driver/internal/async/outbound/chunk_aware_byte_buf_output.rb +0 -110
- data/ruby/neo4j/driver/internal/async/outbound/outbound_message_handler.rb +0 -39
- data/ruby/neo4j/driver/internal/async/pool/channel.rb +0 -66
- data/ruby/neo4j/driver/internal/async/pool/channel_pool.rb +0 -31
- data/ruby/neo4j/driver/internal/async/pool/channel_tracker.rb +0 -135
- data/ruby/neo4j/driver/internal/async/pool/connection_pool_impl.rb +0 -156
- data/ruby/neo4j/driver/internal/async/pool/netty_channel_health_checker.rb +0 -87
- data/ruby/neo4j/driver/internal/async/pool/netty_channel_pool.rb +0 -52
- data/ruby/neo4j/driver/internal/async/pool/network_connection_factory.rb +0 -21
- data/ruby/neo4j/driver/internal/async/pool/pool_settings.rb +0 -34
- data/ruby/neo4j/driver/internal/async/pool/timed_stack.rb +0 -15
- data/ruby/neo4j/driver/internal/async/result_cursors_holder.rb +0 -17
- data/ruby/neo4j/driver/internal/async/unmanaged_transaction.rb +0 -212
- data/ruby/neo4j/driver/internal/bookmark_holder.rb +0 -9
- data/ruby/neo4j/driver/internal/cluster/cluster_composition.rb +0 -48
- data/ruby/neo4j/driver/internal/cluster/cluster_composition_lookup_result.rb +0 -14
- data/ruby/neo4j/driver/internal/cluster/cluster_routing_table.rb +0 -122
- data/ruby/neo4j/driver/internal/cluster/identity_resolver.rb +0 -10
- data/ruby/neo4j/driver/internal/cluster/loadbalancing/least_connected_load_balancing_strategy.rb +0 -68
- data/ruby/neo4j/driver/internal/cluster/loadbalancing/load_balancer.rb +0 -125
- data/ruby/neo4j/driver/internal/cluster/loadbalancing/round_robin_array_index.rb +0 -13
- data/ruby/neo4j/driver/internal/cluster/multi_databases_routing_procedure_runner.rb +0 -31
- data/ruby/neo4j/driver/internal/cluster/rediscovery_impl.rb +0 -147
- data/ruby/neo4j/driver/internal/cluster/route_message_routing_procedure_runner.rb +0 -43
- data/ruby/neo4j/driver/internal/cluster/routing_context.rb +0 -77
- data/ruby/neo4j/driver/internal/cluster/routing_procedure_cluster_composition_provider.rb +0 -60
- data/ruby/neo4j/driver/internal/cluster/routing_procedure_response.rb +0 -35
- data/ruby/neo4j/driver/internal/cluster/routing_settings.rb +0 -24
- data/ruby/neo4j/driver/internal/cluster/routing_table_handler_impl.rb +0 -95
- data/ruby/neo4j/driver/internal/cluster/routing_table_registry_impl.rb +0 -121
- data/ruby/neo4j/driver/internal/cluster/single_database_routing_procedure_runner.rb +0 -73
- data/ruby/neo4j/driver/internal/connection_settings.rb +0 -16
- data/ruby/neo4j/driver/internal/cursor/async_result_cursor_impl.rb +0 -55
- data/ruby/neo4j/driver/internal/cursor/async_result_cursor_only_factory.rb +0 -24
- data/ruby/neo4j/driver/internal/cursor/disposable_async_result_cursor.rb +0 -61
- data/ruby/neo4j/driver/internal/cursor/result_cursor_factory_impl.rb +0 -24
- data/ruby/neo4j/driver/internal/cursor/rx_result_cursor_impl.rb +0 -110
- data/ruby/neo4j/driver/internal/database_name_util.rb +0 -37
- data/ruby/neo4j/driver/internal/default_bookmark_holder.rb +0 -9
- data/ruby/neo4j/driver/internal/default_domain_name_resolver.rb +0 -11
- data/ruby/neo4j/driver/internal/direct_connection_provider.rb +0 -40
- data/ruby/neo4j/driver/internal/driver_factory.rb +0 -126
- data/ruby/neo4j/driver/internal/eager_result_value.rb +0 -5
- data/ruby/neo4j/driver/internal/handlers/begin_tx_response_handler.rb +0 -20
- data/ruby/neo4j/driver/internal/handlers/channel_releasing_reset_response_handler.rb +0 -30
- data/ruby/neo4j/driver/internal/handlers/commit_tx_response_handler.rb +0 -23
- data/ruby/neo4j/driver/internal/handlers/hello_response_handler.rb +0 -65
- data/ruby/neo4j/driver/internal/handlers/init_response_handler.rb +0 -34
- data/ruby/neo4j/driver/internal/handlers/legacy_pull_all_response_handler.rb +0 -199
- data/ruby/neo4j/driver/internal/handlers/no_op_response_handler.rb +0 -16
- data/ruby/neo4j/driver/internal/handlers/ping_response_handler.rb +0 -29
- data/ruby/neo4j/driver/internal/handlers/pull_handlers.rb +0 -32
- data/ruby/neo4j/driver/internal/handlers/pulln/auto_pull_response_handler.rb +0 -169
- data/ruby/neo4j/driver/internal/handlers/pulln/basic_pull_response_handler.rb +0 -298
- data/ruby/neo4j/driver/internal/handlers/pulln/fetch_size_util.rb +0 -20
- data/ruby/neo4j/driver/internal/handlers/reset_response_handler.rb +0 -34
- data/ruby/neo4j/driver/internal/handlers/rollback_tx_response_handler.rb +0 -25
- data/ruby/neo4j/driver/internal/handlers/route_message_response_handler.rb +0 -21
- data/ruby/neo4j/driver/internal/handlers/routing_response_handler.rb +0 -79
- data/ruby/neo4j/driver/internal/handlers/run_response_handler.rb +0 -38
- data/ruby/neo4j/driver/internal/handlers/session_pull_response_completion_listener.rb +0 -34
- data/ruby/neo4j/driver/internal/handlers/transaction_pull_response_completion_listener.rb +0 -20
- data/ruby/neo4j/driver/internal/impersonation_util.rb +0 -22
- data/ruby/neo4j/driver/internal/internal_bookmark.rb +0 -9
- data/ruby/neo4j/driver/internal/internal_database_name.rb +0 -9
- data/ruby/neo4j/driver/internal/internal_driver.rb +0 -83
- data/ruby/neo4j/driver/internal/internal_entity.rb +0 -21
- data/ruby/neo4j/driver/internal/internal_node.rb +0 -21
- data/ruby/neo4j/driver/internal/internal_pair.rb +0 -9
- data/ruby/neo4j/driver/internal/internal_path.rb +0 -35
- data/ruby/neo4j/driver/internal/internal_point2_d.rb +0 -9
- data/ruby/neo4j/driver/internal/internal_point3_d.rb +0 -6
- data/ruby/neo4j/driver/internal/internal_record.rb +0 -27
- data/ruby/neo4j/driver/internal/internal_relationship.rb +0 -27
- data/ruby/neo4j/driver/internal/internal_result.rb +0 -49
- data/ruby/neo4j/driver/internal/internal_session.rb +0 -91
- data/ruby/neo4j/driver/internal/internal_transaction.rb +0 -48
- data/ruby/neo4j/driver/internal/logging/channel_activity_logger.rb +0 -29
- data/ruby/neo4j/driver/internal/logging/channel_error_logger.rb +0 -17
- data/ruby/neo4j/driver/internal/logging/prefixed_logger.rb +0 -19
- data/ruby/neo4j/driver/internal/logging/reformatted_logger.rb +0 -17
- data/ruby/neo4j/driver/internal/messaging/abstract_message_writer.rb +0 -23
- data/ruby/neo4j/driver/internal/messaging/bolt_protocol.rb +0 -32
- data/ruby/neo4j/driver/internal/messaging/bolt_protocol_version.rb +0 -48
- data/ruby/neo4j/driver/internal/messaging/common/common_message_reader.rb +0 -51
- data/ruby/neo4j/driver/internal/messaging/common/common_value.rb +0 -33
- data/ruby/neo4j/driver/internal/messaging/common/common_value_packer.rb +0 -104
- data/ruby/neo4j/driver/internal/messaging/common/common_value_unpacker.rb +0 -256
- data/ruby/neo4j/driver/internal/messaging/encode/begin_message_encoder.rb +0 -15
- data/ruby/neo4j/driver/internal/messaging/encode/commit_message_encoder.rb +0 -14
- data/ruby/neo4j/driver/internal/messaging/encode/discard_all_message_encoder.rb +0 -14
- data/ruby/neo4j/driver/internal/messaging/encode/discard_message_encoder.rb +0 -15
- data/ruby/neo4j/driver/internal/messaging/encode/goodbye_message_encoder.rb +0 -14
- data/ruby/neo4j/driver/internal/messaging/encode/hello_message_encoder.rb +0 -15
- data/ruby/neo4j/driver/internal/messaging/encode/init_message_encoder.rb +0 -16
- data/ruby/neo4j/driver/internal/messaging/encode/logoff_message_encoder.rb +0 -14
- data/ruby/neo4j/driver/internal/messaging/encode/logon_message_encoder.rb +0 -15
- data/ruby/neo4j/driver/internal/messaging/encode/pull_all_message_encoder.rb +0 -14
- data/ruby/neo4j/driver/internal/messaging/encode/pull_message_encoder.rb +0 -15
- data/ruby/neo4j/driver/internal/messaging/encode/reset_message_encoder.rb +0 -14
- data/ruby/neo4j/driver/internal/messaging/encode/rollback_message_encoder.rb +0 -14
- data/ruby/neo4j/driver/internal/messaging/encode/route_message_encoder.rb +0 -24
- data/ruby/neo4j/driver/internal/messaging/encode/route_v44_message_encoder.rb +0 -22
- data/ruby/neo4j/driver/internal/messaging/encode/run_message_encoder.rb +0 -16
- data/ruby/neo4j/driver/internal/messaging/encode/run_with_metadata_message_encoder.rb +0 -17
- data/ruby/neo4j/driver/internal/messaging/request/abstract_streaming_message.rb +0 -25
- data/ruby/neo4j/driver/internal/messaging/request/begin_message.rb +0 -25
- data/ruby/neo4j/driver/internal/messaging/request/commit_message.rb +0 -20
- data/ruby/neo4j/driver/internal/messaging/request/discard_all_message.rb +0 -20
- data/ruby/neo4j/driver/internal/messaging/request/discard_message.rb +0 -23
- data/ruby/neo4j/driver/internal/messaging/request/goodbye_message.rb +0 -20
- data/ruby/neo4j/driver/internal/messaging/request/hello_message.rb +0 -30
- data/ruby/neo4j/driver/internal/messaging/request/init_message.rb +0 -19
- data/ruby/neo4j/driver/internal/messaging/request/logoff_message.rb +0 -13
- data/ruby/neo4j/driver/internal/messaging/request/logon_message.rb +0 -13
- data/ruby/neo4j/driver/internal/messaging/request/message_with_metadata.rb +0 -17
- data/ruby/neo4j/driver/internal/messaging/request/multi_database_util.rb +0 -26
- data/ruby/neo4j/driver/internal/messaging/request/pull_all_message.rb +0 -23
- data/ruby/neo4j/driver/internal/messaging/request/pull_message.rb +0 -22
- data/ruby/neo4j/driver/internal/messaging/request/reset_message.rb +0 -32
- data/ruby/neo4j/driver/internal/messaging/request/rollback_message.rb +0 -20
- data/ruby/neo4j/driver/internal/messaging/request/route_message.rb +0 -28
- data/ruby/neo4j/driver/internal/messaging/request/run_message.rb +0 -23
- data/ruby/neo4j/driver/internal/messaging/request/run_with_metadata_message.rb +0 -49
- data/ruby/neo4j/driver/internal/messaging/request/transaction_metadata_builder.rb +0 -24
- data/ruby/neo4j/driver/internal/messaging/response/failure_message.rb +0 -40
- data/ruby/neo4j/driver/internal/messaging/response/ignored_message.rb +0 -29
- data/ruby/neo4j/driver/internal/messaging/response/record_message.rb +0 -33
- data/ruby/neo4j/driver/internal/messaging/response/success_message.rb +0 -34
- data/ruby/neo4j/driver/internal/messaging/v3/bolt_protocol_v3.rb +0 -82
- data/ruby/neo4j/driver/internal/messaging/v3/message_format_v3.rb +0 -17
- data/ruby/neo4j/driver/internal/messaging/v3/message_writer_v3.rb +0 -27
- data/ruby/neo4j/driver/internal/messaging/v4/bolt_protocol_v4.rb +0 -29
- data/ruby/neo4j/driver/internal/messaging/v4/message_format_v4.rb +0 -13
- data/ruby/neo4j/driver/internal/messaging/v4/message_writer_v4.rb +0 -17
- data/ruby/neo4j/driver/internal/messaging/v41/bolt_protocol_v41.rb +0 -25
- data/ruby/neo4j/driver/internal/messaging/v42/bolt_protocol_v42.rb +0 -13
- data/ruby/neo4j/driver/internal/messaging/v43/bolt_protocol_v43.rb +0 -19
- data/ruby/neo4j/driver/internal/messaging/v43/message_format_v43.rb +0 -14
- data/ruby/neo4j/driver/internal/messaging/v43/message_writer_v43.rb +0 -20
- data/ruby/neo4j/driver/internal/messaging/v44/bolt_protocol_v44.rb +0 -17
- data/ruby/neo4j/driver/internal/messaging/v44/message_format_v44.rb +0 -14
- data/ruby/neo4j/driver/internal/messaging/v44/message_writer_v44.rb +0 -15
- data/ruby/neo4j/driver/internal/messaging/v5/bolt_protocol_v5.rb +0 -21
- data/ruby/neo4j/driver/internal/messaging/v5/message_format_v5.rb +0 -18
- data/ruby/neo4j/driver/internal/messaging/v5/value_unpacker_v5.rb +0 -17
- data/ruby/neo4j/driver/internal/messaging/v51/bolt_protocol_v51.rb +0 -40
- data/ruby/neo4j/driver/internal/messaging/v51/message_format_v51.rb +0 -14
- data/ruby/neo4j/driver/internal/messaging/v51/message_writer_v51.rb +0 -17
- data/ruby/neo4j/driver/internal/metrics/connection_pool_metrics_listener.rb +0 -34
- data/ruby/neo4j/driver/internal/metrics/internal_abstract_metrics.rb +0 -46
- data/ruby/neo4j/driver/internal/metrics/internal_connection_pool_metrics.rb +0 -105
- data/ruby/neo4j/driver/internal/metrics/internal_metrics.rb +0 -82
- data/ruby/neo4j/driver/internal/metrics/internal_metrics_provider.rb +0 -18
- data/ruby/neo4j/driver/internal/metrics/listener_event.rb +0 -17
- data/ruby/neo4j/driver/internal/metrics/metrics_provider.rb +0 -24
- data/ruby/neo4j/driver/internal/metrics/time_recorder_listener_event.rb +0 -15
- data/ruby/neo4j/driver/internal/packstream/byte_array_incompatible_packer.rb +0 -12
- data/ruby/neo4j/driver/internal/packstream/pack_input.rb +0 -47
- data/ruby/neo4j/driver/internal/packstream/pack_output.rb +0 -39
- data/ruby/neo4j/driver/internal/packstream/pack_stream.rb +0 -324
- data/ruby/neo4j/driver/internal/packstream/pack_type.rb +0 -17
- data/ruby/neo4j/driver/internal/read_only_bookmark_holder.rb +0 -13
- data/ruby/neo4j/driver/internal/resolved_bolt_server_address.rb +0 -35
- data/ruby/neo4j/driver/internal/retry/exponential_backoff_retry_logic.rb +0 -150
- data/ruby/neo4j/driver/internal/revocation_strategy.rb +0 -19
- data/ruby/neo4j/driver/internal/scheme.rb +0 -32
- data/ruby/neo4j/driver/internal/security/internal_auth_token.rb +0 -15
- data/ruby/neo4j/driver/internal/security/security_plan_impl.rb +0 -48
- data/ruby/neo4j/driver/internal/security_setting.rb +0 -66
- data/ruby/neo4j/driver/internal/session_factory_impl.rb +0 -32
- data/ruby/neo4j/driver/internal/spi/connection.rb +0 -19
- data/ruby/neo4j/driver/internal/spi/connection_pool.rb +0 -9
- data/ruby/neo4j/driver/internal/spi/response_handler.rb +0 -23
- data/ruby/neo4j/driver/internal/summary/internal_database_info.rb +0 -7
- data/ruby/neo4j/driver/internal/summary/internal_input_position.rb +0 -11
- data/ruby/neo4j/driver/internal/summary/internal_notification.rb +0 -16
- data/ruby/neo4j/driver/internal/summary/internal_plan.rb +0 -41
- data/ruby/neo4j/driver/internal/summary/internal_profiled_plan.rb +0 -32
- data/ruby/neo4j/driver/internal/summary/internal_result_summary.rb +0 -33
- data/ruby/neo4j/driver/internal/summary/internal_server_info.rb +0 -6
- data/ruby/neo4j/driver/internal/summary/internal_summary_counters.rb +0 -18
- data/ruby/neo4j/driver/internal/svm/netty_substitutions.rb +0 -196
- data/ruby/neo4j/driver/internal/svm/z_lib_substitutions.rb +0 -21
- data/ruby/neo4j/driver/internal/util/certificate_tool.rb +0 -65
- data/ruby/neo4j/driver/internal/util/clock.rb +0 -29
- data/ruby/neo4j/driver/internal/util/error_util.rb +0 -104
- data/ruby/neo4j/driver/internal/util/extract.rb +0 -123
- data/ruby/neo4j/driver/internal/util/format.rb +0 -39
- data/ruby/neo4j/driver/internal/util/futures.rb +0 -99
- data/ruby/neo4j/driver/internal/util/iterables.rb +0 -35
- data/ruby/neo4j/driver/internal/util/lock_util.rb +0 -23
- data/ruby/neo4j/driver/internal/util/metadata_extractor.rb +0 -101
- data/ruby/neo4j/driver/internal/util/mutex.rb +0 -9
- data/ruby/neo4j/driver/internal/util/preconditions.rb +0 -16
- data/ruby/neo4j/driver/internal/util/result_holder.rb +0 -72
- data/ruby/neo4j/driver/internal/util/server_version.rb +0 -60
- data/ruby/neo4j/driver/logging1.rb +0 -51
- data/ruby/neo4j/driver/net/server_address.rb +0 -9
- data/ruby/neo4j/driver/query.rb +0 -48
- data/ruby/neo4j/driver/records.rb +0 -13
- data/ruby/neo4j/driver/transaction_config.rb +0 -50
- data/ruby/neo4j/driver/values.rb +0 -26
- data/ruby/neo4j/driver.rb +0 -30
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Neo4j
|
|
4
|
+
module Driver
|
|
5
|
+
module Bolt
|
|
6
|
+
module Protocol
|
|
7
|
+
# Bolt 5.7. FAILURE switches to a GQL-flavoured map: the legacy
|
|
8
|
+
# `code` key is renamed to `neo4j_code` (optional, defaults to
|
|
9
|
+
# "N/A"), and new keys appear (`gql_status`, `description`,
|
|
10
|
+
# `diagnostic_record`, recursive `cause`). The driver's
|
|
11
|
+
# exception classifier keys off `:code`, so we alias
|
|
12
|
+
# `neo4j_code → code` here. The other GQL fields ride along in
|
|
13
|
+
# the metadata for any caller that wants them.
|
|
14
|
+
#
|
|
15
|
+
# 5.7+ is also where HandshakeManifestV1 negotiation becomes
|
|
16
|
+
# mandatory on the server side; that's handled in Bolt::Handshake,
|
|
17
|
+
# not here.
|
|
18
|
+
class V57 < V56
|
|
19
|
+
def customize_hydration(unpacker)
|
|
20
|
+
super
|
|
21
|
+
unpacker.register_hydration_handler(Message::FAILURE) do |fields|
|
|
22
|
+
meta = fields[0] || {}
|
|
23
|
+
meta = meta.merge(code: meta[:neo4j_code]) if meta[:neo4j_code]
|
|
24
|
+
Message::Failure.new(meta)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Neo4j
|
|
4
|
+
module Driver
|
|
5
|
+
module Bolt
|
|
6
|
+
module Protocol
|
|
7
|
+
# Bolt 5.8. Wire-identical to 5.7 from the client's perspective;
|
|
8
|
+
# the version bump only flags additional server capabilities
|
|
9
|
+
# negotiated through the manifest's capabilities bitmask.
|
|
10
|
+
class V58 < V57
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Neo4j
|
|
4
|
+
module Driver
|
|
5
|
+
module Bolt
|
|
6
|
+
module Protocol
|
|
7
|
+
# Bolt 6.0. HELLO / LOGON / TELEMETRY shapes are unchanged vs
|
|
8
|
+
# 5.8; the major bump exists to (a) gate the manifest as the
|
|
9
|
+
# only supported negotiation path and (b) introduce two new
|
|
10
|
+
# server-pushed struct types in result records:
|
|
11
|
+
# - VECTOR 0x56 — packed numeric array; 2 fields
|
|
12
|
+
# (element-type byte, raw bytes).
|
|
13
|
+
# - UNSUPPORTED 0x3F — forward-compat marker; 4 fields
|
|
14
|
+
# (name, min_major, min_minor, extra-map whose
|
|
15
|
+
# optional `message` key carries a server note).
|
|
16
|
+
#
|
|
17
|
+
# UNSUPPORTED hydrates to Types::UnsupportedType (Feature:API:Type.
|
|
18
|
+
# UnsupportedType). VECTOR stays a plain hash — Feature:API:Type.Vector
|
|
19
|
+
# is unimplemented, so the goal there is still just "don't crash at
|
|
20
|
+
# hydration" until there's a public API to wire it to.
|
|
21
|
+
class V6 < V58
|
|
22
|
+
VECTOR_SIGNATURE = 0x56
|
|
23
|
+
UNSUPPORTED_SIGNATURE = 0x3F
|
|
24
|
+
|
|
25
|
+
def customize_hydration(unpacker)
|
|
26
|
+
super
|
|
27
|
+
unpacker.register_hydration_handler(VECTOR_SIGNATURE) do |fields|
|
|
28
|
+
{ element_type: fields[0], bytes: fields[1] }
|
|
29
|
+
end
|
|
30
|
+
unpacker.register_hydration_handler(UNSUPPORTED_SIGNATURE) do |fields|
|
|
31
|
+
# fields[3] is an extra map (symbol keys) whose :message is the
|
|
32
|
+
# optional server note. Guard the type so a malformed/absent
|
|
33
|
+
# 4th field can't crash hydration — the whole point of a
|
|
34
|
+
# forward-compat marker is to survive the unexpected.
|
|
35
|
+
extra = fields[3].is_a?(Hash) ? fields[3] : {}
|
|
36
|
+
Types::UnsupportedType.new(fields[0], fields[1], fields[2], extra[:message])
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Neo4j
|
|
4
|
+
module Driver
|
|
5
|
+
module Bolt
|
|
6
|
+
module Protocol
|
|
7
|
+
# Bolt 6.1. HELLO / LOGON shapes are unchanged vs 6.0; the minor bump
|
|
8
|
+
# introduces PackStream V2, whose only new type is UUID — a top-level
|
|
9
|
+
# value (marker 0xE0 + 16 raw bytes), not a struct. This is the one
|
|
10
|
+
# protocol version that supports it: pack/unpack the UUID codec here
|
|
11
|
+
# instead of raising like Protocol::Base (Feature:API:Type.UUID,
|
|
12
|
+
# Feature:Bolt:6.1).
|
|
13
|
+
class V61 < V6
|
|
14
|
+
def pack_uuid(packer, value) = packer.pack_uuid_value(value)
|
|
15
|
+
|
|
16
|
+
def unpack_uuid(unpacker) = unpacker.unpack_uuid_value
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Neo4j
|
|
4
|
+
module Driver
|
|
5
|
+
module Bolt
|
|
6
|
+
# Factory for the per-minor protocol handler matching the
|
|
7
|
+
# negotiated wire version. Lookup is exact (`major.minor`)
|
|
8
|
+
# because the Bolt handshake only ever returns a version the
|
|
9
|
+
# server actually supports — so we don't need fuzzy matching.
|
|
10
|
+
class ProtocolVersionHandler
|
|
11
|
+
HANDLERS = {
|
|
12
|
+
BoltVersion::V6_1.to_i => Protocol::V61,
|
|
13
|
+
BoltVersion::V6_0.to_i => Protocol::V6,
|
|
14
|
+
BoltVersion::V5_8.to_i => Protocol::V58,
|
|
15
|
+
BoltVersion::V5_7.to_i => Protocol::V57,
|
|
16
|
+
BoltVersion::V5_6.to_i => Protocol::V56,
|
|
17
|
+
BoltVersion::V5_5.to_i => Protocol::V55,
|
|
18
|
+
BoltVersion::V5_4.to_i => Protocol::V54,
|
|
19
|
+
BoltVersion::V5_3.to_i => Protocol::V53,
|
|
20
|
+
BoltVersion::V5_2.to_i => Protocol::V52,
|
|
21
|
+
BoltVersion::V5_1.to_i => Protocol::V51,
|
|
22
|
+
BoltVersion::V5_0.to_i => Protocol::V5,
|
|
23
|
+
BoltVersion::V4_4.to_i => Protocol::V44,
|
|
24
|
+
BoltVersion::V4_3.to_i => Protocol::V43,
|
|
25
|
+
BoltVersion::V4_2.to_i => Protocol::V4,
|
|
26
|
+
BoltVersion::V3_0.to_i => Protocol::V3
|
|
27
|
+
}.freeze
|
|
28
|
+
|
|
29
|
+
def self.for_version(connection, version_int)
|
|
30
|
+
version = BoltVersion.from_int(version_int)
|
|
31
|
+
klass = HANDLERS[version.to_i] ||
|
|
32
|
+
raise(Exceptions::ServiceUnavailableException,
|
|
33
|
+
"Unsupported Bolt protocol version: #{version}")
|
|
34
|
+
klass.new(connection, version)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Neo4j
|
|
4
|
+
module Driver
|
|
5
|
+
module Bolt
|
|
6
|
+
# Record buffer for one streaming result, with a high/low watermark autopull
|
|
7
|
+
# policy. Sits between the connection's reader (producer) and the cursor
|
|
8
|
+
# (consumer), and unifies two things under one mutex + condition variable:
|
|
9
|
+
# the record queue *and* the batch's "has_more promise".
|
|
10
|
+
#
|
|
11
|
+
# Records are delivered incrementally — pushed the instant the reader decodes
|
|
12
|
+
# them — so the cursor sees record 1 without waiting for the whole batch. The
|
|
13
|
+
# batch's terminating SUCCESS resolves the promise (`batch_complete`), which
|
|
14
|
+
# says whether the server has more. The cursor drives flow control:
|
|
15
|
+
#
|
|
16
|
+
# * after each record, once drained to/below the low watermark, it checks
|
|
17
|
+
# the promise (`pull_ready?`, non-blocking) and, if fulfilled with
|
|
18
|
+
# has_more, issues the next `PULL {n: fetch_size}` — prefetch overlap;
|
|
19
|
+
# * when it drains the buffer empty mid-stream, it `await`s — one wait that
|
|
20
|
+
# wakes on *either* the next record *or* the promise resolving. That
|
|
21
|
+
# shared wait is the crux: mid-batch it wakes on a record (incremental
|
|
22
|
+
# delivery preserved), at batch-end it wakes on the promise (so it PULLs
|
|
23
|
+
# the next batch instead of blocking forever on a record that, the SUCCESS
|
|
24
|
+
# having no payload, will never come).
|
|
25
|
+
#
|
|
26
|
+
# The cursor is the sole writer (issues every PULL/DISCARD); the reader only
|
|
27
|
+
# ever fills. All sync primitives are stdlib + scheduler-aware, so a cursor
|
|
28
|
+
# running as a fiber under a host reactor yields rather than blocking the
|
|
29
|
+
# thread. See docs/unified-pipeline.md.
|
|
30
|
+
class RecordBuffer
|
|
31
|
+
attr_reader :fetch_size, :high_watermark, :low_watermark
|
|
32
|
+
|
|
33
|
+
def initialize(fetch_size:, high_watermark: nil, low_watermark: nil)
|
|
34
|
+
@fetch_size = fetch_size
|
|
35
|
+
# Defaults: refill under half of ~2 batches held. fetch_size -1 ("pull
|
|
36
|
+
# all in one batch") never paginates, so just size the watermarks for a
|
|
37
|
+
# steady single-batch handoff.
|
|
38
|
+
@high_watermark = high_watermark || (fetch_size.positive? ? fetch_size * 2 : 1000)
|
|
39
|
+
@low_watermark = low_watermark || [@high_watermark / 2, 1].max
|
|
40
|
+
@mutex = Mutex.new
|
|
41
|
+
@cv = ConditionVariable.new
|
|
42
|
+
@records = [] # incrementally filled by the reader, drained by the cursor
|
|
43
|
+
@has_more = true # server may have more records for this stream
|
|
44
|
+
@pull_in_flight = true # the first PULL is pipelined with RUN — promise unfulfilled
|
|
45
|
+
@ended = false # terminal SUCCESS/IGNORED seen → no more records
|
|
46
|
+
@error = nil # stream failed; re-raised to the cursor after buffered records
|
|
47
|
+
@summary = nil # terminating SUCCESS metadata
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# --- Producer (reader) side -----------------------------------------
|
|
51
|
+
|
|
52
|
+
# Append a decoded record and wake a cursor parked in #await. Never blocks
|
|
53
|
+
# (unbounded); the cursor's watermark bounds how much the server ships.
|
|
54
|
+
def push_record(record)
|
|
55
|
+
@mutex.synchronize do
|
|
56
|
+
@records.push(record)
|
|
57
|
+
@cv.broadcast
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# The current batch's terminal SUCCESS arrived — resolve the promise.
|
|
62
|
+
# `has_more` says whether to keep paging; either way no PULL is in flight,
|
|
63
|
+
# so the cursor may issue the next once it drains past the low watermark.
|
|
64
|
+
# Wake a cursor parked in #await waiting for exactly this.
|
|
65
|
+
def batch_complete(has_more:)
|
|
66
|
+
@mutex.synchronize do
|
|
67
|
+
@has_more = has_more
|
|
68
|
+
@pull_in_flight = false
|
|
69
|
+
@cv.broadcast
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Final batch (terminating SUCCESS without has_more, or IGNORED): stash the
|
|
74
|
+
# summary, mark ended, and wake the cursor.
|
|
75
|
+
def finish(summary = nil)
|
|
76
|
+
@mutex.synchronize do
|
|
77
|
+
@summary = summary
|
|
78
|
+
@ended = true
|
|
79
|
+
@has_more = false
|
|
80
|
+
@pull_in_flight = false
|
|
81
|
+
@cv.broadcast
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# The stream failed: arm the error the cursor re-raises *after* it drains
|
|
86
|
+
# the records already delivered (records that preceded the failure are
|
|
87
|
+
# valid), and wake it.
|
|
88
|
+
def fail(error)
|
|
89
|
+
@mutex.synchronize do
|
|
90
|
+
@error ||= error
|
|
91
|
+
@ended = true
|
|
92
|
+
@has_more = false
|
|
93
|
+
@pull_in_flight = false
|
|
94
|
+
@cv.broadcast
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# The terminating SUCCESS's metadata (nil until finished / on failure).
|
|
99
|
+
def summary = @mutex.synchronize { @summary }
|
|
100
|
+
|
|
101
|
+
# --- Consumer (cursor) side -----------------------------------------
|
|
102
|
+
|
|
103
|
+
# Non-blocking: the next buffered record, or :empty when none is buffered
|
|
104
|
+
# yet, or :ended once the stream is drained and terminal. Buffered records
|
|
105
|
+
# are handed out before a stream failure is raised (they preceded it).
|
|
106
|
+
def try_shift
|
|
107
|
+
@mutex.synchronize do
|
|
108
|
+
return @records.shift unless @records.empty?
|
|
109
|
+
raise @error if @error
|
|
110
|
+
|
|
111
|
+
@ended ? :ended : :empty
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Block (colorlessly) until there's something to re-evaluate: a record was
|
|
116
|
+
# delivered, the batch completed (promise resolved), or the stream
|
|
117
|
+
# ended/failed. Called only when the cursor has drained the buffer empty
|
|
118
|
+
# and a PULL is still outstanding (records coming, or its SUCCESS pending).
|
|
119
|
+
def await
|
|
120
|
+
@mutex.synchronize do
|
|
121
|
+
@cv.wait(@mutex) while @records.empty? && !@ended && @error.nil? && @pull_in_flight
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def empty? = @mutex.synchronize { @records.empty? }
|
|
126
|
+
def size = @mutex.synchronize { @records.size }
|
|
127
|
+
def ended? = @mutex.synchronize { @ended }
|
|
128
|
+
def has_more? = @mutex.synchronize { @has_more }
|
|
129
|
+
|
|
130
|
+
# --- Autopull policy (cursor side) ----------------------------------
|
|
131
|
+
|
|
132
|
+
# True when the cursor should issue the next PULL: the batch promise is
|
|
133
|
+
# fulfilled (none in flight) with has_more, and the buffer has drained
|
|
134
|
+
# to/below the low watermark.
|
|
135
|
+
def pull_ready? = @mutex.synchronize { @has_more && !@pull_in_flight && @records.size <= @low_watermark }
|
|
136
|
+
|
|
137
|
+
# The cursor issued the next PULL — the promise is unfulfilled again; don't
|
|
138
|
+
# issue another until this batch completes.
|
|
139
|
+
def note_pull_issued = @mutex.synchronize { @pull_in_flight = true }
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Neo4j
|
|
4
|
+
module Driver
|
|
5
|
+
module Bolt
|
|
6
|
+
# The wire handler for a streaming PULL/DISCARD: the dedicated reader routes
|
|
7
|
+
# the result's replies here, and it fills the result's RecordBuffer.
|
|
8
|
+
#
|
|
9
|
+
# Records are forwarded to the buffer incrementally — the instant each is
|
|
10
|
+
# decoded — so the cursor can read record 1 without waiting for the whole
|
|
11
|
+
# batch. The batch's terminating SUCCESS resolves the buffer's has_more
|
|
12
|
+
# promise (batch_complete) or ends the stream (finish); a FAILURE/IGNORED
|
|
13
|
+
# ends it too. The cursor consumes the buffer and drives follow-up PULLs —
|
|
14
|
+
# this side only fills.
|
|
15
|
+
#
|
|
16
|
+
# Runs in the reader thread; same visitor interface as @collector, so the
|
|
17
|
+
# wire dispatches to it identically.
|
|
18
|
+
class StreamHandler
|
|
19
|
+
def initialize(buffer)
|
|
20
|
+
@buffer = buffer
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def on_record(message)
|
|
24
|
+
@buffer.push_record(message)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def on_success(message)
|
|
28
|
+
if message.metadata[:has_more]
|
|
29
|
+
@buffer.batch_complete(has_more: true)
|
|
30
|
+
else
|
|
31
|
+
@buffer.finish(message.metadata)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def on_failure(message)
|
|
36
|
+
# Records already delivered stay readable; the cursor hits this error
|
|
37
|
+
# once it drains them (records that preceded the failure are valid).
|
|
38
|
+
@buffer.fail(message.to_exception)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def on_ignored(_message)
|
|
42
|
+
@buffer.finish
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Connection failure fan-out (see Connection#fan_out / Wire#fail_pending):
|
|
46
|
+
# surface the error to a cursor parked in the buffer.
|
|
47
|
+
def fail(error)
|
|
48
|
+
@buffer.fail(error)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Neo4j
|
|
4
|
+
module Driver
|
|
5
|
+
module Bolt
|
|
6
|
+
# Resolves the driver's URI scheme + user options into an
|
|
7
|
+
# OpenSSL::SSL::SSLContext, or nil for plaintext. Mirrors Java's
|
|
8
|
+
# TrustStrategy modes:
|
|
9
|
+
#
|
|
10
|
+
# :system_certificates — verify cert chain against system roots
|
|
11
|
+
# + verify hostname. Default for +s schemes.
|
|
12
|
+
# :all_certificates — encrypted but skip both checks. Default
|
|
13
|
+
# for +ssc schemes. Useful for self-signed
|
|
14
|
+
# dev servers; not for production.
|
|
15
|
+
# :custom_certificates — verify against an explicit CA bundle.
|
|
16
|
+
#
|
|
17
|
+
# Hostname verification rides along with peer verification — turning
|
|
18
|
+
# peer verification off (:all_certificates) implicitly turns off
|
|
19
|
+
# hostname check too, which is why +ssc exists.
|
|
20
|
+
class TlsConfig
|
|
21
|
+
# +s / +ssc are scheme-level encryption opt-in (mirrors
|
|
22
|
+
# Driver::ENCRYPTED_SCHEMES). +ssc additionally implies
|
|
23
|
+
# trust-all — the whole point of the "self-signed" suffix.
|
|
24
|
+
ENCRYPTED_SCHEMES = Driver::ENCRYPTED_SCHEMES
|
|
25
|
+
TRUST_ALL_SCHEMES = %w[bolt+ssc neo4j+ssc].freeze
|
|
26
|
+
|
|
27
|
+
def initialize(uri:, options:)
|
|
28
|
+
@uri = uri
|
|
29
|
+
@options = options
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# nil ⇒ plaintext socket; SSLContext ⇒ wrap.
|
|
33
|
+
def ssl_context
|
|
34
|
+
return nil unless encrypted?
|
|
35
|
+
|
|
36
|
+
ctx = OpenSSL::SSL::SSLContext.new
|
|
37
|
+
ctx.min_version = OpenSSL::SSL::TLS1_2_VERSION
|
|
38
|
+
apply_trust(ctx)
|
|
39
|
+
apply_client_certificate(ctx)
|
|
40
|
+
ctx
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def encrypted?
|
|
44
|
+
ENCRYPTED_SCHEMES.include?(@uri.scheme) || @options[:encryption] == true
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Whether the SSLSocket should verify the server hostname after
|
|
48
|
+
# the TLS handshake. False for the trust-all path; true otherwise.
|
|
49
|
+
def verify_hostname?
|
|
50
|
+
encrypted? && resolved_strategy != :all_certificates
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
# Mutual TLS (Feature:API:SSLClientCertificate): present the client
|
|
56
|
+
# certificate the manager currently holds. Polled per connection so a
|
|
57
|
+
# rotated certificate takes effect on the next connect; nil manager or
|
|
58
|
+
# nil certificate leaves the context client-cert-free.
|
|
59
|
+
def apply_client_certificate(ctx)
|
|
60
|
+
certificate = @options[:client_certificate_manager]&.get_client_certificate
|
|
61
|
+
return unless certificate
|
|
62
|
+
|
|
63
|
+
ctx.cert = OpenSSL::X509::Certificate.new(File.read(certificate.certfile))
|
|
64
|
+
# PKey.read handles both encrypted (password used) and unencrypted
|
|
65
|
+
# (password ignored) PEM keys. Pass "" rather than nil for a missing
|
|
66
|
+
# password so an encrypted key raises PKeyError instead of blocking
|
|
67
|
+
# the thread on OpenSSL's interactive stdin passphrase prompt.
|
|
68
|
+
ctx.key = OpenSSL::PKey.read(File.read(certificate.keyfile), certificate.password || '')
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def apply_trust(ctx)
|
|
72
|
+
case resolved_strategy
|
|
73
|
+
when :all_certificates
|
|
74
|
+
ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
|
75
|
+
when :custom_certificates
|
|
76
|
+
ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
|
77
|
+
ctx.cert_store = custom_cert_store
|
|
78
|
+
else # :system_certificates
|
|
79
|
+
ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
|
80
|
+
ctx.cert_store = OpenSSL::X509::Store.new.tap(&:set_default_paths)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Custom-trust mode without any `cert_files` paths would produce
|
|
85
|
+
# a VERIFY_PEER context with an empty store — every connection
|
|
86
|
+
# would fail with an opaque OpenSSL error. Catch this at config
|
|
87
|
+
# time with a clear message instead.
|
|
88
|
+
def custom_cert_store
|
|
89
|
+
paths = cert_files
|
|
90
|
+
if paths.empty?
|
|
91
|
+
raise ArgumentError,
|
|
92
|
+
'trust_strategy :trust_custom_certificates requires at least one path in :cert_files'
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
paths.each_with_object(OpenSSL::X509::Store.new) do |path, store|
|
|
96
|
+
store.add_file(path)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Resolves trust-strategy option → internal symbol. Falls back
|
|
101
|
+
# to the URI-implied default (+ssc → all-certs, anything else
|
|
102
|
+
# → system-certs) when no explicit option was given.
|
|
103
|
+
def resolved_strategy
|
|
104
|
+
return uri_default unless explicit_strategy
|
|
105
|
+
|
|
106
|
+
case explicit_strategy
|
|
107
|
+
when :trust_system_certificates then :system_certificates
|
|
108
|
+
when :trust_all_certificates then :all_certificates
|
|
109
|
+
when :trust_custom_certificates then :custom_certificates
|
|
110
|
+
else
|
|
111
|
+
raise ArgumentError, "Unknown trust_strategy: #{explicit_strategy.inspect}"
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def uri_default
|
|
116
|
+
TRUST_ALL_SCHEMES.include?(@uri.scheme) ? :all_certificates : :system_certificates
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def explicit_strategy
|
|
120
|
+
@options.dig(:trust_strategy, :strategy)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def cert_files
|
|
124
|
+
Array(@options.dig(:trust_strategy, :cert_files))
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|