neo4j-ruby-driver 1.7.4 → 4.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (342) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +37 -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/driver/types/time.rb +4 -2
  33. data/lib/neo4j_ruby_driver.rb +5 -10
  34. data/{ffi → ruby}/neo4j/driver/access_mode.rb +2 -2
  35. data/ruby/neo4j/driver/auth_tokens.rb +34 -0
  36. data/ruby/neo4j/driver/bookmark.rb +21 -0
  37. data/ruby/neo4j/driver/config.rb +89 -0
  38. data/ruby/neo4j/driver/graph_database.rb +80 -0
  39. data/ruby/neo4j/driver/internal/async/connection/bolt_protocol_util.rb +51 -0
  40. data/ruby/neo4j/driver/internal/async/connection/bootstrap_factory.rb +22 -0
  41. data/ruby/neo4j/driver/internal/async/connection/channel_attributes.rb +31 -0
  42. data/ruby/neo4j/driver/internal/async/connection/channel_connected_listener.rb +32 -0
  43. data/ruby/neo4j/driver/internal/async/connection/channel_connector_impl.rb +83 -0
  44. data/ruby/neo4j/driver/internal/async/connection/channel_pipeline_builder_impl.rb +22 -0
  45. data/ruby/neo4j/driver/internal/async/connection/direct_connection.rb +30 -0
  46. data/ruby/neo4j/driver/internal/async/connection/event_loop_group_factory.rb +83 -0
  47. data/ruby/neo4j/driver/internal/async/connection/handshake_completed_listener.rb +27 -0
  48. data/ruby/neo4j/driver/internal/async/connection/handshake_handler.rb +113 -0
  49. data/ruby/neo4j/driver/internal/async/connection/netty_channel_initializer.rb +57 -0
  50. data/ruby/neo4j/driver/internal/async/connection/netty_domain_name_resolver.rb +26 -0
  51. data/ruby/neo4j/driver/internal/async/connection/netty_domain_name_resolver_group.rb +19 -0
  52. data/ruby/neo4j/driver/internal/async/connection/routing_connection.rb +36 -0
  53. data/ruby/neo4j/driver/internal/async/connection/stream.rb +12 -0
  54. data/ruby/neo4j/driver/internal/async/connection/stream_reader.rb +16 -0
  55. data/ruby/neo4j/driver/internal/async/connection_context.rb +10 -0
  56. data/ruby/neo4j/driver/internal/async/immutable_connection_context.rb +24 -0
  57. data/ruby/neo4j/driver/internal/async/inbound/byte_buf_input.rb +30 -0
  58. data/ruby/neo4j/driver/internal/async/inbound/channel_error_handler.rb +77 -0
  59. data/ruby/neo4j/driver/internal/async/inbound/chunk_decoder.rb +41 -0
  60. data/ruby/neo4j/driver/internal/async/inbound/connect_timeout_handler.rb +32 -0
  61. data/ruby/neo4j/driver/internal/async/inbound/connection_read_timeout_handler.rb +17 -0
  62. data/ruby/neo4j/driver/internal/async/inbound/inbound_message_dispatcher.rb +171 -0
  63. data/ruby/neo4j/driver/internal/async/inbound/inbound_message_handler.rb +42 -0
  64. data/ruby/neo4j/driver/internal/async/inbound/message_decoder.rb +51 -0
  65. data/ruby/neo4j/driver/internal/async/internal_async_session.rb +98 -0
  66. data/ruby/neo4j/driver/internal/async/internal_async_transaction.rb +13 -0
  67. data/ruby/neo4j/driver/internal/async/leak_logging_network_session.rb +34 -0
  68. data/ruby/neo4j/driver/internal/async/network_connection.rb +194 -0
  69. data/ruby/neo4j/driver/internal/async/network_session.rb +150 -0
  70. data/ruby/neo4j/driver/internal/async/outbound/chunk_aware_byte_buf_output.rb +110 -0
  71. data/ruby/neo4j/driver/internal/async/outbound/outbound_message_handler.rb +39 -0
  72. data/ruby/neo4j/driver/internal/async/pool/channel.rb +62 -0
  73. data/ruby/neo4j/driver/internal/async/pool/channel_pool.rb +31 -0
  74. data/ruby/neo4j/driver/internal/async/pool/channel_tracker.rb +135 -0
  75. data/ruby/neo4j/driver/internal/async/pool/connection_pool_impl.rb +156 -0
  76. data/ruby/neo4j/driver/internal/async/pool/netty_channel_health_checker.rb +87 -0
  77. data/ruby/neo4j/driver/internal/async/pool/netty_channel_pool.rb +52 -0
  78. data/ruby/neo4j/driver/internal/async/pool/network_connection_factory.rb +21 -0
  79. data/ruby/neo4j/driver/internal/async/pool/pool_settings.rb +34 -0
  80. data/ruby/neo4j/driver/internal/async/pool/timed_stack.rb +15 -0
  81. data/ruby/neo4j/driver/internal/async/result_cursors_holder.rb +17 -0
  82. data/ruby/neo4j/driver/internal/async/unmanaged_transaction.rb +212 -0
  83. data/ruby/neo4j/driver/internal/bookmark_holder.rb +9 -0
  84. data/ruby/neo4j/driver/internal/cluster/cluster_composition.rb +48 -0
  85. data/ruby/neo4j/driver/internal/cluster/cluster_composition_lookup_result.rb +14 -0
  86. data/ruby/neo4j/driver/internal/cluster/cluster_routing_table.rb +122 -0
  87. data/ruby/neo4j/driver/internal/cluster/identity_resolver.rb +10 -0
  88. data/ruby/neo4j/driver/internal/cluster/loadbalancing/least_connected_load_balancing_strategy.rb +68 -0
  89. data/ruby/neo4j/driver/internal/cluster/loadbalancing/load_balancer.rb +125 -0
  90. data/ruby/neo4j/driver/internal/cluster/loadbalancing/round_robin_array_index.rb +13 -0
  91. data/ruby/neo4j/driver/internal/cluster/multi_databases_routing_procedure_runner.rb +31 -0
  92. data/ruby/neo4j/driver/internal/cluster/rediscovery_impl.rb +147 -0
  93. data/ruby/neo4j/driver/internal/cluster/route_message_routing_procedure_runner.rb +43 -0
  94. data/ruby/neo4j/driver/internal/cluster/routing_context.rb +77 -0
  95. data/ruby/neo4j/driver/internal/cluster/routing_procedure_cluster_composition_provider.rb +60 -0
  96. data/ruby/neo4j/driver/internal/cluster/routing_procedure_response.rb +35 -0
  97. data/ruby/neo4j/driver/internal/cluster/routing_settings.rb +24 -0
  98. data/ruby/neo4j/driver/internal/cluster/routing_table_handler_impl.rb +95 -0
  99. data/ruby/neo4j/driver/internal/cluster/routing_table_registry_impl.rb +121 -0
  100. data/ruby/neo4j/driver/internal/cluster/single_database_routing_procedure_runner.rb +73 -0
  101. data/ruby/neo4j/driver/internal/connection_settings.rb +16 -0
  102. data/ruby/neo4j/driver/internal/cursor/async_result_cursor_impl.rb +55 -0
  103. data/ruby/neo4j/driver/internal/cursor/async_result_cursor_only_factory.rb +24 -0
  104. data/ruby/neo4j/driver/internal/cursor/disposable_async_result_cursor.rb +61 -0
  105. data/ruby/neo4j/driver/internal/cursor/result_cursor_factory_impl.rb +24 -0
  106. data/ruby/neo4j/driver/internal/cursor/rx_result_cursor_impl.rb +110 -0
  107. data/ruby/neo4j/driver/internal/database_name_util.rb +37 -0
  108. data/ruby/neo4j/driver/internal/default_bookmark_holder.rb +9 -0
  109. data/ruby/neo4j/driver/internal/default_domain_name_resolver.rb +11 -0
  110. data/ruby/neo4j/driver/internal/direct_connection_provider.rb +40 -0
  111. data/ruby/neo4j/driver/internal/driver_factory.rb +126 -0
  112. data/ruby/neo4j/driver/internal/handlers/begin_tx_response_handler.rb +20 -0
  113. data/ruby/neo4j/driver/internal/handlers/channel_releasing_reset_response_handler.rb +30 -0
  114. data/ruby/neo4j/driver/internal/handlers/commit_tx_response_handler.rb +25 -0
  115. data/ruby/neo4j/driver/internal/handlers/hello_response_handler.rb +65 -0
  116. data/ruby/neo4j/driver/internal/handlers/init_response_handler.rb +34 -0
  117. data/ruby/neo4j/driver/internal/handlers/legacy_pull_all_response_handler.rb +199 -0
  118. data/ruby/neo4j/driver/internal/handlers/no_op_response_handler.rb +16 -0
  119. data/ruby/neo4j/driver/internal/handlers/ping_response_handler.rb +29 -0
  120. data/ruby/neo4j/driver/internal/handlers/pull_handlers.rb +32 -0
  121. data/ruby/neo4j/driver/internal/handlers/pulln/auto_pull_response_handler.rb +168 -0
  122. data/ruby/neo4j/driver/internal/handlers/pulln/basic_pull_response_handler.rb +298 -0
  123. data/ruby/neo4j/driver/internal/handlers/pulln/fetch_size_util.rb +20 -0
  124. data/ruby/neo4j/driver/internal/handlers/reset_response_handler.rb +34 -0
  125. data/ruby/neo4j/driver/internal/handlers/rollback_tx_response_handler.rb +25 -0
  126. data/ruby/neo4j/driver/internal/handlers/route_message_response_handler.rb +21 -0
  127. data/ruby/neo4j/driver/internal/handlers/routing_response_handler.rb +70 -0
  128. data/ruby/neo4j/driver/internal/handlers/run_response_handler.rb +38 -0
  129. data/ruby/neo4j/driver/internal/handlers/session_pull_response_completion_listener.rb +34 -0
  130. data/ruby/neo4j/driver/internal/handlers/transaction_pull_response_completion_listener.rb +20 -0
  131. data/ruby/neo4j/driver/internal/impersonation_util.rb +22 -0
  132. data/ruby/neo4j/driver/internal/internal_bookmark.rb +36 -0
  133. data/ruby/neo4j/driver/internal/internal_database_name.rb +9 -0
  134. data/ruby/neo4j/driver/internal/internal_driver.rb +74 -0
  135. data/ruby/neo4j/driver/internal/internal_entity.rb +20 -0
  136. data/ruby/neo4j/driver/internal/internal_node.rb +21 -0
  137. data/ruby/neo4j/driver/internal/internal_pair.rb +9 -0
  138. data/ruby/neo4j/driver/internal/internal_path.rb +35 -0
  139. data/ruby/neo4j/driver/internal/internal_point2_d.rb +9 -0
  140. data/ruby/neo4j/driver/internal/internal_point3_d.rb +6 -0
  141. data/{ffi → ruby}/neo4j/driver/internal/internal_record.rb +2 -1
  142. data/ruby/neo4j/driver/internal/internal_relationship.rb +26 -0
  143. data/ruby/neo4j/driver/internal/internal_result.rb +49 -0
  144. data/ruby/neo4j/driver/internal/internal_session.rb +81 -0
  145. data/ruby/neo4j/driver/internal/internal_transaction.rb +48 -0
  146. data/ruby/neo4j/driver/internal/logging/channel_activity_logger.rb +29 -0
  147. data/ruby/neo4j/driver/internal/logging/channel_error_logger.rb +17 -0
  148. data/ruby/neo4j/driver/internal/logging/prefixed_logger.rb +19 -0
  149. data/ruby/neo4j/driver/internal/logging/reformatted_logger.rb +17 -0
  150. data/ruby/neo4j/driver/internal/messaging/abstract_message_writer.rb +23 -0
  151. data/ruby/neo4j/driver/internal/messaging/bolt_protocol.rb +30 -0
  152. data/ruby/neo4j/driver/internal/messaging/bolt_protocol_version.rb +48 -0
  153. data/ruby/neo4j/driver/internal/messaging/common/common_message_reader.rb +51 -0
  154. data/ruby/neo4j/driver/internal/messaging/common/common_value.rb +31 -0
  155. data/ruby/neo4j/driver/internal/messaging/common/common_value_packer.rb +101 -0
  156. data/ruby/neo4j/driver/internal/messaging/common/common_value_unpacker.rb +234 -0
  157. data/ruby/neo4j/driver/internal/messaging/encode/begin_message_encoder.rb +15 -0
  158. data/ruby/neo4j/driver/internal/messaging/encode/commit_message_encoder.rb +14 -0
  159. data/ruby/neo4j/driver/internal/messaging/encode/discard_all_message_encoder.rb +14 -0
  160. data/ruby/neo4j/driver/internal/messaging/encode/discard_message_encoder.rb +15 -0
  161. data/ruby/neo4j/driver/internal/messaging/encode/goodbye_message_encoder.rb +14 -0
  162. data/ruby/neo4j/driver/internal/messaging/encode/hello_message_encoder.rb +15 -0
  163. data/ruby/neo4j/driver/internal/messaging/encode/init_message_encoder.rb +16 -0
  164. data/ruby/neo4j/driver/internal/messaging/encode/pull_all_message_encoder.rb +14 -0
  165. data/ruby/neo4j/driver/internal/messaging/encode/pull_message_encoder.rb +15 -0
  166. data/ruby/neo4j/driver/internal/messaging/encode/reset_message_encoder.rb +14 -0
  167. data/ruby/neo4j/driver/internal/messaging/encode/rollback_message_encoder.rb +14 -0
  168. data/ruby/neo4j/driver/internal/messaging/encode/route_message_encoder.rb +24 -0
  169. data/ruby/neo4j/driver/internal/messaging/encode/route_v44_message_encoder.rb +22 -0
  170. data/ruby/neo4j/driver/internal/messaging/encode/run_message_encoder.rb +16 -0
  171. data/ruby/neo4j/driver/internal/messaging/encode/run_with_metadata_message_encoder.rb +17 -0
  172. data/ruby/neo4j/driver/internal/messaging/request/abstract_streaming_message.rb +25 -0
  173. data/ruby/neo4j/driver/internal/messaging/request/begin_message.rb +25 -0
  174. data/ruby/neo4j/driver/internal/messaging/request/commit_message.rb +20 -0
  175. data/ruby/neo4j/driver/internal/messaging/request/discard_all_message.rb +20 -0
  176. data/ruby/neo4j/driver/internal/messaging/request/discard_message.rb +23 -0
  177. data/ruby/neo4j/driver/internal/messaging/request/goodbye_message.rb +20 -0
  178. data/ruby/neo4j/driver/internal/messaging/request/hello_message.rb +31 -0
  179. data/ruby/neo4j/driver/internal/messaging/request/init_message.rb +19 -0
  180. data/ruby/neo4j/driver/internal/messaging/request/message_with_metadata.rb +10 -0
  181. data/ruby/neo4j/driver/internal/messaging/request/multi_database_util.rb +26 -0
  182. data/ruby/neo4j/driver/internal/messaging/request/pull_all_message.rb +23 -0
  183. data/ruby/neo4j/driver/internal/messaging/request/pull_message.rb +22 -0
  184. data/ruby/neo4j/driver/internal/messaging/request/reset_message.rb +32 -0
  185. data/ruby/neo4j/driver/internal/messaging/request/rollback_message.rb +20 -0
  186. data/ruby/neo4j/driver/internal/messaging/request/route_message.rb +28 -0
  187. data/ruby/neo4j/driver/internal/messaging/request/run_message.rb +23 -0
  188. data/ruby/neo4j/driver/internal/messaging/request/run_with_metadata_message.rb +49 -0
  189. data/ruby/neo4j/driver/internal/messaging/request/transaction_metadata_builder.rb +24 -0
  190. data/ruby/neo4j/driver/internal/messaging/response/failure_message.rb +40 -0
  191. data/ruby/neo4j/driver/internal/messaging/response/ignored_message.rb +29 -0
  192. data/ruby/neo4j/driver/internal/messaging/response/record_message.rb +33 -0
  193. data/ruby/neo4j/driver/internal/messaging/response/success_message.rb +34 -0
  194. data/ruby/neo4j/driver/internal/messaging/v3/bolt_protocol_v3.rb +82 -0
  195. data/ruby/neo4j/driver/internal/messaging/v3/message_format_v3.rb +17 -0
  196. data/ruby/neo4j/driver/internal/messaging/v3/message_writer_v3.rb +27 -0
  197. data/ruby/neo4j/driver/internal/messaging/v4/bolt_protocol_v4.rb +29 -0
  198. data/ruby/neo4j/driver/internal/messaging/v4/message_format_v4.rb +17 -0
  199. data/ruby/neo4j/driver/internal/messaging/v4/message_writer_v4.rb +17 -0
  200. data/ruby/neo4j/driver/internal/messaging/v41/bolt_protocol_v41.rb +25 -0
  201. data/ruby/neo4j/driver/internal/messaging/v42/bolt_protocol_v42.rb +13 -0
  202. data/ruby/neo4j/driver/internal/messaging/v43/bolt_protocol_v43.rb +19 -0
  203. data/ruby/neo4j/driver/internal/messaging/v43/message_format_v43.rb +18 -0
  204. data/ruby/neo4j/driver/internal/messaging/v43/message_writer_v43.rb +20 -0
  205. data/ruby/neo4j/driver/internal/messaging/v44/bolt_protocol_v44.rb +17 -0
  206. data/ruby/neo4j/driver/internal/messaging/v44/message_format_v44.rb +18 -0
  207. data/ruby/neo4j/driver/internal/messaging/v44/message_writer_v44.rb +15 -0
  208. data/ruby/neo4j/driver/internal/metrics/connection_pool_metrics_listener.rb +34 -0
  209. data/ruby/neo4j/driver/internal/metrics/internal_abstract_metrics.rb +46 -0
  210. data/ruby/neo4j/driver/internal/metrics/internal_connection_pool_metrics.rb +105 -0
  211. data/ruby/neo4j/driver/internal/metrics/internal_metrics.rb +82 -0
  212. data/ruby/neo4j/driver/internal/metrics/internal_metrics_provider.rb +18 -0
  213. data/ruby/neo4j/driver/internal/metrics/listener_event.rb +17 -0
  214. data/ruby/neo4j/driver/internal/metrics/metrics_provider.rb +24 -0
  215. data/ruby/neo4j/driver/internal/metrics/time_recorder_listener_event.rb +15 -0
  216. data/ruby/neo4j/driver/internal/packstream/byte_array_incompatible_packer.rb +12 -0
  217. data/ruby/neo4j/driver/internal/packstream/pack_input.rb +47 -0
  218. data/ruby/neo4j/driver/internal/packstream/pack_output.rb +39 -0
  219. data/ruby/neo4j/driver/internal/packstream/pack_stream.rb +326 -0
  220. data/ruby/neo4j/driver/internal/packstream/pack_type.rb +17 -0
  221. data/ruby/neo4j/driver/internal/read_only_bookmark_holder.rb +13 -0
  222. data/ruby/neo4j/driver/internal/resolved_bolt_server_address.rb +35 -0
  223. data/ruby/neo4j/driver/internal/retry/exponential_backoff_retry_logic.rb +151 -0
  224. data/ruby/neo4j/driver/internal/revocation_strategy.rb +19 -0
  225. data/ruby/neo4j/driver/internal/scheme.rb +32 -0
  226. data/ruby/neo4j/driver/internal/security/internal_auth_token.rb +15 -0
  227. data/ruby/neo4j/driver/internal/security/security_plan_impl.rb +48 -0
  228. data/ruby/neo4j/driver/internal/security_setting.rb +66 -0
  229. data/ruby/neo4j/driver/internal/session_factory_impl.rb +32 -0
  230. data/ruby/neo4j/driver/internal/spi/connection.rb +19 -0
  231. data/ruby/neo4j/driver/internal/spi/connection_pool.rb +9 -0
  232. data/ruby/neo4j/driver/internal/spi/response_handler.rb +23 -0
  233. data/ruby/neo4j/driver/internal/summary/internal_database_info.rb +7 -0
  234. data/ruby/neo4j/driver/internal/summary/internal_input_position.rb +11 -0
  235. data/ruby/neo4j/driver/internal/summary/internal_notification.rb +16 -0
  236. data/ruby/neo4j/driver/internal/summary/internal_plan.rb +41 -0
  237. data/ruby/neo4j/driver/internal/summary/internal_profiled_plan.rb +32 -0
  238. data/ruby/neo4j/driver/internal/summary/internal_result_summary.rb +33 -0
  239. data/ruby/neo4j/driver/internal/summary/internal_server_info.rb +6 -0
  240. data/ruby/neo4j/driver/internal/summary/internal_summary_counters.rb +18 -0
  241. data/ruby/neo4j/driver/internal/svm/netty_substitutions.rb +196 -0
  242. data/ruby/neo4j/driver/internal/svm/z_lib_substitutions.rb +21 -0
  243. data/ruby/neo4j/driver/internal/util/certificate_tool.rb +65 -0
  244. data/ruby/neo4j/driver/internal/util/clock.rb +29 -0
  245. data/ruby/neo4j/driver/internal/util/error_util.rb +104 -0
  246. data/ruby/neo4j/driver/internal/util/extract.rb +123 -0
  247. data/ruby/neo4j/driver/internal/util/format.rb +39 -0
  248. data/ruby/neo4j/driver/internal/util/futures.rb +99 -0
  249. data/ruby/neo4j/driver/internal/util/iterables.rb +35 -0
  250. data/ruby/neo4j/driver/internal/util/lock_util.rb +23 -0
  251. data/ruby/neo4j/driver/internal/util/metadata_extractor.rb +107 -0
  252. data/ruby/neo4j/driver/internal/util/mutex.rb +9 -0
  253. data/ruby/neo4j/driver/internal/util/preconditions.rb +16 -0
  254. data/ruby/neo4j/driver/internal/util/result_holder.rb +72 -0
  255. data/ruby/neo4j/driver/internal/util/server_version.rb +60 -0
  256. data/ruby/neo4j/driver/logging1.rb +51 -0
  257. data/ruby/neo4j/driver/net/server_address.rb +9 -0
  258. data/ruby/neo4j/driver/query.rb +48 -0
  259. data/ruby/neo4j/driver/records.rb +13 -0
  260. data/ruby/neo4j/driver/transaction_config.rb +50 -0
  261. data/ruby/neo4j/driver/values.rb +26 -0
  262. data/{lib → ruby}/neo4j/driver/version.rb +1 -1
  263. data/ruby/neo4j/driver.rb +29 -0
  264. metadata +264 -101
  265. data/ffi/bolt/address.rb +0 -11
  266. data/ffi/bolt/address_resolver.rb +0 -12
  267. data/ffi/bolt/address_set.rb +0 -9
  268. data/ffi/bolt/auth.rb +0 -10
  269. data/ffi/bolt/auto_releasable.rb +0 -22
  270. data/ffi/bolt/boolean.rb +0 -9
  271. data/ffi/bolt/bytes.rb +0 -10
  272. data/ffi/bolt/config.rb +0 -45
  273. data/ffi/bolt/connection.rb +0 -44
  274. data/ffi/bolt/connector.rb +0 -17
  275. data/ffi/bolt/dictionary.rb +0 -15
  276. data/ffi/bolt/error.rb +0 -74
  277. data/ffi/bolt/float.rb +0 -9
  278. data/ffi/bolt/integer.rb +0 -9
  279. data/ffi/bolt/library.rb +0 -12
  280. data/ffi/bolt/lifecycle.rb +0 -9
  281. data/ffi/bolt/list.rb +0 -10
  282. data/ffi/bolt/log.rb +0 -16
  283. data/ffi/bolt/socket_options.rb +0 -14
  284. data/ffi/bolt/status.rb +0 -25
  285. data/ffi/bolt/string.rb +0 -9
  286. data/ffi/bolt/structure.rb +0 -10
  287. data/ffi/bolt/value.rb +0 -35
  288. data/ffi/neo4j/driver/auth_tokens.rb +0 -18
  289. data/ffi/neo4j/driver/config.rb +0 -40
  290. data/ffi/neo4j/driver/graph_database.rb +0 -52
  291. data/ffi/neo4j/driver/internal/async/access_mode_connection.rb +0 -19
  292. data/ffi/neo4j/driver/internal/async/direct_connection.rb +0 -106
  293. data/ffi/neo4j/driver/internal/bolt_server_address.rb +0 -18
  294. data/ffi/neo4j/driver/internal/bookmarks_holder.rb +0 -30
  295. data/ffi/neo4j/driver/internal/direct_connection_provider.rb +0 -28
  296. data/ffi/neo4j/driver/internal/driver_factory.rb +0 -125
  297. data/ffi/neo4j/driver/internal/error_handling.rb +0 -112
  298. data/ffi/neo4j/driver/internal/explicit_transaction.rb +0 -146
  299. data/ffi/neo4j/driver/internal/handlers/pull_all_response_handler.rb +0 -104
  300. data/ffi/neo4j/driver/internal/handlers/response_handler.rb +0 -49
  301. data/ffi/neo4j/driver/internal/handlers/run_response_handler.rb +0 -32
  302. data/ffi/neo4j/driver/internal/handlers/session_pull_all_response_handler.rb +0 -32
  303. data/ffi/neo4j/driver/internal/handlers/transaction_pull_all_response_handler.rb +0 -23
  304. data/ffi/neo4j/driver/internal/internal_driver.rb +0 -45
  305. data/ffi/neo4j/driver/internal/internal_logger.rb +0 -32
  306. data/ffi/neo4j/driver/internal/internal_resolver.rb +0 -31
  307. data/ffi/neo4j/driver/internal/internal_statement_result.rb +0 -52
  308. data/ffi/neo4j/driver/internal/messaging/bolt_protocol.rb +0 -24
  309. data/ffi/neo4j/driver/internal/messaging/v1/bolt_protocol_v1.rb +0 -59
  310. data/ffi/neo4j/driver/internal/messaging/v2/bolt_protocol_v2.rb +0 -16
  311. data/ffi/neo4j/driver/internal/messaging/v3/bolt_protocol_v3.rb +0 -63
  312. data/ffi/neo4j/driver/internal/network_session.rb +0 -129
  313. data/ffi/neo4j/driver/internal/retry/exponential_backoff_retry_logic.rb +0 -80
  314. data/ffi/neo4j/driver/internal/session_factory_impl.rb +0 -28
  315. data/ffi/neo4j/driver/internal/summary/internal_result_summary.rb +0 -67
  316. data/ffi/neo4j/driver/internal/summary/internal_server_info.rb +0 -19
  317. data/ffi/neo4j/driver/internal/summary/internal_summary_counters.rb +0 -23
  318. data/ffi/neo4j/driver/internal/util/metadata_extractor.rb +0 -15
  319. data/ffi/neo4j/driver/internal/value/base_time_value.rb +0 -22
  320. data/ffi/neo4j/driver/internal/value/date_value.rb +0 -25
  321. data/ffi/neo4j/driver/internal/value/duration_value.rb +0 -27
  322. data/ffi/neo4j/driver/internal/value/local_date_time_value.rb +0 -24
  323. data/ffi/neo4j/driver/internal/value/local_time_value.rb +0 -19
  324. data/ffi/neo4j/driver/internal/value/node_value.rb +0 -18
  325. data/ffi/neo4j/driver/internal/value/offset_time_value.rb +0 -25
  326. data/ffi/neo4j/driver/internal/value/path_value.rb +0 -41
  327. data/ffi/neo4j/driver/internal/value/point2_d_value.rb +0 -24
  328. data/ffi/neo4j/driver/internal/value/point3_d_value.rb +0 -24
  329. data/ffi/neo4j/driver/internal/value/relationship_value.rb +0 -18
  330. data/ffi/neo4j/driver/internal/value/structure_value.rb +0 -42
  331. data/ffi/neo4j/driver/internal/value/time_with_zone_id_value.rb +0 -25
  332. data/ffi/neo4j/driver/internal/value/time_with_zone_offset_value.rb +0 -28
  333. data/ffi/neo4j/driver/internal/value/unbound_relationship_value.rb +0 -18
  334. data/ffi/neo4j/driver/internal/value/value_adapter.rb +0 -101
  335. data/ffi/neo4j/driver/net/server_address.rb +0 -13
  336. data/ffi/neo4j/driver/statement.rb +0 -15
  337. data/ffi/neo4j/driver/types/entity.rb +0 -21
  338. data/ffi/neo4j/driver/types/node.rb +0 -16
  339. data/ffi/neo4j/driver/types/path.rb +0 -35
  340. data/ffi/neo4j/driver/types/relationship.rb +0 -19
  341. data/ffi/neo4j/driver.rb +0 -61
  342. data/lib/neo4j/driver/internal/ruby_signature.rb +0 -18
