neo4j-ruby-driver 1.7.5 → 4.4.0.alpha.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.
Files changed (339) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +26 -42
  3. data/lib/loader.rb +5 -3
  4. data/lib/neo4j/driver/auto_closable.rb +2 -2
  5. data/lib/neo4j/driver/exceptions/authentication_exception.rb +6 -1
  6. data/lib/neo4j/driver/exceptions/authorization_expired_exception.rb +14 -0
  7. data/lib/neo4j/driver/{types/bytes.rb → exceptions/certificate_exception.rb} +2 -2
  8. data/lib/neo4j/driver/exceptions/client_exception.rb +3 -0
  9. data/lib/neo4j/driver/exceptions/connection_read_timeout_exception.rb +14 -0
  10. data/lib/neo4j/driver/exceptions/database_exception.rb +3 -0
  11. data/lib/neo4j/driver/exceptions/discovery_exception.rb +16 -0
  12. data/lib/neo4j/driver/exceptions/fatal_discovery_exception.rb +13 -0
  13. data/lib/neo4j/driver/exceptions/protocol_exception.rb +7 -0
  14. data/lib/neo4j/driver/exceptions/result_consumed_exception.rb +13 -0
  15. data/lib/neo4j/driver/exceptions/security_exception.rb +5 -1
  16. data/lib/neo4j/driver/exceptions/service_unavailable_exception.rb +2 -0
  17. data/lib/neo4j/driver/exceptions/session_expired_exception.rb +4 -0
  18. data/lib/neo4j/driver/exceptions/token_expired_exception.rb +15 -0
  19. data/lib/neo4j/driver/exceptions/transaction_nesting_exception.rb +11 -0
  20. data/lib/neo4j/driver/exceptions/transient_exception.rb +3 -0
  21. data/lib/neo4j/driver/exceptions/untrusted_server_exception.rb +1 -0
  22. data/lib/neo4j/driver/exceptions/value/lossy_coercion.rb +15 -0
  23. data/lib/neo4j/driver/exceptions/value/not_multi_valued.rb +13 -0
  24. data/lib/neo4j/driver/exceptions/value/uncoercible.rb +15 -0
  25. data/lib/neo4j/driver/exceptions/value/unsizable.rb +12 -0
  26. data/lib/neo4j/driver/exceptions/value/value_exception.rb +12 -0
  27. data/lib/neo4j/driver/internal/bolt_server_address.rb +97 -0
  28. data/lib/neo4j/driver/internal/duration_normalizer.rb +1 -1
  29. data/lib/neo4j/driver/internal/validator.rb +5 -4
  30. data/{ffi/neo4j/driver/summary/statement_type.rb → lib/neo4j/driver/summary/query_type.rb} +1 -3
  31. data/lib/neo4j/driver/synchronizable.rb +23 -0
  32. data/lib/neo4j_ruby_driver.rb +5 -10
  33. data/{ffi → ruby}/neo4j/driver/access_mode.rb +2 -2
  34. data/ruby/neo4j/driver/auth_tokens.rb +34 -0
  35. data/ruby/neo4j/driver/bookmark.rb +21 -0
  36. data/ruby/neo4j/driver/config.rb +91 -0
  37. data/ruby/neo4j/driver/graph_database.rb +140 -0
  38. data/ruby/neo4j/driver/internal/async/connection/bolt_protocol_util.rb +51 -0
  39. data/ruby/neo4j/driver/internal/async/connection/bootstrap_factory.rb +22 -0
  40. data/ruby/neo4j/driver/internal/async/connection/channel_attributes.rb +31 -0
  41. data/ruby/neo4j/driver/internal/async/connection/channel_connected_listener.rb +32 -0
  42. data/ruby/neo4j/driver/internal/async/connection/channel_connector_impl.rb +77 -0
  43. data/ruby/neo4j/driver/internal/async/connection/channel_pipeline_builder_impl.rb +22 -0
  44. data/ruby/neo4j/driver/internal/async/connection/direct_connection.rb +30 -0
  45. data/ruby/neo4j/driver/internal/async/connection/event_loop_group_factory.rb +83 -0
  46. data/ruby/neo4j/driver/internal/async/connection/handshake_completed_listener.rb +27 -0
  47. data/ruby/neo4j/driver/internal/async/connection/handshake_handler.rb +113 -0
  48. data/ruby/neo4j/driver/internal/async/connection/netty_channel_initializer.rb +57 -0
  49. data/ruby/neo4j/driver/internal/async/connection/netty_domain_name_resolver.rb +26 -0
  50. data/ruby/neo4j/driver/internal/async/connection/netty_domain_name_resolver_group.rb +19 -0
  51. data/ruby/neo4j/driver/internal/async/connection/routing_connection.rb +36 -0
  52. data/ruby/neo4j/driver/internal/async/connection/stream.rb +12 -0
  53. data/ruby/neo4j/driver/internal/async/connection/stream_reader.rb +16 -0
  54. data/ruby/neo4j/driver/internal/async/connection_context.rb +10 -0
  55. data/ruby/neo4j/driver/internal/async/immutable_connection_context.rb +24 -0
  56. data/ruby/neo4j/driver/internal/async/inbound/byte_buf_input.rb +30 -0
  57. data/ruby/neo4j/driver/internal/async/inbound/channel_error_handler.rb +77 -0
  58. data/ruby/neo4j/driver/internal/async/inbound/chunk_decoder.rb +41 -0
  59. data/ruby/neo4j/driver/internal/async/inbound/connect_timeout_handler.rb +32 -0
  60. data/ruby/neo4j/driver/internal/async/inbound/connection_read_timeout_handler.rb +17 -0
  61. data/ruby/neo4j/driver/internal/async/inbound/inbound_message_dispatcher.rb +172 -0
  62. data/ruby/neo4j/driver/internal/async/inbound/inbound_message_handler.rb +42 -0
  63. data/ruby/neo4j/driver/internal/async/inbound/message_decoder.rb +51 -0
  64. data/ruby/neo4j/driver/internal/async/internal_async_session.rb +98 -0
  65. data/ruby/neo4j/driver/internal/async/internal_async_transaction.rb +13 -0
  66. data/ruby/neo4j/driver/internal/async/leak_logging_network_session.rb +34 -0
  67. data/ruby/neo4j/driver/internal/async/network_connection.rb +196 -0
  68. data/ruby/neo4j/driver/internal/async/network_session.rb +152 -0
  69. data/ruby/neo4j/driver/internal/async/outbound/chunk_aware_byte_buf_output.rb +110 -0
  70. data/ruby/neo4j/driver/internal/async/outbound/outbound_message_handler.rb +39 -0
  71. data/ruby/neo4j/driver/internal/async/pool/channel.rb +63 -0
  72. data/ruby/neo4j/driver/internal/async/pool/connection_pool_impl.rb +149 -0
  73. data/ruby/neo4j/driver/internal/async/pool/controller.rb +25 -0
  74. data/ruby/neo4j/driver/internal/async/pool/netty_channel_health_checker.rb +87 -0
  75. data/ruby/neo4j/driver/internal/async/pool/netty_channel_pool.rb +52 -0
  76. data/ruby/neo4j/driver/internal/async/pool/netty_channel_tracker.rb +137 -0
  77. data/ruby/neo4j/driver/internal/async/pool/network_connection_factory.rb +21 -0
  78. data/ruby/neo4j/driver/internal/async/pool/pool_settings.rb +34 -0
  79. data/ruby/neo4j/driver/internal/async/result_cursors_holder.rb +17 -0
  80. data/ruby/neo4j/driver/internal/async/unmanaged_transaction.rb +214 -0
  81. data/ruby/neo4j/driver/internal/bookmark_holder.rb +9 -0
  82. data/ruby/neo4j/driver/internal/cluster/cluster_composition.rb +58 -0
  83. data/ruby/neo4j/driver/internal/cluster/cluster_composition_lookup_result.rb +14 -0
  84. data/ruby/neo4j/driver/internal/cluster/cluster_routing_table.rb +139 -0
  85. data/ruby/neo4j/driver/internal/cluster/identity_resolver.rb +13 -0
  86. data/ruby/neo4j/driver/internal/cluster/loadbalancing/least_connected_load_balancing_strategy.rb +68 -0
  87. data/ruby/neo4j/driver/internal/cluster/loadbalancing/load_balancer.rb +159 -0
  88. data/ruby/neo4j/driver/internal/cluster/loadbalancing/round_robin_array_index.rb +13 -0
  89. data/ruby/neo4j/driver/internal/cluster/multi_databases_routing_procedure_runner.rb +34 -0
  90. data/ruby/neo4j/driver/internal/cluster/rediscovery_impl.rb +238 -0
  91. data/ruby/neo4j/driver/internal/cluster/route_message_routing_procedure_runner.rb +43 -0
  92. data/ruby/neo4j/driver/internal/cluster/routing_context.rb +77 -0
  93. data/ruby/neo4j/driver/internal/cluster/routing_procedure_cluster_composition_provider.rb +64 -0
  94. data/ruby/neo4j/driver/internal/cluster/routing_procedure_response.rb +19 -0
  95. data/ruby/neo4j/driver/internal/cluster/routing_settings.rb +24 -0
  96. data/ruby/neo4j/driver/internal/cluster/routing_table_handler_impl.rb +116 -0
  97. data/ruby/neo4j/driver/internal/cluster/routing_table_registry_impl.rb +140 -0
  98. data/ruby/neo4j/driver/internal/cluster/single_database_routing_procedure_runner.rb +76 -0
  99. data/ruby/neo4j/driver/internal/connection_settings.rb +16 -0
  100. data/ruby/neo4j/driver/internal/cursor/async_result_cursor_impl.rb +76 -0
  101. data/ruby/neo4j/driver/internal/cursor/async_result_cursor_only_factory.rb +29 -0
  102. data/ruby/neo4j/driver/internal/cursor/disposable_async_result_cursor.rb +59 -0
  103. data/ruby/neo4j/driver/internal/cursor/result_cursor_factory_impl.rb +29 -0
  104. data/ruby/neo4j/driver/internal/cursor/rx_result_cursor_impl.rb +110 -0
  105. data/ruby/neo4j/driver/internal/database_name.rb +12 -0
  106. data/ruby/neo4j/driver/internal/database_name_util.rb +37 -0
  107. data/ruby/neo4j/driver/internal/default_bookmark_holder.rb +15 -0
  108. data/ruby/neo4j/driver/internal/default_domain_name_resolver.rb +11 -0
  109. data/ruby/neo4j/driver/internal/direct_connection_provider.rb +40 -0
  110. data/ruby/neo4j/driver/internal/driver_factory.rb +127 -0
  111. data/ruby/neo4j/driver/internal/handlers/begin_tx_response_handler.rb +20 -0
  112. data/ruby/neo4j/driver/internal/handlers/channel_releasing_reset_response_handler.rb +29 -0
  113. data/ruby/neo4j/driver/internal/handlers/commit_tx_response_handler.rb +25 -0
  114. data/ruby/neo4j/driver/internal/handlers/hello_response_handler.rb +65 -0
  115. data/ruby/neo4j/driver/internal/handlers/init_response_handler.rb +34 -0
  116. data/ruby/neo4j/driver/internal/handlers/legacy_pull_all_response_handler.rb +228 -0
  117. data/ruby/neo4j/driver/internal/handlers/no_op_response_handler.rb +16 -0
  118. data/ruby/neo4j/driver/internal/handlers/ping_response_handler.rb +29 -0
  119. data/ruby/neo4j/driver/internal/handlers/pull_handlers.rb +32 -0
  120. data/ruby/neo4j/driver/internal/handlers/pulln/auto_pull_response_handler.rb +174 -0
  121. data/ruby/neo4j/driver/internal/handlers/pulln/basic_pull_response_handler.rb +288 -0
  122. data/ruby/neo4j/driver/internal/handlers/pulln/fetch_size_util.rb +20 -0
  123. data/ruby/neo4j/driver/internal/handlers/reset_response_handler.rb +34 -0
  124. data/ruby/neo4j/driver/internal/handlers/rollback_tx_response_handler.rb +19 -0
  125. data/ruby/neo4j/driver/internal/handlers/route_message_response_handler.rb +21 -0
  126. data/ruby/neo4j/driver/internal/handlers/routing_response_handler.rb +70 -0
  127. data/ruby/neo4j/driver/internal/handlers/run_response_handler.rb +37 -0
  128. data/ruby/neo4j/driver/internal/handlers/session_pull_response_completion_listener.rb +34 -0
  129. data/ruby/neo4j/driver/internal/handlers/transaction_pull_response_completion_listener.rb +20 -0
  130. data/ruby/neo4j/driver/internal/impersonation_util.rb +22 -0
  131. data/ruby/neo4j/driver/internal/internal_bookmark.rb +38 -0
  132. data/ruby/neo4j/driver/internal/internal_database_name.rb +11 -0
  133. data/ruby/neo4j/driver/internal/internal_driver.rb +78 -0
  134. data/ruby/neo4j/driver/internal/internal_entity.rb +22 -0
  135. data/ruby/neo4j/driver/internal/internal_node.rb +21 -0
  136. data/ruby/neo4j/driver/internal/internal_pair.rb +9 -0
  137. data/ruby/neo4j/driver/internal/internal_path.rb +35 -0
  138. data/ruby/neo4j/driver/internal/internal_point2_d.rb +9 -0
  139. data/ruby/neo4j/driver/internal/internal_point3_d.rb +6 -0
  140. data/{ffi → ruby}/neo4j/driver/internal/internal_record.rb +2 -1
  141. data/ruby/neo4j/driver/internal/internal_relationship.rb +26 -0
  142. data/ruby/neo4j/driver/internal/internal_result.rb +60 -0
  143. data/ruby/neo4j/driver/internal/internal_session.rb +81 -0
  144. data/ruby/neo4j/driver/internal/internal_transaction.rb +48 -0
  145. data/ruby/neo4j/driver/internal/logging/channel_activity_logger.rb +29 -0
  146. data/ruby/neo4j/driver/internal/logging/channel_error_logger.rb +17 -0
  147. data/ruby/neo4j/driver/internal/logging/prefixed_logger.rb +19 -0
  148. data/ruby/neo4j/driver/internal/logging/reformatted_logger.rb +17 -0
  149. data/ruby/neo4j/driver/internal/messaging/abstract_message_writer.rb +23 -0
  150. data/ruby/neo4j/driver/internal/messaging/bolt_protocol.rb +30 -0
  151. data/ruby/neo4j/driver/internal/messaging/bolt_protocol_version.rb +46 -0
  152. data/ruby/neo4j/driver/internal/messaging/common/common_message_reader.rb +51 -0
  153. data/ruby/neo4j/driver/internal/messaging/common/common_value.rb +31 -0
  154. data/ruby/neo4j/driver/internal/messaging/common/common_value_packer.rb +101 -0
  155. data/ruby/neo4j/driver/internal/messaging/common/common_value_unpacker.rb +234 -0
  156. data/ruby/neo4j/driver/internal/messaging/encode/begin_message_encoder.rb +15 -0
  157. data/ruby/neo4j/driver/internal/messaging/encode/commit_message_encoder.rb +14 -0
  158. data/ruby/neo4j/driver/internal/messaging/encode/discard_all_message_encoder.rb +14 -0
  159. data/ruby/neo4j/driver/internal/messaging/encode/discard_message_encoder.rb +15 -0
  160. data/ruby/neo4j/driver/internal/messaging/encode/goodbye_message_encoder.rb +14 -0
  161. data/ruby/neo4j/driver/internal/messaging/encode/hello_message_encoder.rb +15 -0
  162. data/ruby/neo4j/driver/internal/messaging/encode/init_message_encoder.rb +16 -0
  163. data/ruby/neo4j/driver/internal/messaging/encode/pull_all_message_encoder.rb +14 -0
  164. data/ruby/neo4j/driver/internal/messaging/encode/pull_message_encoder.rb +15 -0
  165. data/ruby/neo4j/driver/internal/messaging/encode/reset_message_encoder.rb +14 -0
  166. data/ruby/neo4j/driver/internal/messaging/encode/rollback_message_encoder.rb +14 -0
  167. data/ruby/neo4j/driver/internal/messaging/encode/route_message_encoder.rb +18 -0
  168. data/ruby/neo4j/driver/internal/messaging/encode/route_v44_message_encoder.rb +27 -0
  169. data/ruby/neo4j/driver/internal/messaging/encode/run_message_encoder.rb +16 -0
  170. data/ruby/neo4j/driver/internal/messaging/encode/run_with_metadata_message_encoder.rb +17 -0
  171. data/ruby/neo4j/driver/internal/messaging/request/abstract_streaming_message.rb +22 -0
  172. data/ruby/neo4j/driver/internal/messaging/request/begin_message.rb +26 -0
  173. data/ruby/neo4j/driver/internal/messaging/request/commit_message.rb +20 -0
  174. data/ruby/neo4j/driver/internal/messaging/request/discard_all_message.rb +20 -0
  175. data/ruby/neo4j/driver/internal/messaging/request/discard_message.rb +23 -0
  176. data/ruby/neo4j/driver/internal/messaging/request/goodbye_message.rb +20 -0
  177. data/ruby/neo4j/driver/internal/messaging/request/hello_message.rb +31 -0
  178. data/ruby/neo4j/driver/internal/messaging/request/init_message.rb +19 -0
  179. data/ruby/neo4j/driver/internal/messaging/request/message_with_metadata.rb +10 -0
  180. data/ruby/neo4j/driver/internal/messaging/request/multi_database_util.rb +26 -0
  181. data/ruby/neo4j/driver/internal/messaging/request/pull_all_message.rb +23 -0
  182. data/ruby/neo4j/driver/internal/messaging/request/pull_message.rb +22 -0
  183. data/ruby/neo4j/driver/internal/messaging/request/reset_message.rb +32 -0
  184. data/ruby/neo4j/driver/internal/messaging/request/rollback_message.rb +20 -0
  185. data/ruby/neo4j/driver/internal/messaging/request/route_message.rb +33 -0
  186. data/ruby/neo4j/driver/internal/messaging/request/run_message.rb +23 -0
  187. data/ruby/neo4j/driver/internal/messaging/request/run_with_metadata_message.rb +47 -0
  188. data/ruby/neo4j/driver/internal/messaging/request/transaction_metadata_builder.rb +24 -0
  189. data/ruby/neo4j/driver/internal/messaging/response/failure_message.rb +40 -0
  190. data/ruby/neo4j/driver/internal/messaging/response/ignored_message.rb +29 -0
  191. data/ruby/neo4j/driver/internal/messaging/response/record_message.rb +33 -0
  192. data/ruby/neo4j/driver/internal/messaging/response/success_message.rb +34 -0
  193. data/ruby/neo4j/driver/internal/messaging/v3/bolt_protocol_v3.rb +79 -0
  194. data/ruby/neo4j/driver/internal/messaging/v3/message_format_v3.rb +17 -0
  195. data/ruby/neo4j/driver/internal/messaging/v3/message_writer_v3.rb +27 -0
  196. data/ruby/neo4j/driver/internal/messaging/v4/bolt_protocol_v4.rb +29 -0
  197. data/ruby/neo4j/driver/internal/messaging/v4/message_format_v4.rb +17 -0
  198. data/ruby/neo4j/driver/internal/messaging/v4/message_writer_v4.rb +28 -0
  199. data/ruby/neo4j/driver/internal/messaging/v41/bolt_protocol_v41.rb +25 -0
  200. data/ruby/neo4j/driver/internal/messaging/v42/bolt_protocol_v42.rb +13 -0
  201. data/ruby/neo4j/driver/internal/messaging/v43/bolt_protocol_v43.rb +19 -0
  202. data/ruby/neo4j/driver/internal/messaging/v43/message_format_v43.rb +18 -0
  203. data/ruby/neo4j/driver/internal/messaging/v43/message_writer_v43.rb +34 -0
  204. data/ruby/neo4j/driver/internal/messaging/v44/bolt_protocol_v44.rb +17 -0
  205. data/ruby/neo4j/driver/internal/messaging/v44/message_format_v44.rb +18 -0
  206. data/ruby/neo4j/driver/internal/messaging/v44/message_writer_v44.rb +26 -0
  207. data/ruby/neo4j/driver/internal/metrics/connection_pool_metrics_listener.rb +34 -0
  208. data/ruby/neo4j/driver/internal/metrics/internal_abstract_metrics.rb +46 -0
  209. data/ruby/neo4j/driver/internal/metrics/internal_connection_pool_metrics.rb +105 -0
  210. data/ruby/neo4j/driver/internal/metrics/internal_metrics.rb +82 -0
  211. data/ruby/neo4j/driver/internal/metrics/internal_metrics_provider.rb +18 -0
  212. data/ruby/neo4j/driver/internal/metrics/listener_event.rb +17 -0
  213. data/ruby/neo4j/driver/internal/metrics/metrics_provider.rb +24 -0
  214. data/ruby/neo4j/driver/internal/metrics/time_recorder_listener_event.rb +15 -0
  215. data/ruby/neo4j/driver/internal/packstream/byte_array_incompatible_packer.rb +12 -0
  216. data/ruby/neo4j/driver/internal/packstream/pack_input.rb +47 -0
  217. data/ruby/neo4j/driver/internal/packstream/pack_output.rb +39 -0
  218. data/ruby/neo4j/driver/internal/packstream/pack_stream.rb +326 -0
  219. data/ruby/neo4j/driver/internal/packstream/pack_type.rb +17 -0
  220. data/ruby/neo4j/driver/internal/retry/exponential_backoff_retry_logic.rb +151 -0
  221. data/ruby/neo4j/driver/internal/revocation_strategy.rb +19 -0
  222. data/ruby/neo4j/driver/internal/scheme.rb +32 -0
  223. data/ruby/neo4j/driver/internal/security/internal_auth_token.rb +15 -0
  224. data/ruby/neo4j/driver/internal/security/security_plan_impl.rb +92 -0
  225. data/ruby/neo4j/driver/internal/security_setting.rb +73 -0
  226. data/ruby/neo4j/driver/internal/session_factory_impl.rb +32 -0
  227. data/ruby/neo4j/driver/internal/spi/connection.rb +19 -0
  228. data/ruby/neo4j/driver/internal/spi/connection_pool.rb +9 -0
  229. data/ruby/neo4j/driver/internal/spi/response_handler.rb +23 -0
  230. data/ruby/neo4j/driver/internal/summary/internal_database_info.rb +7 -0
  231. data/ruby/neo4j/driver/internal/summary/internal_input_position.rb +11 -0
  232. data/ruby/neo4j/driver/internal/summary/internal_notification.rb +16 -0
  233. data/ruby/neo4j/driver/internal/summary/internal_plan.rb +41 -0
  234. data/ruby/neo4j/driver/internal/summary/internal_profiled_plan.rb +32 -0
  235. data/ruby/neo4j/driver/internal/summary/internal_result_summary.rb +33 -0
  236. data/ruby/neo4j/driver/internal/summary/internal_server_info.rb +6 -0
  237. data/ruby/neo4j/driver/internal/summary/internal_summary_counters.rb +18 -0
  238. data/ruby/neo4j/driver/internal/svm/netty_substitutions.rb +196 -0
  239. data/ruby/neo4j/driver/internal/svm/z_lib_substitutions.rb +21 -0
  240. data/ruby/neo4j/driver/internal/util/certificate_tool.rb +65 -0
  241. data/ruby/neo4j/driver/internal/util/clock.rb +29 -0
  242. data/ruby/neo4j/driver/internal/util/error_util.rb +104 -0
  243. data/ruby/neo4j/driver/internal/util/extract.rb +123 -0
  244. data/ruby/neo4j/driver/internal/util/format.rb +39 -0
  245. data/ruby/neo4j/driver/internal/util/futures.rb +99 -0
  246. data/ruby/neo4j/driver/internal/util/iterables.rb +35 -0
  247. data/ruby/neo4j/driver/internal/util/lock_util.rb +23 -0
  248. data/ruby/neo4j/driver/internal/util/metadata_extractor.rb +109 -0
  249. data/ruby/neo4j/driver/internal/util/mutex.rb +9 -0
  250. data/ruby/neo4j/driver/internal/util/preconditions.rb +16 -0
  251. data/ruby/neo4j/driver/internal/util/server_version.rb +60 -0
  252. data/ruby/neo4j/driver/logging1.rb +51 -0
  253. data/ruby/neo4j/driver/net/server_address1.rb +9 -0
  254. data/ruby/neo4j/driver/query.rb +48 -0
  255. data/ruby/neo4j/driver/records.rb +13 -0
  256. data/ruby/neo4j/driver/session_config.rb +15 -0
  257. data/ruby/neo4j/driver/transaction_config.rb +46 -0
  258. data/ruby/neo4j/driver/values.rb +26 -0
  259. data/{lib → ruby}/neo4j/driver/version.rb +1 -1
  260. data/ruby/neo4j/driver.rb +30 -0
  261. metadata +267 -92
  262. data/ffi/bolt/address.rb +0 -11
  263. data/ffi/bolt/address_resolver.rb +0 -12
  264. data/ffi/bolt/address_set.rb +0 -9
  265. data/ffi/bolt/auth.rb +0 -10
  266. data/ffi/bolt/auto_releasable.rb +0 -22
  267. data/ffi/bolt/boolean.rb +0 -9
  268. data/ffi/bolt/bytes.rb +0 -10
  269. data/ffi/bolt/config.rb +0 -45
  270. data/ffi/bolt/connection.rb +0 -44
  271. data/ffi/bolt/connector.rb +0 -17
  272. data/ffi/bolt/dictionary.rb +0 -15
  273. data/ffi/bolt/error.rb +0 -74
  274. data/ffi/bolt/float.rb +0 -9
  275. data/ffi/bolt/integer.rb +0 -9
  276. data/ffi/bolt/library.rb +0 -12
  277. data/ffi/bolt/lifecycle.rb +0 -9
  278. data/ffi/bolt/list.rb +0 -10
  279. data/ffi/bolt/log.rb +0 -16
  280. data/ffi/bolt/socket_options.rb +0 -14
  281. data/ffi/bolt/status.rb +0 -25
  282. data/ffi/bolt/string.rb +0 -9
  283. data/ffi/bolt/structure.rb +0 -10
  284. data/ffi/bolt/value.rb +0 -35
  285. data/ffi/neo4j/driver/auth_tokens.rb +0 -18
  286. data/ffi/neo4j/driver/config.rb +0 -40
  287. data/ffi/neo4j/driver/graph_database.rb +0 -52
  288. data/ffi/neo4j/driver/internal/async/access_mode_connection.rb +0 -19
  289. data/ffi/neo4j/driver/internal/async/direct_connection.rb +0 -106
  290. data/ffi/neo4j/driver/internal/bolt_server_address.rb +0 -18
  291. data/ffi/neo4j/driver/internal/bookmarks_holder.rb +0 -30
  292. data/ffi/neo4j/driver/internal/direct_connection_provider.rb +0 -28
  293. data/ffi/neo4j/driver/internal/driver_factory.rb +0 -126
  294. data/ffi/neo4j/driver/internal/error_handling.rb +0 -112
  295. data/ffi/neo4j/driver/internal/explicit_transaction.rb +0 -146
  296. data/ffi/neo4j/driver/internal/handlers/pull_all_response_handler.rb +0 -104
  297. data/ffi/neo4j/driver/internal/handlers/response_handler.rb +0 -49
  298. data/ffi/neo4j/driver/internal/handlers/run_response_handler.rb +0 -32
  299. data/ffi/neo4j/driver/internal/handlers/session_pull_all_response_handler.rb +0 -32
  300. data/ffi/neo4j/driver/internal/handlers/transaction_pull_all_response_handler.rb +0 -23
  301. data/ffi/neo4j/driver/internal/internal_driver.rb +0 -45
  302. data/ffi/neo4j/driver/internal/internal_logger.rb +0 -32
  303. data/ffi/neo4j/driver/internal/internal_resolver.rb +0 -31
  304. data/ffi/neo4j/driver/internal/internal_statement_result.rb +0 -52
  305. data/ffi/neo4j/driver/internal/messaging/bolt_protocol.rb +0 -24
  306. data/ffi/neo4j/driver/internal/messaging/v1/bolt_protocol_v1.rb +0 -59
  307. data/ffi/neo4j/driver/internal/messaging/v2/bolt_protocol_v2.rb +0 -16
  308. data/ffi/neo4j/driver/internal/messaging/v3/bolt_protocol_v3.rb +0 -63
  309. data/ffi/neo4j/driver/internal/network_session.rb +0 -129
  310. data/ffi/neo4j/driver/internal/retry/exponential_backoff_retry_logic.rb +0 -80
  311. data/ffi/neo4j/driver/internal/session_factory_impl.rb +0 -28
  312. data/ffi/neo4j/driver/internal/summary/internal_result_summary.rb +0 -67
  313. data/ffi/neo4j/driver/internal/summary/internal_server_info.rb +0 -19
  314. data/ffi/neo4j/driver/internal/summary/internal_summary_counters.rb +0 -23
  315. data/ffi/neo4j/driver/internal/util/metadata_extractor.rb +0 -15
  316. data/ffi/neo4j/driver/internal/value/base_time_value.rb +0 -22
  317. data/ffi/neo4j/driver/internal/value/date_value.rb +0 -25
  318. data/ffi/neo4j/driver/internal/value/duration_value.rb +0 -27
  319. data/ffi/neo4j/driver/internal/value/local_date_time_value.rb +0 -24
  320. data/ffi/neo4j/driver/internal/value/local_time_value.rb +0 -19
  321. data/ffi/neo4j/driver/internal/value/node_value.rb +0 -18
  322. data/ffi/neo4j/driver/internal/value/offset_time_value.rb +0 -25
  323. data/ffi/neo4j/driver/internal/value/path_value.rb +0 -41
  324. data/ffi/neo4j/driver/internal/value/point2_d_value.rb +0 -24
  325. data/ffi/neo4j/driver/internal/value/point3_d_value.rb +0 -24
  326. data/ffi/neo4j/driver/internal/value/relationship_value.rb +0 -18
  327. data/ffi/neo4j/driver/internal/value/structure_value.rb +0 -42
  328. data/ffi/neo4j/driver/internal/value/time_with_zone_id_value.rb +0 -25
  329. data/ffi/neo4j/driver/internal/value/time_with_zone_offset_value.rb +0 -28
  330. data/ffi/neo4j/driver/internal/value/unbound_relationship_value.rb +0 -18
  331. data/ffi/neo4j/driver/internal/value/value_adapter.rb +0 -101
  332. data/ffi/neo4j/driver/net/server_address.rb +0 -13
  333. data/ffi/neo4j/driver/statement.rb +0 -15
  334. data/ffi/neo4j/driver/types/entity.rb +0 -21
  335. data/ffi/neo4j/driver/types/node.rb +0 -16
  336. data/ffi/neo4j/driver/types/path.rb +0 -35
  337. data/ffi/neo4j/driver/types/relationship.rb +0 -19
  338. data/ffi/neo4j/driver.rb +0 -61
  339. data/lib/neo4j/driver/internal/ruby_signature.rb +0 -18
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Neo4j
4
+ module Driver
5
+ class AuthTokens
6
+ class << self
7
+ def basic(username, password, realm = nil)
8
+ Internal::Validator.require_non_nil_credentials!(username, password)
9
+ Internal::Security::InternalAuthToken[
10
+ { scheme: 'basic', principal: username, credentials: password, realm: realm }.compact]
11
+ end
12
+
13
+ def bearer(token)
14
+ Internal::Validator.require_non_nil!(token, "Token")
15
+ Internal::Security::InternalAuthToken[scheme: 'bearer', credentials: token]
16
+ end
17
+
18
+ def kerberos(base64_encoded_ticket)
19
+ Internal::Validator.require_non_nil!(base64_encoded_ticket, "Ticket")
20
+ Internal::Security::InternalAuthToken[scheme: 'bearer', credentials: base64_encoded_ticket]
21
+ end
22
+
23
+ def custom(principal, credentials, realm, scheme, **parameters)
24
+ Internal::Security::InternalAuthToken[{ scheme: scheme, principal: principal, credentials: credentials,
25
+ realm: realm, parameters: parameters.presence || nil }.compact]
26
+ end
27
+
28
+ def none
29
+ Internal::Security::InternalAuthToken[scheme: 'none']
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,21 @@
1
+ module Neo4j
2
+ module Driver
3
+ # Causal chaining is carried out by passing bookmarks between transactions.
4
+
5
+ # When starting a session with initial bookmarks, the first transaction will be ensured to run at least after
6
+ # the database is as up-to-date as the latest transaction referenced by the supplied bookmarks.
7
+
8
+ # Within a session, bookmark propagation is carried out automatically.
9
+ # Thus all transactions in a session (both managed and unmanaged) are guaranteed to be carried out one after another.
10
+
11
+ # To opt out of this mechanism for unrelated units of work, applications can use multiple sessions.
12
+ module Bookmark
13
+ # Reconstruct bookmark from \bookmarks string values.
14
+ # @param values values obtained from a previous bookmark.
15
+ # @return A bookmark.
16
+ def self.from(*values)
17
+ Internal::InternalBookmark.parse(*values)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Neo4j
4
+ module Driver
5
+ class Config < Hash
6
+ class TrustStrategy
7
+ TRUST_ALL_CERTIFICATES = :trust_all_certificates
8
+ TRUST_CUSTOM_CA_SIGNED_CERTIFICATES = :trust_custom_certificates
9
+ TRUST_SYSTEM_CA_SIGNED_CERTIFICATES = :trust_system_certificates
10
+
11
+ attr_reader :strategy, :cert_files, :revocation_strategy
12
+
13
+ #
14
+ # {
15
+ # trust_strategy: {
16
+ # strategy: :trust_custom_certificates,
17
+ # cert_files: ['some_path', 'another_path'],
18
+ # revocation_strategy: :no_checks, # or :verify_if_present, :strict
19
+ # hostname_verification: true
20
+ # },
21
+ # encryption: true
22
+ # }
23
+ def initialize(**config)
24
+ @strategy = config[:strategy]
25
+ @cert_files = config[:cert_files]
26
+ @revocation_strategy = config[:revocation_strategy] || Neo4j::Driver::Internal::RevocationStrategy::NO_CHECKS
27
+ @hostname_verification_enabled = config[:hostname_verification] || false
28
+ end
29
+
30
+ def self.trust_all_certificates
31
+ new(trust_strategy: TRUST_ALL_CERTIFICATES)
32
+ end
33
+
34
+ def hostname_verification_enabled?
35
+ @hostname_verification_enabled
36
+ end
37
+ end
38
+
39
+ # Console.logger = ::Logger.new(STDOUT, level: :debug)
40
+ DEFAULTS = {
41
+ logger: ::Logger.new(nil),
42
+ # logger: ::Logger.new(STDOUT, level: :debug),
43
+ # logger: Console.logger,
44
+ leaked_sessions_logging: false,
45
+ max_connection_pool_size: Internal::Async::Pool::PoolSettings::DEFAULT_MAX_CONNECTION_POOL_SIZE,
46
+ idle_time_before_connection_test: Internal::Async::Pool::PoolSettings::DEFAULT_IDLE_TIME_BEFORE_CONNECTION_TEST,
47
+ max_connection_lifetime: Internal::Async::Pool::PoolSettings::DEFAULT_MAX_CONNECTION_LIFETIME,
48
+ connection_acquisition_timeout: Internal::Async::Pool::PoolSettings::DEFAULT_CONNECTION_ACQUISITION_TIMEOUT,
49
+ routing_failure_limit: Internal::Cluster::RoutingSettings::DEFAULT.max_routing_failures,
50
+ routing_retry_delay: Internal::Cluster::RoutingSettings::DEFAULT.retry_timeout_delay,
51
+ routing_table_purge_delay: Internal::Cluster::RoutingSettings::DEFAULT.routing_table_purge_delay,
52
+ user_agent: "neo4j-ruby/#{Neo4j::Driver::VERSION}",
53
+ connection_timeout: 30.seconds,
54
+ driver_metrics: false,
55
+ fetch_size: Internal::Handlers::Pulln::FetchSizeUtil::DEFAULT_FETCH_SIZE,
56
+ event_loop_threads: 0,
57
+
58
+ # TODO: Still to cleanup
59
+ encryption: false, # :set_transport
60
+ keep_alive: true, # BoltSocketOptions_set_keep_alive
61
+ # connection_liveness_check_timeout: -1, # Not configured
62
+ max_transaction_retry_time: Internal::Retry::ExponentialBackoffRetryLogic::DEFAULT_MAX_RETRY_TIME,
63
+ metrics_enabled: false,
64
+ # resolver: nil # :set_address_resolver
65
+ trust_strategy: TrustStrategy.trust_all_certificates,
66
+ }.freeze
67
+
68
+ def initialize(**config)
69
+ merge!(DEFAULTS).merge!(config.compact)
70
+ init_security_and_trust_config(config)
71
+ end
72
+
73
+ def routing_settings
74
+ Internal::Cluster::RoutingSettings.new(
75
+ *values_at(:routing_failure_limit, :routing_retry_delay, :routing_table_purge_delay))
76
+ end
77
+
78
+ private
79
+
80
+ def init_security_and_trust_config(config)
81
+ trust_strategy = config.key?(:trust_strategy) ? TrustStrategy.new(**config) : DEFAULTS[:trust_strategy]
82
+ encryption = config.key?(:encryption) ? config[:encryption] : DEFAULTS[:encryption]
83
+ customized = %i[encryption trust_strategy].any?(&config.method(:key?))
84
+ merge!(
85
+ security_settings: Neo4j::Driver::Internal::SecuritySetting.new(encryption, trust_strategy, customized),
86
+ trust_strategy: trust_strategy
87
+ )
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,140 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Neo4j::Driver
4
+ class GraphDatabase
5
+ class << self
6
+ extend AutoClosable
7
+ extend Synchronizable
8
+ auto_closable :driver, :routing_driver
9
+ sync :driver
10
+
11
+ GOGOBOLT = ["6060B017"].pack('H*')
12
+
13
+ def handshake_concurrent(*versions)
14
+ remote_port = 7687
15
+ remote_addr = 'localhost'
16
+ selector = NIO::Selector.new
17
+ socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
18
+ begin
19
+ socket.connect_nonblock Socket.sockaddr_in(remote_port, remote_addr)
20
+ rescue Errno::EINPROGRESS
21
+ # Ruby's a-tryin' to connect us, we swear!
22
+ selector.register(socket, :w)
23
+ end
24
+ selector.select do |monitor|
25
+ case monitor.io
26
+ when Socket
27
+ if monitor.writable?
28
+ begin
29
+ socket.connect_nonblock Socket.sockaddr_in(remote_port, remote_addr)
30
+ rescue Errno::EISCONN
31
+ # SUCCESS! Since Ruby is crazy we discover we're successful via an exception
32
+ end
33
+ end
34
+ end
35
+ end
36
+ socket.write_nonblock(GOGOBOLT)
37
+ socket.write_nonblock(bolt_versions(*versions))
38
+
39
+ @data = nil
40
+ begin
41
+ @data = socket.read_nonblock(16384)
42
+ rescue IO::WaitReadable
43
+ monitor = selector.register(socket, :r)
44
+ monitor.value = proc do
45
+ @data = socket.read_nonblock(16384)
46
+ end
47
+ end
48
+ Concurrent::Promises.future do
49
+ selector.select do |monitor|
50
+ monitor.value.call
51
+ end
52
+ ruby_version(@data)
53
+ end
54
+ end
55
+
56
+ class Connection < Async::Pool::Resource
57
+ attr :version, true
58
+ attr :io
59
+
60
+ def initialize
61
+ super
62
+ @io = Async::IO::Endpoint.tcp('localhost', 7687).connect
63
+ end
64
+
65
+ def close
66
+ super
67
+ @io.close
68
+ end
69
+ end
70
+
71
+ def driver(uri, auth_token = nil, **config)
72
+ internal_driver(uri, auth_token, config, Internal::DriverFactory.new)
73
+ end
74
+
75
+ def internal_driver(uri, auth_token, config, factory)
76
+ uri = URI(uri)
77
+ config = Config.new(**config)
78
+
79
+ factory.new_instance(
80
+ uri,
81
+ auth_token || AuthTokens.none,
82
+ config.routing_settings,
83
+ config[:max_transaction_retry_time],
84
+ config,
85
+ config[:security_settings].create_security_plan(uri.scheme)
86
+ )
87
+ end
88
+
89
+ def routing_driver(routing_uris, auth_toke, **config)
90
+ assert_routing_uris(routing_uris)
91
+ log = Config.new(**config)[:logger]
92
+
93
+ routing_uris.each do |uri|
94
+ driver = driver(uri, auth_toke, **config)
95
+ begin
96
+ return driver.tap(&:verify_connectivity)
97
+ rescue Exceptions::ServiceUnavailableException => e
98
+ log.warn { "Unable to create routing driver for URI: #{uri}\n#{e}" }
99
+ close_driver(driver, uri, log)
100
+ rescue Exception => e
101
+ close_driver(driver, uri, log)
102
+ raise e
103
+ end
104
+ end
105
+
106
+ raise Exceptions::ServiceUnavailableException, 'Failed to discover an available server'
107
+ end
108
+
109
+ private
110
+
111
+ def bolt_version(version)
112
+ pad(version.split(/[.\-]/).map(&:to_i), 4).reverse
113
+ end
114
+
115
+ def ruby_version(bolt_version)
116
+ bolt_version.unpack('C*').reverse.map(&:to_s).join('.')
117
+ end
118
+
119
+ def bolt_versions(*versions)
120
+ pad(versions[0..3].map(&method(:bolt_version)).flatten, 16).pack('C*')
121
+ end
122
+
123
+ def pad(arr, n)
124
+ arr + [0] * [0, n - arr.size].max
125
+ end
126
+
127
+ def close_driver(driver, uri, log)
128
+ driver.close
129
+ rescue StandardError => close_error
130
+ log.warn { "Unable to close driver towards URI: #{uri}\n#{close_error}" }
131
+ end
132
+
133
+ def assert_routing_uris(uris)
134
+ uris.find { |uri| URI(uri).scheme != Neo4j::Driver::Internal::Scheme::NEO4J_URI_SCHEME }&.tap do |uri|
135
+ raise ArgumentError, "Illegal URI scheme, expected '#{Internal::Scheme::NEO4J_URI_SCHEME}' in '#{uri}'"
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,51 @@
1
+ module Neo4j::Driver
2
+ module Internal
3
+ module Async
4
+ module Connection
5
+ class BoltProtocolUtil
6
+ BOLT_MAGIC_PREAMBLE = 0x6060B017
7
+ NO_PROTOCOL_VERSION = Messaging::BoltProtocolVersion.new(0, 0)
8
+ CHUNK_HEADER_SIZE_BYTES = 2
9
+ DEFAULT_MAX_OUTBOUND_CHUNK_SIZE_BYTES = 2 ** 15 - 1
10
+ HANDSHAKE = [
11
+ BOLT_MAGIC_PREAMBLE,
12
+ Messaging::V44::BoltProtocolV44::VERSION.to_int_range(Messaging::V42::BoltProtocolV42::VERSION),
13
+ Messaging::V41::BoltProtocolV41::VERSION.to_int,
14
+ Messaging::V4::BoltProtocolV4::VERSION.to_int,
15
+ Messaging::V3::BoltProtocolV3::VERSION.to_int]
16
+ HANDSHAKE_BUF = HANDSHAKE.pack('N*').freeze
17
+
18
+ class << self
19
+ def handshake_buf
20
+ HANDSHAKE_BUF
21
+ end
22
+
23
+ def handshake_string
24
+ HANDSHAKE_STRING
25
+ end
26
+
27
+ def write_message_boundary(buf)
28
+ buf.write_short(0)
29
+ end
30
+
31
+ def write_empty_chunk_header(buf)
32
+ buf.write_short(0)
33
+ end
34
+
35
+ def write_chunk_header(buf, chunk_start_index, header_value)
36
+ buf.set_short(chunk_start_index, header_value)
37
+ end
38
+
39
+ private
40
+
41
+ def create_handshake_string
42
+ "[0x#{HANDSHAKE.first.to_s(16)}, %s, %s, %s, %s]" % HANDSHAKE[1, 4]
43
+ end
44
+ end
45
+
46
+ HANDSHAKE_STRING = create_handshake_string
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,22 @@
1
+ module Neo4j::Driver
2
+ module Internal
3
+ module Async
4
+ module Connection
5
+ class BootstrapFactory
6
+ class << self
7
+ def new_bootstrap(thread_count: nil,
8
+ event_loop_group: EventLoopGroupFactory.new_event_loop_group(thread_count))
9
+ # Ione::Io::IoReactor.new
10
+ # Io::Bootstrap.new.tap do |bootstrap|
11
+ # bootstrap.group = event_loop_group
12
+ # bootstrap.channel(EventLoopGroupFactory.channel_class)
13
+ # bootstrap.option(org.neo4j.driver.internal.shaded.io.netty.channel.ChannelOption::SO_KEEPALIVE, true)
14
+ # bootstrap.option(org.neo4j.driver.internal.shaded.io.netty.channel.ChannelOption::SO_REUSEADDR, true)
15
+ # end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,31 @@
1
+ module Neo4j::Driver
2
+ module Internal
3
+ module Async
4
+ module Connection
5
+ class ChannelAttributes < Hash
6
+ # CONNECTION_ID = org.neo4j.driver.internal.shaded.io.netty.util.AttributeKey.new_instance('connectionId')
7
+ # POOL_ID = org.neo4j.driver.internal.shaded.io.netty.util.AttributeKey.new_instance('poolId')
8
+ # PROTOCOL_VERSION = org.neo4j.driver.internal.shaded.io.netty.util.AttributeKey.new_instance('protocolVersion')
9
+ # SERVER_AGENT = org.neo4j.driver.internal.shaded.io.netty.util.AttributeKey.new_instance('serverAgent')
10
+ # ADDRESS = org.neo4j.driver.internal.shaded.io.netty.util.AttributeKey.new_instance('serverAddress')
11
+ # SERVER_VERSION = org.neo4j.driver.internal.shaded.io.netty.util.AttributeKey.new_instance('serverVersion')
12
+ # CREATION_TIMESTAMP = org.neo4j.driver.internal.shaded.io.netty.util.AttributeKey.new_instance('creationTimestamp')
13
+ # LAST_USED_TIMESTAMP = org.neo4j.driver.internal.shaded.io.netty.util.AttributeKey.new_instance('lastUsedTimestamp')
14
+ # MESSAGE_DISPATCHER = org.neo4j.driver.internal.shaded.io.netty.util.AttributeKey.new_instance('messageDispatcher')
15
+ # TERMINATION_REASON = org.neo4j.driver.internal.shaded.io.netty.util.AttributeKey.new_instance('terminationReason')
16
+ # AUTHORIZATION_STATE_LISTENER = org.neo4j.driver.internal.shaded.io.netty.util.AttributeKey.new_instance('authorizationStateListener')
17
+ # CONNECTION_READ_TIMEOUT = org.neo4j.driver.internal.shaded.io.netty.util.AttributeKey.new_instance('connectionReadTimeout')
18
+
19
+ UPDATABLE_KEYS = %i[last_used_timestamp authorization_state_listener]
20
+
21
+ def []=(key, value)
22
+ if !UPDATABLE_KEYS.include?(key) && key?(key)
23
+ raise Neo4j::Driver::Exceptions::IllegalStateException, "Unable to set #{key} because it is already set to #{self[key]}"
24
+ end
25
+ super
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,32 @@
1
+ module Neo4j::Driver
2
+ module Internal
3
+ module Async
4
+ module Connection
5
+ class ChannelConnectedListener < Struct.new(:address, :pipeline_builder, :handshake_completed_promise, :logger)
6
+ # include org.neo4j.driver.internal.shaded.io.netty.channel.ChannelFutureListener
7
+ def operationComplete(future)
8
+ channel = future.channel
9
+ log = Logging::ChannelActivityLogger.new(channel, logger, self.class)
10
+
11
+ if future.fulfilled?
12
+ log.debug("Channel #{channel} connected, initiating bolt handshake")
13
+
14
+ pipeline = channel.pipeline
15
+ pipeline.add_last(HandshakeHandler.new(pipeline_builder, handshake_completed_promise, logger))
16
+ log.debug("C: [Bolt Handshake] #{BoltProtocolUtil.handshake_string}")
17
+ channel.write_and_flush(BoltProtocolUtil.handshake_buf, channel.void_promise)
18
+ else
19
+ handshake_completed_promise.set_failure(self.class.database_unavailable_error(address, future.cause))
20
+ end
21
+ end
22
+
23
+ def self.database_unavailable_error(address, cause)
24
+ Neo4j::Driver::Exceptions::ServiceUnavailableException.new(
25
+ "Unable to connect to #{address}, ensure the database is running and that there is a working network connection to it.",
26
+ cause)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,77 @@
1
+ module Neo4j::Driver
2
+ module Internal
3
+ module Async
4
+ module Connection
5
+ class ChannelConnectorImpl
6
+ def initialize(connection_settings, security_plan, logger, clock, routing_context, pipeline_builder = ChannelPipelineBuilderImpl.new, &domain_name_resolver)
7
+ @user_agent = connection_settings.user_agent
8
+ @auth_token = self.class.require_valid_auth_token(connection_settings.auth_token)
9
+ @routing_context = routing_context
10
+ @connect_timeout_millis = connection_settings.connect_timeout_millis
11
+ @security_plan = Validator.require_non_nil!(security_plan)
12
+ @pipeline_builder = pipeline_builder
13
+ @logger = Validator.require_non_nil!(logger)
14
+ @clock = Validator.require_non_nil!(clock)
15
+ @domain_name_resolver = Validator.require_non_nil!(domain_name_resolver)
16
+ end
17
+
18
+ def connect(address)
19
+ socket_host = (@domain_name_resolver.call(address.connection_host).first.ip_address rescue nil) || bracketless(address.connection_host)
20
+
21
+ channel_connected = ::Async::IO::Endpoint.tcp(socket_host, address.port).connect
22
+
23
+ # install_channel_connected_listeners(address, channel_connected, handshake_completed)
24
+ # install_handshake_completed_listeners(handshake_completed, connection_initialized)
25
+
26
+ channel_connected
27
+ rescue Errno::ECONNREFUSED => e
28
+ raise Exceptions::ServiceUnavailableException, e.message
29
+ end
30
+
31
+ def initialize_channel(channel, protocol)
32
+ protocol.initialize_channel(channel, @user_agent, @auth_token, @routing_context)
33
+ end
34
+
35
+ private
36
+
37
+ def bracketless(host)
38
+ host.delete_prefix('[').delete_suffix(']')
39
+ end
40
+
41
+ def install_channel_connected_listeners(address, channel_connected, handshake_completed)
42
+ pipeline = channel_connected.channel.pipeline
43
+
44
+ # add timeout handler to the pipeline when channel is connected. it's needed to limit amount of time code
45
+ # spends in TLS and Bolt handshakes. prevents infinite waiting when database does not respond
46
+ channel_connected.add_listener { pipeline.add_first(Inbound::ConnectTimeoutHandler.new(@connect_timeout_millis)) }
47
+
48
+ # add listener that sends Bolt handshake bytes when channel is connected
49
+ channel_connected.add_listener(ChannelConnectedListener.new(address, @pipeline_builder, handshake_completed, @logger))
50
+ end
51
+
52
+ def install_handshake_completed_listeners(handshake_completed, connection_initialized)
53
+ pipeline = handshake_completed.channel.pipeline
54
+
55
+ # remove timeout handler from the pipeline once TLS and Bolt handshakes are completed. regular protocol
56
+ # messages will flow next and we do not want to have read timeout for them
57
+ handshake_completed.add_listener { pipeline.remove(Inbound::ConnectTimeoutHandler.java_class) }
58
+
59
+ # add listener that sends an INIT message. connection is now fully established. channel pipeline if fully
60
+ # set to send/receive messages for a selected protocol version
61
+ handshake_completed.add_listener(HandshakeCompletedListener.new(@user_agent, @auth_token, @routing_context, connection_initialized))
62
+ end
63
+
64
+ class << self
65
+ def require_valid_auth_token(token)
66
+ if token.is_a? Internal::Security::InternalAuthToken
67
+ token
68
+ else
69
+ raise Exceptions::ClientException, "Unknown authentication token, `#{token}`. Please use one of the supported tokens from `#{AuthTokens.class}`."
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,22 @@
1
+ module Neo4j::Driver
2
+ module Internal
3
+ module Async
4
+ module Connection
5
+ class ChannelPipelineBuilderImpl
6
+ def build(message_format, pipeline, logger)
7
+ # inbound handlers
8
+ pipeline.add_last(Inbound::ChunkDecoder.new(logger))
9
+ pipeline.add_last(Inbound::MessageDecoder.new)
10
+ pipeline.add_last(Inbound::InboundMessageHandler.new(message_format, logger))
11
+
12
+ # outbound handlers
13
+ pipeline.add_last(Outbound::OutboundMessageHandler::NAME, Outbound::OutboundMessageHandler.new(message_format, logger))
14
+
15
+ # last one - error handler
16
+ pipeline.add_last(Inbound::ChannelErrorHandler.new(logger))
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,30 @@
1
+ module Neo4j::Driver
2
+ module Internal
3
+ module Async
4
+ module Connection
5
+ # This is a connection used by {@link DirectConnectionProvider} to connect to a remote database.
6
+ class DirectConnection < Struct.new(:delegate, :database_name, :mode, :impersonated_user)
7
+ delegate *%i[enable_auto_read disable_auto_read reset open? release terminate_and_release server_agent
8
+ server_address server_version protocol flush], to: :delegate
9
+ alias connection delegate
10
+
11
+ def write(message1, handler1, message2 = nil, handler2 = nil)
12
+ if message2.present? && handler2.present?
13
+ delegate.write(message1, handler1, message2, handler2)
14
+ else
15
+ delegate.write(message1, handler1)
16
+ end
17
+ end
18
+
19
+ def write_and_flush(message1, handler1, message2 = nil, handler2 = nil)
20
+ if message2.present? && handler2.present?
21
+ delegate.write_and_flush(message1, handler1, message2, handler2)
22
+ else
23
+ delegate.write_and_flush(message1, handler1)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,83 @@
1
+ module Neo4j::Driver
2
+ module Internal
3
+ module Async
4
+ module Connection
5
+ class EventLoopGroupFactory
6
+ THREAD_NAME_PREFIX = "Neo4jDriverIO"
7
+ THREAD_PRIORITY = 10
8
+ THREAD_IS_DAEMON = true
9
+
10
+ class << self
11
+ # Get class of {@link Channel} for {@link Bootstrap#channel(Class)} method.
12
+
13
+ # @return class of the channel, which should be consistent with {@link EventLoopGroup}s returned by
14
+ # {@link #newEventLoopGroup(int)}.
15
+ def channel_class
16
+ # org.neo4j.driver.internal.shaded.io.netty.channel.socket.nio.NioSocketChannel
17
+ end
18
+
19
+ # Create new {@link EventLoopGroup} with specified thread count. Returned group should by given to
20
+ # {@link Bootstrap#group(EventLoopGroup)}.
21
+
22
+ # @param threadCount amount of IO threads for the new group.
23
+ # @return new group consistent with channel class returned by {@link #channelClass()}.
24
+ def new_event_loop_group(thread_count)
25
+ DriverEventLoopGroup.new(thread_count)
26
+ end
27
+
28
+ # Assert that current thread is not an event loop used for async IO operations. This check is needed because
29
+ # blocking API methods like {@link Session#run(String)} are implemented on top of corresponding async API methods
30
+ # like {@link AsyncSession#runAsync(String)} using basically {@link Future#get()} calls. Deadlocks might happen when IO
31
+ # thread executes blocking API call and has to wait for itself to read from the network.
32
+
33
+ # @throws IllegalStateException when current thread is an event loop IO thread.
34
+ def assert_not_in_event_loop_thread
35
+ if event_loop_thread?(Thread.current)
36
+ raise Exceptions::IllegalStateException, "Blocking operation can't be executed in IO thread because it might result in a deadlock. Please do not use blocking API when chaining futures returned by async API methods."
37
+ end
38
+ end
39
+
40
+ # Check if given thread is an event loop IO thread.
41
+
42
+ # @param thread the thread to check.
43
+ # @return {@code true} when given thread belongs to the event loop, {@code false} otherwise.
44
+ def event_loop_thread?(thread)
45
+ thread.is_a?(DriverThread)
46
+ end
47
+ end
48
+
49
+ private
50
+
51
+ # Same as {@link NioEventLoopGroup} but uses a different {@link ThreadFactory} that produces threads of
52
+ # {@link DriverThread} class. Such threads can be recognized by {@link #assertNotInEventLoopThread()}.
53
+ class DriverEventLoopGroup #< org.neo4j.driver.internal.shaded.io.netty.channel.nio.NioEventLoopGroup
54
+ def initialize(n_threads = nil)
55
+ end
56
+
57
+ protected
58
+
59
+ def new_default_thread_factory
60
+ DriverThreadFactory.new
61
+ end
62
+ end
63
+
64
+ # Same as {@link DefaultThreadFactory} created by {@link NioEventLoopGroup} by default, except produces threads of
65
+ # {@link DriverThread} class. Such threads can be recognized by {@link #assertNotInEventLoopThread()}.
66
+
67
+ class DriverThreadFactory #< org.neo4j.driver.internal.shaded.io.netty.util.concurrent.DefaultThreadFactory
68
+ def initialize()
69
+ super(THREAD_NAME_PREFIX, THREAD_IS_DAEMON, THREAD_PRIORITY)
70
+ end
71
+
72
+ def new_thread(r, name)
73
+ DriverThread.new(@thread_group, r, name)
74
+ end
75
+ end
76
+
77
+ class DriverThread #< org.neo4j.driver.internal.shaded.io.netty.util.concurrent.FastThreadLocalThread
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,27 @@
1
+ module Neo4j::Driver
2
+ module Internal
3
+ module Async
4
+ module Connection
5
+ class HandshakeCompletedListener
6
+ attr_reader :user_agent, :auth_token, :routing_context, :connection_initialized_promise
7
+
8
+ def initialize(user_agent, auth_token, routing_context, connection_initialized_promise)
9
+ @user_agent = java.util.Objects.require_non_null(user_agent)
10
+ @auth_token = java.util.Objects.require_non_null(auth_token)
11
+ @routing_context = routing_context
12
+ @connection_initialized_promise = java.util.Objects.require_non_null(connection_initialized_promise)
13
+ end
14
+
15
+ def operation_complete(future)
16
+ if future.is_success?
17
+ protocol = Messaging::BoltProtocol.for_channel(future.channel)
18
+ protocol.initialize_channel(user_agent, auth_token, routing_context, connection_initialized_promise)
19
+ else
20
+ connection_initialized_promise.set_failure(future.cause)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end