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,152 @@
1
+ module Neo4j::Driver
2
+ module Internal
3
+ module Async
4
+ class NetworkSession
5
+ attr_reader :retry_logic
6
+
7
+ def initialize(connection_provider, retry_logic, database_name, mode, bookmark_holder, impersonated_user, fetch_size, logger)
8
+ @connection_provider = connection_provider
9
+ @mode = mode
10
+ @retry_logic = retry_logic
11
+ @log = Logging::PrefixedLogger.new("[#{hash}]", logger)
12
+ @bookmark_holder = bookmark_holder
13
+ @database_name = database_name.database_name
14
+ @connection_context = NetworkSessionConnectionContext.new(@database_name, @bookmark_holder.bookmark, impersonated_user)
15
+ @fetch_size = fetch_size
16
+ @open = Concurrent::AtomicBoolean.new(true)
17
+ end
18
+
19
+ def run_async(query, **config)
20
+ new_result_cursor = build_result_cursor_factory(query, config).async_result
21
+ @result_cursor = new_result_cursor
22
+ new_result_cursor.map_successful_run_completion_async
23
+ end
24
+
25
+ def run_rx(query, **config)
26
+ new_result_cursor_stage = build_result_cursor_factory(query, config).then_flat(Cursor::ResultCursorFactory.rx_result)
27
+ @result_cursor_stage = new_result_cursor_stage.rescue {}
28
+ new_result_cursor_stage
29
+ end
30
+
31
+ def begin_transaction_async(mode = @mode, **config)
32
+ ensure_session_is_open
33
+ ensure_no_open_tx_before_starting_tx
34
+ acquire_connection(mode).then do |connection|
35
+ ImpersonationUtil.ensure_impersonation_support(connection, connection.impersonated_user)
36
+ tx = UnmanagedTransaction.new(connection, @bookmark_holder, @fetch_size)
37
+ tx.begin_async(@bookmark_holder.bookmark, config)
38
+ end&.tap { |new_transaction| @transaction = new_transaction }
39
+ end
40
+
41
+ def reset_async
42
+ existing_transaction_or_null
43
+ .then_accept { |tx| tx&.mark_terminated }
44
+ .then_flat { @connection_stage }
45
+ .then_flat do |connection|
46
+ # there exists an active connection, send a RESET message over it
47
+ connection&.reset || Util::Futures.completed_with_null
48
+ end
49
+ end
50
+
51
+ def last_bookmark
52
+ @bookmark_holder.bookmark
53
+ end
54
+
55
+ def release_connection_async
56
+ @connection&.release
57
+ end
58
+
59
+ def connection_async
60
+ @connection
61
+ end
62
+
63
+ def open?
64
+ @open.true?
65
+ end
66
+
67
+ def close_async
68
+ return unless @open.make_false
69
+ # there exists a cursor with potentially unconsumed error, try to extract and propagate it
70
+ @result_cursor&.discard_all_failure_async
71
+ ensure
72
+ close_transaction_and_release_connection
73
+ end
74
+
75
+ def current_connection_open?
76
+ @connection&.open? # some connection has actually been acquired and it's still open
77
+ end
78
+
79
+ private
80
+
81
+ def build_result_cursor_factory(query, config)
82
+ ensure_session_is_open
83
+ ensure_no_open_tx_before_running_query
84
+ connection = acquire_connection(@mode)
85
+ ImpersonationUtil.ensure_impersonation_support(connection, connection.impersonated_user)
86
+ connection.protocol.run_in_auto_commit_transaction(connection, query, @bookmark_holder, config,
87
+ @fetch_size)
88
+ end
89
+
90
+ def acquire_connection(mode)
91
+ # make sure previous result is fully consumed and connection is released back to the pool
92
+ @result_cursor&.pull_all_failure_async
93
+ if @connection&.open?
94
+ # there somehow is an existing open connection, this should not happen, just a precondition
95
+ raise Neo4j::Driver::Exceptions::IllegalStateException.new('Existing open connection detected')
96
+ end
97
+
98
+ @connection = @connection_provider.acquire_connection(@connection_context.context_with_mode(mode))
99
+ end
100
+
101
+ def close_transaction_and_release_connection
102
+ existing_transaction_or_null&.close_async
103
+ ensure
104
+ release_connection_async
105
+ end
106
+
107
+ def ensure_no_open_tx_before_running_query
108
+ ensure_no_open_tx('Queries cannot be run directly on a session with an open transaction; either run from within the transaction or use a different session.')
109
+ end
110
+
111
+ def ensure_no_open_tx_before_starting_tx
112
+ ensure_no_open_tx('You cannot begin a transaction on a session with an open transaction; either run from within the transaction or use a different session.')
113
+ end
114
+
115
+ def ensure_no_open_tx(error_message)
116
+ existing_transaction_or_null&.then do
117
+ raise Neo4j::Driver::Exceptions::TransactionNestingException.new(error_message)
118
+ end
119
+ end
120
+
121
+ def existing_transaction_or_null
122
+ @transaction if @transaction&.open?
123
+ end
124
+
125
+ def ensure_session_is_open
126
+ unless @open.true?
127
+ raise Neo4j::Driver::Exceptions::ClientException.new('No more interaction with this session are allowed as the current session is already closed.')
128
+ end
129
+ end
130
+
131
+ # The {@link NetworkSessionConnectionContext#mode} can be mutable for a session connection context
132
+ class NetworkSessionConnectionContext
133
+ # This bookmark is only used for rediscovery.
134
+ # It has to be the initial bookmark given at the creation of the session.
135
+ # As only that bookmark could carry extra system bookmarks
136
+ attr_reader :database_name, :mode, :rediscovery_bookmark, :impersonated_user
137
+
138
+ def initialize(database_name, bookmark, impersonated_user)
139
+ @database_name = database_name
140
+ @rediscovery_bookmark = bookmark
141
+ @impersonated_user = impersonated_user
142
+ end
143
+
144
+ def context_with_mode(mode)
145
+ @mode = mode
146
+ self
147
+ end
148
+ end
149
+ end
150
+ end
151
+ end
152
+ end
@@ -0,0 +1,110 @@
1
+ module Neo4j::Driver
2
+ module Internal
3
+ module Async
4
+ module Outbound
5
+ class ChunkAwareByteBufOutput
6
+ include Packstream::PackStream::Packer
7
+ include Messaging::Common::CommonValuePacker
8
+
9
+ class ChunkBuffer < ::Async::IO::Buffer
10
+ include Packstream::PackOutput
11
+ alias write <<
12
+ end
13
+
14
+ def initialize(output, max_chunk_size: Connection::BoltProtocolUtil::DEFAULT_MAX_OUTBOUND_CHUNK_SIZE_BYTES)
15
+ @output = output
16
+ @max_chunk_size = verify_max_chunk_size(max_chunk_size)
17
+ @chunk = ChunkBuffer.new
18
+ end
19
+
20
+ def start
21
+ assert_not_started
22
+ @chunk.clear
23
+ end
24
+
25
+ def write_byte(value)
26
+ ensure_can_fit_in_current_chunk(1)
27
+ @chunk.write_byte(value)
28
+ self
29
+ end
30
+
31
+ def write(data)
32
+ offset = 0
33
+ length = data.bytesize
34
+
35
+ while offset < length
36
+ # Ensure there is an open chunk, and that it has at least one byte of space left
37
+ ensure_can_fit_in_current_chunk(1)
38
+
39
+ # Write as much as we can into the current chunk
40
+ amount_to_write = [available_bytes_in_current_chunk, length - offset].min
41
+
42
+ @chunk.write(data.byteslice(offset, amount_to_write))
43
+ offset += amount_to_write
44
+ end
45
+
46
+ self
47
+ end
48
+
49
+ def write_short(value)
50
+ ensure_can_fit_in_current_chunk(2)
51
+ @chunk.write_short(value)
52
+ self
53
+ end
54
+
55
+ def write_int(value)
56
+ ensure_can_fit_in_current_chunk(4)
57
+ @chunk.write_int(value)
58
+ self
59
+ end
60
+
61
+ def write_long(value)
62
+ ensure_can_fit_in_current_chunk(8)
63
+ @chunk.write_long(value)
64
+ self
65
+ end
66
+
67
+ def write_double(value)
68
+ ensure_can_fit_in_current_chunk(8)
69
+ @chunk.write_double(value)
70
+ self
71
+ end
72
+
73
+ def write_message_boundary
74
+ @output.write_short(0)
75
+ end
76
+
77
+ def write_chunk
78
+ @output.write_short(@chunk.bytesize)
79
+ @output.write(@chunk)
80
+ @chunk.clear
81
+ end
82
+
83
+ alias stop write_chunk
84
+
85
+ private
86
+
87
+ def ensure_can_fit_in_current_chunk(number_of_bytes)
88
+ write_chunk if @chunk.bytesize + number_of_bytes > @max_chunk_size
89
+ end
90
+
91
+ def available_bytes_in_current_chunk
92
+ @max_chunk_size - @chunk.bytesize
93
+ end
94
+
95
+ def assert_not_started
96
+ raise Neo4j::Driver::Exceptions::IllegalStateException.new('Already started') unless @chunk.empty?
97
+ end
98
+
99
+ def verify_max_chunk_size(max_chunk_size)
100
+ if max_chunk_size <= 0
101
+ raise ArgumentError.new("Max chunk size should be > 0, given: #{max_chunk_size}")
102
+ end
103
+
104
+ max_chunk_size
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,39 @@
1
+ module Neo4j::Driver
2
+ module Internal
3
+ module Async
4
+ module Outbound
5
+ class OutboundMessageHandler
6
+ NAME = self.class.name
7
+
8
+ def initialize(output, message_format, logger)
9
+ @output = output
10
+ @writer = message_format.new_writer(output)
11
+ @log = logger
12
+ end
13
+
14
+ def handler_added(ctx)
15
+ @log = Logging::ChannelActivityLogger.new(ctx.channel, @log, self.class)
16
+ end
17
+
18
+ def handler_removed(ctx)
19
+ @log = nil
20
+ end
21
+
22
+ def encode(msg)
23
+ @log.debug("C: #{msg}")
24
+
25
+ @output.start
26
+ begin
27
+ @writer.write(msg)
28
+ ensure
29
+ @output.stop
30
+ end
31
+
32
+ @output.write_message_boundary
33
+ # @log.debug( "C: #{}") if @log.debug_enabled?
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,63 @@
1
+ module Neo4j::Driver
2
+ module Internal
3
+ module Async
4
+ module Pool
5
+ class Channel < ::Async::Pool::Resource
6
+ attr :stream
7
+ attr_accessor :version, :protocol, :message_format, :message_dispatcher
8
+ attr :attributes # should be attr
9
+
10
+ def initialize(address, connector, logger)
11
+ super()
12
+ @attributes = Connection::ChannelAttributes.new
13
+ @stream = Connection::Stream.new(connector.connect(address))
14
+ @stream.write(Connection::BoltProtocolUtil.handshake_buf)
15
+ @stream.flush
16
+ Connection::HandshakeHandler.new(logger).decode(self)
17
+ stream_reader = Connection::StreamReader.new(@stream)
18
+ stream_writer = Outbound::ChunkAwareByteBufOutput.new(@stream)
19
+ @message_dispatcher = Inbound::InboundMessageDispatcher.new(self, logger)
20
+ @attributes[:message_dispatcher] = @message_dispatcher
21
+ @outbound_handler = Outbound::OutboundMessageHandler.new(stream_writer, message_format, logger)
22
+ @common_message_reader = Messaging::Common::CommonMessageReader.new(stream_reader)
23
+ connector.initialize_channel(self, protocol)
24
+ end
25
+
26
+ def close
27
+ super unless closed? # Should this be conditional?
28
+ @stream.close
29
+ end
30
+
31
+ def write(message)
32
+ @outbound_handler.encode(message)
33
+ end
34
+
35
+ def write_and_flush(message)
36
+ write(message)
37
+ @stream.flush
38
+ ensure_response_handling
39
+ end
40
+
41
+ private
42
+
43
+ def bracketless(host)
44
+ host.delete_prefix('[').delete_suffix(']')
45
+ end
46
+
47
+ def ensure_response_handling
48
+ # probably should be synchronized
49
+ return if @handling_active
50
+ @handling_active = true
51
+ while @message_dispatcher.queued_handlers_count > 0 do
52
+ @common_message_reader.read(@message_dispatcher)
53
+ end
54
+ @handling_active = false
55
+ rescue
56
+ @handling_active = false
57
+ raise
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,149 @@
1
+ module Neo4j::Driver
2
+ module Internal
3
+ module Async
4
+ module Pool
5
+ class ConnectionPoolImpl
6
+ def initialize(connector, settings, logger)
7
+ @connector = connector
8
+ @settings = settings
9
+ @log = logger
10
+ @address_to_pool_lock = Concurrent::ReentrantReadWriteLock.new
11
+ @address_to_pool = {}
12
+ @closed = Concurrent::AtomicBoolean.new
13
+ end
14
+
15
+ def acquire(address)
16
+ @log.debug("Acquiring a connection from pool towards #{address}")
17
+
18
+ assert_not_closed
19
+ pool = get_or_create_pool(address)
20
+
21
+ begin
22
+ channel = pool.acquire
23
+ rescue => error
24
+ process_acquisition_error(pool, address, error)
25
+ end
26
+ assert_not_closed(address, channel, pool)
27
+ NetworkConnection.new(channel, pool, @log)
28
+ end
29
+
30
+ def retain_all(addresses_to_retain)
31
+ @address_to_pool_lock.with_write_lock do
32
+ @address_to_pool.each do |address, pool|
33
+ unless addresses_to_retain.include?(address)
34
+ active_channels = @netty_channel_tracker.in_use_channel_count(address)
35
+ if active_channels.zero?
36
+ # address is not present in updated routing table and has no active connections
37
+ # it's now safe to terminate corresponding connection pool and forget about it
38
+ @address_to_pool.delete(address)
39
+ if pool
40
+ @log.info("Closing connection pool towards #{address}, it has no active connections and is not in the routing table registry.")
41
+ close_pool_in_background(address, pool)
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ def in_use_connections(address)
50
+ @netty_channel_tracker.in_use_channel_count(address)
51
+ end
52
+
53
+ def idle_connections(address)
54
+ @netty_channel_tracker.idle_channel_count(address)
55
+ end
56
+
57
+ def close
58
+ if @closed.make_true
59
+ @address_to_pool_lock.with_write_lock do
60
+ # We can only shutdown event loop group when all netty pools are fully closed,
61
+ # otherwise the netty pools might missing threads (from event loop group) to execute clean ups.
62
+ close_all_pools
63
+ @address_to_pool.clear
64
+ end
65
+ end
66
+ end
67
+
68
+ def open?(address)
69
+ @address_to_pool_lock.with_read_lock { @address_to_pool.key?(address) }
70
+ end
71
+
72
+ def to_string
73
+ @address_to_pool_lock.with_read_lock { "ConnectionPoolImpl{ pools=#{@address_to_pool}}" }
74
+ end
75
+
76
+ private
77
+
78
+ def process_acquisition_error(pool, server_address, error)
79
+ if error.is_a?(::Async::TimeoutError)
80
+ # NettyChannelPool returns future failed with TimeoutException if acquire operation takes more than
81
+ # configured time, translate this exception to a prettier one and re-throw
82
+ raise Neo4j::Driver::Exceptions::ClientException.new("Unable to acquire connection from the pool within configured maximum time of #{@settings.connection_acquisition_timeout.inspect}")
83
+ # elsif pool.closed?
84
+ # There is a race condition where a thread tries to acquire a connection while the pool is closed by another concurrent thread.
85
+ # Treat as failed to obtain connection for a direct driver. For a routing driver, this error should be retried.
86
+ # raise Neo4j::Driver::Exceptions::ServiceUnavailableException, "Connection pool for server #{server_address} is closed while acquiring a connection."
87
+ else
88
+ # some unknown error happened during connection acquisition, propagate it
89
+ raise error
90
+ end
91
+ end
92
+
93
+ def assert_not_closed(address = nil, channel = nil, pool = nil)
94
+ if @closed.true?
95
+ if address
96
+ pool.release(channel)
97
+ close_pool_in_background(address, pool)
98
+ @address_to_pool_lock.with_write_lock { @address_to_pool.delete(address) }
99
+ assert_not_closed
100
+ end
101
+ raise Exceptions::IllegalStateException, Spi::ConnectionPool::CONNECTION_POOL_CLOSED_ERROR_MESSAGE
102
+ end
103
+ end
104
+
105
+ # for testing only
106
+ protected def pool(address)
107
+ @address_to_pool_lock.with_read_lock { @address_to_pool[address] }
108
+ end
109
+
110
+ def new_pool(address)
111
+ Controller.wrap(limit: @settings.max_connection_pool_size, acquisition_timeout: @settings.connection_acquisition_timeout) { Channel.new(address, @connector, @log) }
112
+ end
113
+
114
+ def get_or_create_pool(address)
115
+ @address_to_pool_lock.with_read_lock { @address_to_pool[address] } ||
116
+ @address_to_pool_lock.with_write_lock do
117
+ new_pool(address)&.tap do |pool|
118
+ # before the connection pool is added I can add the metrics for the pool.
119
+ # @metrics_listener.put_pool_metrics(pool.object_id, address, self)
120
+ @address_to_pool[address] = pool
121
+ end
122
+ end
123
+ end
124
+
125
+ def close_pool(pool)
126
+ pool.close
127
+ end
128
+
129
+ def close_pool_in_background(address, pool)
130
+ Async do
131
+ # Close in the background
132
+ close_pool(pool)
133
+ rescue => error
134
+ @log.warn("An error occurred while closing connection pool towards #{address}.", error)
135
+ end
136
+ end
137
+
138
+ def close_all_pools
139
+ @address_to_pool.map do |address, pool|
140
+ @log.info("Closing connection pool towards #{address}")
141
+ # Wait for all pools to be closed.
142
+ close_pool(pool)
143
+ end
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,25 @@
1
+ module Neo4j::Driver
2
+ module Internal
3
+ module Async
4
+ module Pool
5
+ class Controller < ::Async::Pool::Controller
6
+ def initialize(constructor, limit: nil, concurrency: nil, acquisition_timeout: nil)
7
+ super(constructor, limit: limit, concurrency: concurrency)
8
+ @acquisition_timeout = acquisition_timeout
9
+ end
10
+
11
+ def wait_for_resource
12
+ case @acquisition_timeout
13
+ when nil
14
+ super
15
+ when 0
16
+ available_resource or raise ::Async::TimeoutError
17
+ else
18
+ ::Async::Task.current.with_timeout(@acquisition_timeout) { super }
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,87 @@
1
+ module Neo4j::Driver
2
+ module Internal
3
+ module Async
4
+ module Pool
5
+ class NettyChannelHealthChecker
6
+ attr_reader :pool_settings, :clock, :logger, :log, :min_creation_timestamp_millis_opt
7
+
8
+ def initialize(pool_settings, clock, logger)
9
+ @pool_settings = pool_settings
10
+ @clock = clock
11
+ @log = logger
12
+ @min_creation_timestamp_millis_opt = java.util.concurrent.atomic.AtomicReference.new(java.util.Optional.empty)
13
+ end
14
+
15
+ def is_healthy(channel)
16
+ return channel.event_loop.new_succeeded_future(false) if is_too_old?(channel)
17
+
18
+ return ping(channel) if has_been_idle_for_too_long?(channel)
19
+
20
+ ACTIVE.is_healthy(channel)
21
+ end
22
+
23
+ def on_expired(e, channel)
24
+ ts = Connection::ChannelAttributes.creation_timestamp(channel)
25
+
26
+ # Override current value ONLY if the new one is greater
27
+ min_creation_timestamp_millis_opt.get_and_update do |prev|
28
+ java.util.Optional.of(prev.filter(-> (prev_ts) { ts <= prev_ts }.or_else(ts)))
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def is_too_old?(channel)
35
+ creation_timestamp_millis = Connection::ChannelAttributes.creation_timestamp(channel)
36
+ min_creation_timestamp_millis_opt = min_creation_timestamp_millis_opt.get
37
+
38
+ if min_creation_timestamp_millis_opt.present? && creation_timestamp_millis <= min_creation_timestamp_millis_opt.get
39
+ log.debug("The channel #{channel} is marked for closure as its creation timestamp is older than or equal to the acceptable minimum timestamp: #{creation_timestamp_millis} <= #{min_creation_timestamp_millis_opt.get}")
40
+ return true
41
+ end
42
+
43
+ if pool_settings.max_connection_lifetime_enabled
44
+ current_timestamp_millis = clock.millis
45
+
46
+ age_millis = current_timestamp_millis - creation_timestamp_millis
47
+ max_age_millis = pool_settings.max_connection_lifetime
48
+
49
+ too_old = age_millis > max_age_millis
50
+
51
+ if too_old
52
+ log.debug("Failed acquire channel #{channel} from the pool because it is too old: #{age_millis} > #{max_age_millis}")
53
+ end
54
+ return too_old
55
+ end
56
+
57
+ false
58
+ end
59
+
60
+ def has_been_idle_for_too_long?(channel)
61
+ if pool_settings.idle_time_before_connection_test_enabled?
62
+ last_used_timestamp = Connection::ChannelAttributes.last_used_timestamp(channel)
63
+ if !last_used_timestamp.nil?
64
+ idle_time = clock.millis - last_used_timestamp
65
+ idle_too_long = idle_time > pool_settings.idle_time_before_connection_test
66
+
67
+ if idle_too_long
68
+ log.debug( "Channel #{channel} has been idle for #{idle_time} and needs a ping")
69
+ end
70
+
71
+ return idle_too_long
72
+ end
73
+ end
74
+ false
75
+ end
76
+
77
+ def ping(channel)
78
+ result = channel.event_loop.new_promise
79
+ Connection::ChannelAttributes.message_dispatcher.enqueue(Handlers::PingResponseHandler.new(result, channel, logger))
80
+ channel.write_and_flush(Messaging::Request::ResetMessage::RESET, channel.void_promise)
81
+ result
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,52 @@
1
+ module Neo4j::Driver
2
+ module Internal
3
+ module Async
4
+ module Pool
5
+ class NettyChannelPool
6
+ # Unlimited amount of parties are allowed to request channels from the pool.
7
+ MAX_PENDING_ACQUIRES = nil
8
+
9
+ # Do not check channels when they are returned to the pool.
10
+ RELEASE_HEALTH_CHECK = false
11
+
12
+ attr_reader :id
13
+
14
+ def initialize(address, connector, bootstrap, handler, health_check, acquire_timeout_millis, max_connections)
15
+ java.util.Objects.require_non_null(address)
16
+ java.util.Objects.require_non_null(connector)
17
+ java.util.Objects.require_non_null(handler)
18
+ @id = pool_id(address)
19
+ @delegate = Java::IoNettyChannelPool::FixedChannelPool.new(bootstrap, handler, health_check,
20
+ Java::IoNettyChannelPool::FixedChannelPool::AcquireTimeoutAction::FAIL, acquire_timeout_millis,
21
+ max_connections, MAX_PENDING_ACQUIRES, RELEASE_HEALTH_CHECK)
22
+ end
23
+
24
+ def close
25
+ if closed.compare_and_set(false, true)
26
+ Util::Futurs.as_completion_stage(delegate.close_async, close_future)
27
+ end
28
+ close_future
29
+ end
30
+
31
+ def acquire
32
+ Util::Futurs.as_completion_stage(delegate.acquire)
33
+ end
34
+
35
+ def release(channel)
36
+ Util::Futurs.as_completion_stage(delegate.release(channel))
37
+ end
38
+
39
+ def is_closed?
40
+ closed.get
41
+ end
42
+
43
+ private
44
+
45
+ def pool_id(server_address)
46
+ [server_address.host, server_address.port, self.hash_code]
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end