@@ -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
@@ -0,0 +1,21 @@
1
+ module Neo4j::Driver
2
+ module Internal
3
+ module Async
4
+ module Pool
5
+ class NetworkConnectionFactory
6
+ attr_reader :clock, :metrics_listener, :logger
7
+
8
+ def initialize(clock, metrics_listener, logger)
9
+ @clock = clock
10
+ @metrics_listener = metrics_listener
11
+ @logger = logger
12
+ end
13
+
14
+ def create_connection(channel, pool)
15
+ NetworkConnection.new(channel, pool, clock, metrics_listener, @logger)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,34 @@
1
+ module Neo4j::Driver
2
+ module Internal
3
+ module Async
4
+ module Pool
5
+ class PoolSettings
6
+ attr_reader :max_connection_pool_size, :connection_acquisition_timeout, :max_connection_lifetime,
7
+ :idle_time_before_connection_test
8
+
9
+ NOT_CONFIGURED = nil
10
+ DEFAULT_MAX_CONNECTION_POOL_SIZE = 100
11
+ DEFAULT_IDLE_TIME_BEFORE_CONNECTION_TEST = NOT_CONFIGURED
12
+ DEFAULT_MAX_CONNECTION_LIFETIME = 1.hour
13
+ DEFAULT_CONNECTION_ACQUISITION_TIMEOUT = 60.seconds
14
+
15
+ def initialize(max_connection_pool_size, connection_acquisition_timeout, max_connection_lifetime,
16
+ idle_time_before_connection_test)
17
+ @max_connection_pool_size = max_connection_pool_size
18
+ @connection_acquisition_timeout = connection_acquisition_timeout
19
+ @max_connection_lifetime = max_connection_lifetime
20
+ @idle_time_before_connection_test = idle_time_before_connection_test
21
+ end
22
+
23
+ def idle_time_before_connection_test_enabled?
24
+ idle_time_before_connection_test&.send(:>=, 0)
25
+ end
26
+
27
+ def max_connection_lifetime_enabled?
28
+ max_connection_lifetime&.send(:>, 0)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,15 @@
1
+ module Neo4j::Driver
2
+ module Internal
3
+ module Async
4
+ module Pool
5
+ class TimedStack < ConnectionPool::TimedStack
6
+ def any_resource_busy?
7
+ @mutex.synchronize do
8
+ @created > @que.length
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ module Neo4j::Driver
2
+ module Internal
3
+ module Async
4
+ class ResultCursorsHolder < Array
5
+ def retrieve_not_consumed_error
6
+ retrieve_all_failures.find { |failure| failure }
7
+ end
8
+
9
+ private
10
+
11
+ def retrieve_all_failures
12
+ map(&:discard_all_failure_async)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,212 @@
1
+ module Neo4j::Driver
2
+ module Internal
3
+ module Async
4
+ class UnmanagedTransaction
5
+ class State
6
+ # The transaction is running with no explicit success or failure marked
7
+ ACTIVE = 'active'
8
+
9
+ # This transaction has been terminated either because of explicit {@link Session#reset()} or because of a fatal connection error.
10
+ TERMINATED = 'terminated'
11
+
12
+ # This transaction has successfully committed
13
+ COMMITTED = 'committed'
14
+
15
+ # This transaction has been rolled back
16
+ ROLLED_BACK = 'rolled_back'
17
+ end
18
+
19
+ CANT_COMMIT_COMMITTED_MSG = "Can't commit, transaction has been committed"
20
+ CANT_ROLLBACK_COMMITTED_MSG = "Can't rollback, transaction has been committed"
21
+ CANT_COMMIT_ROLLED_BACK_MSG = "Can't commit, transaction has been rolled back"
22
+ CANT_ROLLBACK_ROLLED_BACK_MSG = "Can't rollback, transaction has been rolled back"
23
+ CANT_COMMIT_ROLLING_BACK_MSG = "Can't commit, transaction has been requested to be rolled back"
24
+ CANT_ROLLBACK_COMMITTING_MSG = "Can't rollback, transaction has been requested to be committed"
25
+ OPEN_STATES = [State::ACTIVE, State::TERMINATED]
26
+ attr :connection
27
+
28
+ def initialize(connection, bookmark_holder, fetch_size, result_cursors = ResultCursorsHolder.new)
29
+ @connection = connection
30
+ @protocol = connection.protocol
31
+ @bookmark_holder = bookmark_holder
32
+ @result_cursors = result_cursors
33
+ @fetch_size = fetch_size
34
+ @lock = Util::Mutex.new
35
+ @state = State::ACTIVE
36
+ end
37
+
38
+ def begin_async(initial_bookmark, config)
39
+ @protocol.begin_transaction(@connection, initial_bookmark, config)
40
+ self
41
+ rescue Neo4j::Driver::Exceptions::AuthorizationExpiredException
42
+ @connection.terminate_and_release(Neo4j::Driver::Exceptions::AuthorizationExpiredException::DESCRIPTION)
43
+ raise
44
+ rescue Neo4j::Driver::Exceptions::ConnectionReadTimeoutException => begin_error
45
+ @connection.terminate_and_release(begin_error.message)
46
+ raise
47
+ rescue
48
+ @connection.release
49
+ raise
50
+ end
51
+
52
+ def close_async(commit = false, complete_with_null_if_not_open = true)
53
+ @lock.synchronize do
54
+ if complete_with_null_if_not_open && !open?
55
+ Util::ResultHolder.successful(nil)
56
+ elsif @state == State::COMMITTED
57
+ Util::ResultHolder.failed(Neo4j::Driver::Exceptions::ClientException.new(
58
+ commit ? CANT_COMMIT_COMMITTED_MSG : CANT_ROLLBACK_COMMITTED_MSG))
59
+ elsif @state == State::ROLLED_BACK
60
+ Util::ResultHolder.failed(Neo4j::Driver::Exceptions::ClientException.new(
61
+ commit ? CANT_COMMIT_ROLLED_BACK_MSG : CANT_ROLLBACK_ROLLED_BACK_MSG))
62
+ else
63
+ if commit
64
+ if @rollback_pending
65
+ Util::ResultHolder.failed(Neo4j::Driver::Exceptions::ClientException.new(CANT_COMMIT_ROLLING_BACK_MSG))
66
+ elsif @commit_pending
67
+ @commit_pending
68
+ else
69
+ @commit_pending = Util::ResultHolder.new
70
+ nil
71
+ end
72
+ else
73
+ if @commit_pending
74
+ Util::ResultHolder.failed(Neo4j::Driver::Exceptions::ClientException.new(CANT_ROLLBACK_COMMITTING_MSG))
75
+ elsif @rollback_pending
76
+ @rollback_pending
77
+ else
78
+ @rollback_pending = Util::ResultHolder.new
79
+ nil
80
+ end
81
+ end
82
+ end
83
+ end ||
84
+ begin
85
+ if commit
86
+ target_future = @commit_pending
87
+ target_action = lambda { |throwable|
88
+ do_commit_async(throwable).chain(&handle_commit_or_rollback(throwable))
89
+ }
90
+ else
91
+ target_future = @rollback_pending
92
+ target_action = lambda { |throwable|
93
+ do_rollback_async.chain(&handle_commit_or_rollback(throwable))
94
+ }
95
+ end
96
+
97
+ @result_cursors.retrieve_not_consumed_error.then(&target_action)
98
+ .side { |_, error| handle_transaction_completion(commit, error) }.copy_to(target_future)
99
+ target_future
100
+ end
101
+ end
102
+
103
+ def commit_async
104
+ close_async(true, false)
105
+ end
106
+
107
+ def rollback_async
108
+ close_async(false, false)
109
+ end
110
+
111
+ def run_async(query)
112
+ ensure_can_run_queries
113
+ cursor = @protocol.run_in_unmanaged_transaction(@connection, query, self, @fetch_size).async_result
114
+ @result_cursors << cursor
115
+ cursor.map_successful_run_completion_async
116
+ end
117
+
118
+ def run_rx(query)
119
+ ensure_can_run_queries
120
+ cursor_stage = @protocol.run_in_unmanaged_transaction(@connection, query, self, @fetch_size).rx_result
121
+ @result_cursors << cursor_stage
122
+ cursor_stage
123
+ end
124
+
125
+ def open?
126
+ OPEN_STATES.include?(@lock.synchronize { @state })
127
+ end
128
+
129
+ def mark_terminated(cause)
130
+ @lock.synchronize do
131
+ if @state == State::TERMINATED
132
+ add_suppressed_when_not_captured(@cause_of_termination, cause) if @cause_of_termination
133
+ else
134
+ @state = State::TERMINATED
135
+ @cause_of_termination = cause
136
+ end
137
+ end
138
+ end
139
+
140
+ def ensure_can_run_queries
141
+ @lock.synchronize do
142
+ case @state
143
+ when State::COMMITTED
144
+ raise Neo4j::Driver::Exceptions::ClientException, 'Cannot run more queries in this transaction, it has been committed'
145
+ when State::ROLLED_BACK
146
+ raise Neo4j::Driver::Exceptions::ClientException, 'Cannot run more queries in this transaction, it has been rolled back'
147
+ when State::TERMINATED
148
+ # TODO clunky positional arguments of Neo4jException#initialize, move to named parameters
149
+ raise Neo4j::Driver::Exceptions::ClientException, 'Cannot run more queries in this transaction, it has either experienced an fatal error or was explicitly terminated' #, # TODO should be able to pass @cause_of_termination
150
+ end
151
+ end
152
+ end
153
+
154
+ private
155
+
156
+ def add_suppressed_when_not_captured(current_cause, new_cause)
157
+ if current_cause != new_cause
158
+ none_match = current_cause.get_suppressed.none? { |suppressed| suppressed == new_cause }
159
+
160
+ if none_match
161
+ current_cause.add_suppressed(new_cause)
162
+ end
163
+ end
164
+ end
165
+
166
+ def do_commit_async(cursor_failure)
167
+ exception = @lock.synchronize do
168
+ if @state == State::TERMINATED
169
+ Neo4j::Driver::Exceptions::ClientException.new(
170
+ "Transaction can't be committed. It has been rolled back either because of an error or explicit termination",
171
+ cursor_failure != @cause_of_termination ? @cause_of_termination : nil)
172
+ end
173
+ end
174
+
175
+ if exception
176
+ Util::ResultHolder.failed(exception)
177
+ else
178
+ @protocol.commit_transaction(@connection).then(&@bookmark_holder.method(:bookmark=))
179
+ end
180
+ end
181
+
182
+ def do_rollback_async
183
+ if @lock.synchronize { @state } == State::TERMINATED
184
+ Util::ResultHolder.successful(nil)
185
+ else
186
+ @protocol.rollback_transaction(@connection)
187
+ end
188
+ end
189
+
190
+ def handle_commit_or_rollback(cursor_failure)
191
+ lambda { |_value, commit_or_rollback_error|
192
+ combined_error = Util::Futures.combine_errors(cursor_failure, commit_or_rollback_error)
193
+ raise combined_error if combined_error
194
+ }
195
+ end
196
+
197
+ def handle_transaction_completion(commit_attempt, throwable)
198
+ @lock.synchronize { @state = commit_attempt && throwable.nil? ? State::COMMITTED : State::ROLLED_BACK }
199
+
200
+ case throwable
201
+ when Neo4j::Driver::Exceptions::AuthorizationExpiredException
202
+ @connection.terminate_and_release(Neo4j::Driver::Exceptions::AuthorizationExpiredException::DESCRIPTION)
203
+ when Neo4j::Driver::Exceptions::ConnectionReadTimeoutException
204
+ @connection.terminate_and_release(throwable.message)
205
+ else
206
+ @connection.release # release in background
207
+ end
208
+ end
209
+ end
210
+ end
211
+ end
212
+ end
@@ -0,0 +1,9 @@
1
+ module Neo4j::Driver
2
+ module Internal
3
+ class BookmarkHolder
4
+ NO_OP = Class.new(DefaultBookmarkHolder) do
5
+ def bookmark=(_value) end
6
+ end.new
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,48 @@
1
+ module Neo4j::Driver
2
+ module Internal
3
+ module Cluster
4
+ class ClusterComposition < Struct.new(:expiration_timestamp, :readers, :writers, :routers, :database_name)
5
+ def initialize(expiration_timestamp:, database_name:, readers: [], writers: [], routers: [])
6
+ super(expiration_timestamp, readers, writers, routers, database_name)
7
+ end
8
+
9
+ def has_writers?
10
+ writers.present?
11
+ end
12
+
13
+ def has_routers_and_readers?
14
+ routers.present? && readers.present?
15
+ end
16
+
17
+ def self.parse(record, now)
18
+ return unless record
19
+ new(expiration_timestamp: expiration_timestamp(now, record), database_name: record[:db],
20
+ **record[:servers].to_h do |value|
21
+ [servers(value[:role]),
22
+ value[:addresses].map { |address| BoltServerAddress.new(uri: BoltServerAddress.uri_from(address)) }]
23
+ end)
24
+ end
25
+
26
+ private
27
+
28
+ def self.expiration_timestamp(now, record)
29
+ ttl = record['ttl']
30
+ now + (ttl.negative? ? 1000.years : ttl.seconds)
31
+ end
32
+
33
+ def self.servers(role)
34
+ case role
35
+ when 'READ'
36
+ :readers
37
+ when 'WRITE'
38
+ :writers
39
+ when 'ROUTE'
40
+ :routers
41
+ else
42
+ raise ArgumentError, "invalid server role: #{role}"
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,14 @@
1
+ module Neo4j::Driver
2
+ module Internal
3
+ module Cluster
4
+ class ClusterCompositionLookupResult
5
+ attr_reader :cluster_composition, :resolved_initial_routers
6
+
7
+ def initialize(composition, resolved_initial_routers = nil)
8
+ @cluster_composition = composition
9
+ @resolved_initial_routers = resolved_initial_routers
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,122 @@
1
+ module Neo4j::Driver
2
+ module Internal
3
+ module Cluster
4
+ class ClusterRoutingTable
5
+ MIN_ROUTERS = 1
6
+
7
+ def initialize(of_database, _clock, *routing_addresses)
8
+ @database_name = of_database
9
+ @expiration_timestamp = Time.now
10
+ @routers = routing_addresses.to_set.freeze
11
+ @table_lock = Concurrent::ReentrantReadWriteLock.new
12
+ @prefer_initial_router = true
13
+ @disused = Set.new
14
+ @readers = Set.new
15
+ @writers = Set.new
16
+ end
17
+
18
+ def stale_for?(mode)
19
+ @table_lock.with_read_lock do
20
+ @expiration_timestamp <= Time.now ||
21
+ routers.size < MIN_ROUTERS ||
22
+ (mode == AccessMode::READ && @readers.size == 0) ||
23
+ (mode == AccessMode::WRITE && @writers.size == 0)
24
+ end
25
+ end
26
+
27
+ def has_been_stale_for?(extra_time)
28
+ Time.now - @table_lock.with_read_lock { @expiration_timestamp } >= extra_time
29
+ end
30
+
31
+ def update(cluster)
32
+ @table_lock.with_write_lock do
33
+ @expiration_timestamp = cluster.expiration_timestamp
34
+ @readers = new_with_reused_addresses(@readers, @disused, cluster.readers)
35
+ @writers = new_with_reused_addresses(@writers, @disused, cluster.writers)
36
+ @routers = new_with_reused_addresses(@routers, @disused, cluster.routers)
37
+ @disused.clear
38
+ @prefer_initial_router = !cluster.has_writers?
39
+ end
40
+ end
41
+
42
+ def forget(address)
43
+ @table_lock.with_write_lock do
44
+ @routers = new_without_address_if_present(@routers, address)
45
+ @readers = new_without_address_if_present(@readers, address)
46
+ @writers = new_without_address_if_present(@writers, address)
47
+ @disused << address
48
+ end
49
+ end
50
+
51
+ def readers
52
+ @table_lock.with_read_lock { @readers }
53
+ end
54
+
55
+ def writers
56
+ @table_lock.with_read_lock { @writers }
57
+ end
58
+
59
+ def routers
60
+ @table_lock.with_read_lock { @routers }
61
+ end
62
+
63
+ def servers
64
+ @table_lock.with_write_lock do
65
+ [@readers, @writers, @routers, @disused].reduce(&:+)
66
+ end
67
+ end
68
+
69
+ def database
70
+ @database_name
71
+ end
72
+
73
+ def forget_writer(to_remove)
74
+ Util::LockUtil.execute_with_lock(@table_lock.write_lock) do
75
+ @writers = new_without_address_if_present(@writers, to_remove)
76
+ @disused << to_remove
77
+ end
78
+ end
79
+
80
+ def replace_router_if_present(old_router, new_router)
81
+ @table_lock.with_write_lock { @routers = new_with_address_replaced_if_present(@routers, old_router, new_router) }
82
+ end
83
+
84
+ def prefer_initial_router
85
+ @table_lock.with_read_lock { @prefer_initial_router }
86
+ end
87
+
88
+ def expiration_timestamp
89
+ @table_lock.with_read_lock { @expiration_timestamp }
90
+ end
91
+
92
+ def to_s
93
+ @table_lock.with_read_lock do
94
+ "Ttl #{@expiration_timestamp}, currentTime #{Time.now}, routers #{@routers}, writers #{@writers}, readers #{@readers}, database '#{@database_name.description}'"
95
+ end
96
+ end
97
+
98
+ private
99
+
100
+ def new_without_address_if_present(addresses, address_to_skip)
101
+ (addresses - [address_to_skip]).freeze
102
+ end
103
+
104
+ def new_with_address_replaced_if_present(addresses, old_address, new_address)
105
+ addresses.map { |address| address == old_address ? new_address : address }.freeze
106
+ end
107
+
108
+ def new_with_reused_addresses(*addresses)
109
+ addresses.map(&:to_set).reduce(&:+).freeze
110
+ end
111
+
112
+ def to_bolt_server_address(address)
113
+ if BoltServerAddress.class == address.class
114
+ address
115
+ else
116
+ BoltServerAddress.new(host: address.host, port: address.port)
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,10 @@
1
+ module Neo4j::Driver
2
+ module Internal
3
+ module Cluster
4
+ class IdentityResolver
5
+ IDENTITY_RESOLVER = new
6
+ alias resolve Array
7
+ end
8
+ end
9
+ end
10
+ end