neo4j-ruby-driver 6.0.3.alpha.0 → 6.2.1.beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (348) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +113 -411
  3. data/{ruby → lib}/neo4j/driver/access_mode.rb +2 -1
  4. data/lib/neo4j/driver/auth_token_managers.rb +31 -0
  5. data/lib/neo4j/driver/auth_tokens.rb +41 -0
  6. data/lib/neo4j/driver/auto_commit_retries_mode.rb +18 -0
  7. data/lib/neo4j/driver/bolt/bolt_version.rb +67 -0
  8. data/lib/neo4j/driver/bolt/connection.rb +1091 -0
  9. data/lib/neo4j/driver/bolt/handshake.rb +236 -0
  10. data/lib/neo4j/driver/bolt/message/failure.rb +139 -0
  11. data/lib/neo4j/driver/bolt/message/ignored.rb +27 -0
  12. data/lib/neo4j/driver/bolt/message/record.rb +30 -0
  13. data/lib/neo4j/driver/bolt/message/success.rb +34 -0
  14. data/lib/neo4j/driver/bolt/message.rb +112 -0
  15. data/lib/neo4j/driver/bolt/pool.rb +255 -0
  16. data/lib/neo4j/driver/bolt/protocol/base.rb +146 -0
  17. data/lib/neo4j/driver/bolt/protocol/v3.rb +43 -0
  18. data/lib/neo4j/driver/bolt/protocol/v4.rb +24 -0
  19. data/lib/neo4j/driver/bolt/protocol/v43.rb +28 -0
  20. data/lib/neo4j/driver/bolt/protocol/v44.rb +23 -0
  21. data/lib/neo4j/driver/bolt/protocol/v5.rb +27 -0
  22. data/lib/neo4j/driver/bolt/protocol/v51.rb +24 -0
  23. data/lib/neo4j/driver/bolt/protocol/v52.rb +28 -0
  24. data/lib/neo4j/driver/bolt/protocol/v53.rb +27 -0
  25. data/lib/neo4j/driver/bolt/protocol/v54.rb +14 -0
  26. data/lib/neo4j/driver/bolt/protocol/v55.rb +17 -0
  27. data/lib/neo4j/driver/bolt/protocol/v56.rb +14 -0
  28. data/lib/neo4j/driver/bolt/protocol/v57.rb +31 -0
  29. data/lib/neo4j/driver/bolt/protocol/v58.rb +15 -0
  30. data/lib/neo4j/driver/bolt/protocol/v6.rb +43 -0
  31. data/lib/neo4j/driver/bolt/protocol/v61.rb +21 -0
  32. data/lib/neo4j/driver/bolt/protocol_version_handler.rb +39 -0
  33. data/lib/neo4j/driver/bolt/record_buffer.rb +143 -0
  34. data/lib/neo4j/driver/bolt/stream_handler.rb +53 -0
  35. data/lib/neo4j/driver/bolt/tls_config.rb +129 -0
  36. data/lib/neo4j/driver/bolt/wire.rb +321 -0
  37. data/lib/neo4j/driver/bookmark.rb +15 -0
  38. data/lib/neo4j/driver/bookmark_managers.rb +39 -0
  39. data/lib/neo4j/driver/client_certificate.rb +19 -0
  40. data/lib/neo4j/driver/client_certificate_manager.rb +37 -0
  41. data/lib/neo4j/driver/client_certificate_managers.rb +15 -0
  42. data/lib/neo4j/driver/client_certificates.rb +14 -0
  43. data/lib/neo4j/driver/direct/connection_provider.rb +262 -0
  44. data/lib/neo4j/driver/driver.rb +268 -0
  45. data/lib/neo4j/driver/eager_result.rb +10 -0
  46. data/lib/neo4j/driver/exceptions/neo4j_exception.rb +16 -7
  47. data/lib/neo4j/driver/exceptions/no_such_record_exception.rb +1 -1
  48. data/lib/neo4j/driver/exceptions/protocol_exception.rb +0 -5
  49. data/lib/neo4j/driver/exceptions/security_retryable_exception.rb +14 -0
  50. data/lib/neo4j/driver/exceptions/transaction_terminated_exception.rb +13 -0
  51. data/lib/neo4j/driver/graph_database.rb +29 -0
  52. data/lib/neo4j/driver/internal/clock.rb +20 -0
  53. data/lib/neo4j/driver/internal/clock_adapter.rb +21 -0
  54. data/lib/neo4j/driver/internal/default_bookmark_manager.rb +54 -0
  55. data/lib/neo4j/driver/internal/deprecator.rb +9 -5
  56. data/lib/neo4j/driver/internal/driver_factory.rb +128 -0
  57. data/lib/neo4j/driver/internal/duration_normalizer.rb +14 -39
  58. data/lib/neo4j/driver/internal/extras.rb +23 -0
  59. data/lib/neo4j/driver/internal/home_db_cache.rb +57 -0
  60. data/lib/neo4j/driver/internal/internal_auth_token_manager.rb +37 -0
  61. data/lib/neo4j/driver/internal/metrics.rb +31 -0
  62. data/lib/neo4j/driver/internal/security/static_auth_token_manager.rb +25 -0
  63. data/lib/neo4j/driver/internal/validator.rb +16 -2
  64. data/lib/neo4j/driver/net.rb +29 -0
  65. data/lib/neo4j/driver/packstream/markers.rb +49 -0
  66. data/lib/neo4j/driver/packstream/packer.rb +335 -0
  67. data/lib/neo4j/driver/packstream/structure.rb +27 -0
  68. data/lib/neo4j/driver/packstream/unpacker.rb +170 -0
  69. data/lib/neo4j/driver/record.rb +43 -0
  70. data/lib/neo4j/driver/result.rb +282 -0
  71. data/lib/neo4j/driver/routing/load_balancer.rb +706 -0
  72. data/lib/neo4j/driver/routing/routed_connection.rb +132 -0
  73. data/lib/neo4j/driver/routing/routing_table.rb +127 -0
  74. data/lib/neo4j/driver/routing/server_address.rb +25 -0
  75. data/lib/neo4j/driver/routing_control.rb +13 -0
  76. data/lib/neo4j/driver/session.rb +577 -0
  77. data/lib/neo4j/driver/summary/database_info.rb +25 -0
  78. data/lib/neo4j/driver/summary/gql_notification.rb +38 -0
  79. data/lib/neo4j/driver/summary/gql_status_object.rb +35 -0
  80. data/lib/neo4j/driver/summary/notification.rb +46 -0
  81. data/lib/neo4j/driver/summary/plan.rb +23 -0
  82. data/lib/neo4j/driver/summary/profile.rb +28 -0
  83. data/lib/neo4j/driver/summary/query.rb +19 -0
  84. data/lib/neo4j/driver/summary/query_type.rb +5 -1
  85. data/lib/neo4j/driver/summary/result_summary.rb +215 -0
  86. data/lib/neo4j/driver/summary/server_info.rb +33 -0
  87. data/lib/neo4j/driver/summary/summary_counters.rb +72 -0
  88. data/lib/neo4j/driver/transaction.rb +344 -0
  89. data/lib/neo4j/driver/types/duration.rb +76 -0
  90. data/lib/neo4j/driver/types/entity.rb +40 -0
  91. data/lib/neo4j/driver/types/local_date_time.rb +77 -8
  92. data/lib/neo4j/driver/types/local_time.rb +50 -7
  93. data/lib/neo4j/driver/types/node.rb +18 -0
  94. data/lib/neo4j/driver/types/offset_time.rb +78 -7
  95. data/lib/neo4j/driver/types/path.rb +68 -0
  96. data/lib/neo4j/driver/types/point.rb +38 -18
  97. data/lib/neo4j/driver/types/relationship.rb +32 -0
  98. data/lib/neo4j/driver/types/temporal_value.rb +44 -0
  99. data/lib/neo4j/driver/types/unbound_relationship.rb +24 -0
  100. data/lib/neo4j/driver/types/unresolvable_zoned_date_time.rb +38 -0
  101. data/lib/neo4j/driver/types/unsupported_type.rb +25 -0
  102. data/lib/neo4j/driver/types/uuid.rb +29 -0
  103. data/{ruby → lib}/neo4j/driver/version.rb +1 -1
  104. data/lib/neo4j/driver.rb +15 -0
  105. data/lib/neo4j-ruby-driver_loader.rb +34 -20
  106. metadata +115 -441
  107. data/lib/neo4j/driver/internal/bolt_server_address.rb +0 -97
  108. data/lib/neo4j/driver/synchronizable.rb +0 -23
  109. data/lib/neo4j/driver/types/time.rb +0 -45
  110. data/ruby/neo4j/driver/auth_tokens.rb +0 -34
  111. data/ruby/neo4j/driver/bookmark.rb +0 -21
  112. data/ruby/neo4j/driver/config.rb +0 -89
  113. data/ruby/neo4j/driver/graph_database.rb +0 -78
  114. data/ruby/neo4j/driver/internal/async/connection/bolt_protocol_util.rb +0 -51
  115. data/ruby/neo4j/driver/internal/async/connection/bootstrap_factory.rb +0 -22
  116. data/ruby/neo4j/driver/internal/async/connection/channel_attributes.rb +0 -31
  117. data/ruby/neo4j/driver/internal/async/connection/channel_connected_listener.rb +0 -32
  118. data/ruby/neo4j/driver/internal/async/connection/channel_connector_impl.rb +0 -83
  119. data/ruby/neo4j/driver/internal/async/connection/channel_pipeline_builder_impl.rb +0 -22
  120. data/ruby/neo4j/driver/internal/async/connection/direct_connection.rb +0 -30
  121. data/ruby/neo4j/driver/internal/async/connection/event_loop_group_factory.rb +0 -83
  122. data/ruby/neo4j/driver/internal/async/connection/handshake_completed_listener.rb +0 -27
  123. data/ruby/neo4j/driver/internal/async/connection/handshake_handler.rb +0 -113
  124. data/ruby/neo4j/driver/internal/async/connection/netty_channel_initializer.rb +0 -57
  125. data/ruby/neo4j/driver/internal/async/connection/netty_domain_name_resolver.rb +0 -26
  126. data/ruby/neo4j/driver/internal/async/connection/netty_domain_name_resolver_group.rb +0 -19
  127. data/ruby/neo4j/driver/internal/async/connection/routing_connection.rb +0 -36
  128. data/ruby/neo4j/driver/internal/async/connection/stream.rb +0 -12
  129. data/ruby/neo4j/driver/internal/async/connection/stream_reader.rb +0 -16
  130. data/ruby/neo4j/driver/internal/async/connection_context.rb +0 -10
  131. data/ruby/neo4j/driver/internal/async/immutable_connection_context.rb +0 -24
  132. data/ruby/neo4j/driver/internal/async/inbound/byte_buf_input.rb +0 -30
  133. data/ruby/neo4j/driver/internal/async/inbound/channel_error_handler.rb +0 -77
  134. data/ruby/neo4j/driver/internal/async/inbound/chunk_decoder.rb +0 -41
  135. data/ruby/neo4j/driver/internal/async/inbound/connect_timeout_handler.rb +0 -32
  136. data/ruby/neo4j/driver/internal/async/inbound/connection_read_timeout_handler.rb +0 -17
  137. data/ruby/neo4j/driver/internal/async/inbound/inbound_message_dispatcher.rb +0 -171
  138. data/ruby/neo4j/driver/internal/async/inbound/inbound_message_handler.rb +0 -42
  139. data/ruby/neo4j/driver/internal/async/inbound/message_decoder.rb +0 -51
  140. data/ruby/neo4j/driver/internal/async/internal_async_session.rb +0 -92
  141. data/ruby/neo4j/driver/internal/async/internal_async_transaction.rb +0 -13
  142. data/ruby/neo4j/driver/internal/async/leak_logging_network_session.rb +0 -34
  143. data/ruby/neo4j/driver/internal/async/network_connection.rb +0 -194
  144. data/ruby/neo4j/driver/internal/async/network_session.rb +0 -150
  145. data/ruby/neo4j/driver/internal/async/outbound/chunk_aware_byte_buf_output.rb +0 -110
  146. data/ruby/neo4j/driver/internal/async/outbound/outbound_message_handler.rb +0 -39
  147. data/ruby/neo4j/driver/internal/async/pool/channel.rb +0 -66
  148. data/ruby/neo4j/driver/internal/async/pool/channel_pool.rb +0 -31
  149. data/ruby/neo4j/driver/internal/async/pool/channel_tracker.rb +0 -135
  150. data/ruby/neo4j/driver/internal/async/pool/connection_pool_impl.rb +0 -156
  151. data/ruby/neo4j/driver/internal/async/pool/netty_channel_health_checker.rb +0 -87
  152. data/ruby/neo4j/driver/internal/async/pool/netty_channel_pool.rb +0 -52
  153. data/ruby/neo4j/driver/internal/async/pool/network_connection_factory.rb +0 -21
  154. data/ruby/neo4j/driver/internal/async/pool/pool_settings.rb +0 -34
  155. data/ruby/neo4j/driver/internal/async/pool/timed_stack.rb +0 -15
  156. data/ruby/neo4j/driver/internal/async/result_cursors_holder.rb +0 -17
  157. data/ruby/neo4j/driver/internal/async/unmanaged_transaction.rb +0 -212
  158. data/ruby/neo4j/driver/internal/bookmark_holder.rb +0 -9
  159. data/ruby/neo4j/driver/internal/cluster/cluster_composition.rb +0 -48
  160. data/ruby/neo4j/driver/internal/cluster/cluster_composition_lookup_result.rb +0 -14
  161. data/ruby/neo4j/driver/internal/cluster/cluster_routing_table.rb +0 -122
  162. data/ruby/neo4j/driver/internal/cluster/identity_resolver.rb +0 -10
  163. data/ruby/neo4j/driver/internal/cluster/loadbalancing/least_connected_load_balancing_strategy.rb +0 -68
  164. data/ruby/neo4j/driver/internal/cluster/loadbalancing/load_balancer.rb +0 -125
  165. data/ruby/neo4j/driver/internal/cluster/loadbalancing/round_robin_array_index.rb +0 -13
  166. data/ruby/neo4j/driver/internal/cluster/multi_databases_routing_procedure_runner.rb +0 -31
  167. data/ruby/neo4j/driver/internal/cluster/rediscovery_impl.rb +0 -147
  168. data/ruby/neo4j/driver/internal/cluster/route_message_routing_procedure_runner.rb +0 -43
  169. data/ruby/neo4j/driver/internal/cluster/routing_context.rb +0 -77
  170. data/ruby/neo4j/driver/internal/cluster/routing_procedure_cluster_composition_provider.rb +0 -60
  171. data/ruby/neo4j/driver/internal/cluster/routing_procedure_response.rb +0 -35
  172. data/ruby/neo4j/driver/internal/cluster/routing_settings.rb +0 -24
  173. data/ruby/neo4j/driver/internal/cluster/routing_table_handler_impl.rb +0 -95
  174. data/ruby/neo4j/driver/internal/cluster/routing_table_registry_impl.rb +0 -121
  175. data/ruby/neo4j/driver/internal/cluster/single_database_routing_procedure_runner.rb +0 -73
  176. data/ruby/neo4j/driver/internal/connection_settings.rb +0 -16
  177. data/ruby/neo4j/driver/internal/cursor/async_result_cursor_impl.rb +0 -55
  178. data/ruby/neo4j/driver/internal/cursor/async_result_cursor_only_factory.rb +0 -24
  179. data/ruby/neo4j/driver/internal/cursor/disposable_async_result_cursor.rb +0 -61
  180. data/ruby/neo4j/driver/internal/cursor/result_cursor_factory_impl.rb +0 -24
  181. data/ruby/neo4j/driver/internal/cursor/rx_result_cursor_impl.rb +0 -110
  182. data/ruby/neo4j/driver/internal/database_name_util.rb +0 -37
  183. data/ruby/neo4j/driver/internal/default_bookmark_holder.rb +0 -9
  184. data/ruby/neo4j/driver/internal/default_domain_name_resolver.rb +0 -11
  185. data/ruby/neo4j/driver/internal/direct_connection_provider.rb +0 -40
  186. data/ruby/neo4j/driver/internal/driver_factory.rb +0 -126
  187. data/ruby/neo4j/driver/internal/eager_result_value.rb +0 -5
  188. data/ruby/neo4j/driver/internal/handlers/begin_tx_response_handler.rb +0 -20
  189. data/ruby/neo4j/driver/internal/handlers/channel_releasing_reset_response_handler.rb +0 -30
  190. data/ruby/neo4j/driver/internal/handlers/commit_tx_response_handler.rb +0 -23
  191. data/ruby/neo4j/driver/internal/handlers/hello_response_handler.rb +0 -65
  192. data/ruby/neo4j/driver/internal/handlers/init_response_handler.rb +0 -34
  193. data/ruby/neo4j/driver/internal/handlers/legacy_pull_all_response_handler.rb +0 -199
  194. data/ruby/neo4j/driver/internal/handlers/no_op_response_handler.rb +0 -16
  195. data/ruby/neo4j/driver/internal/handlers/ping_response_handler.rb +0 -29
  196. data/ruby/neo4j/driver/internal/handlers/pull_handlers.rb +0 -32
  197. data/ruby/neo4j/driver/internal/handlers/pulln/auto_pull_response_handler.rb +0 -169
  198. data/ruby/neo4j/driver/internal/handlers/pulln/basic_pull_response_handler.rb +0 -298
  199. data/ruby/neo4j/driver/internal/handlers/pulln/fetch_size_util.rb +0 -20
  200. data/ruby/neo4j/driver/internal/handlers/reset_response_handler.rb +0 -34
  201. data/ruby/neo4j/driver/internal/handlers/rollback_tx_response_handler.rb +0 -25
  202. data/ruby/neo4j/driver/internal/handlers/route_message_response_handler.rb +0 -21
  203. data/ruby/neo4j/driver/internal/handlers/routing_response_handler.rb +0 -79
  204. data/ruby/neo4j/driver/internal/handlers/run_response_handler.rb +0 -38
  205. data/ruby/neo4j/driver/internal/handlers/session_pull_response_completion_listener.rb +0 -34
  206. data/ruby/neo4j/driver/internal/handlers/transaction_pull_response_completion_listener.rb +0 -20
  207. data/ruby/neo4j/driver/internal/impersonation_util.rb +0 -22
  208. data/ruby/neo4j/driver/internal/internal_bookmark.rb +0 -9
  209. data/ruby/neo4j/driver/internal/internal_database_name.rb +0 -9
  210. data/ruby/neo4j/driver/internal/internal_driver.rb +0 -83
  211. data/ruby/neo4j/driver/internal/internal_entity.rb +0 -21
  212. data/ruby/neo4j/driver/internal/internal_node.rb +0 -21
  213. data/ruby/neo4j/driver/internal/internal_pair.rb +0 -9
  214. data/ruby/neo4j/driver/internal/internal_path.rb +0 -35
  215. data/ruby/neo4j/driver/internal/internal_point2_d.rb +0 -9
  216. data/ruby/neo4j/driver/internal/internal_point3_d.rb +0 -6
  217. data/ruby/neo4j/driver/internal/internal_record.rb +0 -27
  218. data/ruby/neo4j/driver/internal/internal_relationship.rb +0 -27
  219. data/ruby/neo4j/driver/internal/internal_result.rb +0 -49
  220. data/ruby/neo4j/driver/internal/internal_session.rb +0 -91
  221. data/ruby/neo4j/driver/internal/internal_transaction.rb +0 -48
  222. data/ruby/neo4j/driver/internal/logging/channel_activity_logger.rb +0 -29
  223. data/ruby/neo4j/driver/internal/logging/channel_error_logger.rb +0 -17
  224. data/ruby/neo4j/driver/internal/logging/prefixed_logger.rb +0 -19
  225. data/ruby/neo4j/driver/internal/logging/reformatted_logger.rb +0 -17
  226. data/ruby/neo4j/driver/internal/messaging/abstract_message_writer.rb +0 -23
  227. data/ruby/neo4j/driver/internal/messaging/bolt_protocol.rb +0 -32
  228. data/ruby/neo4j/driver/internal/messaging/bolt_protocol_version.rb +0 -48
  229. data/ruby/neo4j/driver/internal/messaging/common/common_message_reader.rb +0 -51
  230. data/ruby/neo4j/driver/internal/messaging/common/common_value.rb +0 -33
  231. data/ruby/neo4j/driver/internal/messaging/common/common_value_packer.rb +0 -104
  232. data/ruby/neo4j/driver/internal/messaging/common/common_value_unpacker.rb +0 -256
  233. data/ruby/neo4j/driver/internal/messaging/encode/begin_message_encoder.rb +0 -15
  234. data/ruby/neo4j/driver/internal/messaging/encode/commit_message_encoder.rb +0 -14
  235. data/ruby/neo4j/driver/internal/messaging/encode/discard_all_message_encoder.rb +0 -14
  236. data/ruby/neo4j/driver/internal/messaging/encode/discard_message_encoder.rb +0 -15
  237. data/ruby/neo4j/driver/internal/messaging/encode/goodbye_message_encoder.rb +0 -14
  238. data/ruby/neo4j/driver/internal/messaging/encode/hello_message_encoder.rb +0 -15
  239. data/ruby/neo4j/driver/internal/messaging/encode/init_message_encoder.rb +0 -16
  240. data/ruby/neo4j/driver/internal/messaging/encode/logoff_message_encoder.rb +0 -14
  241. data/ruby/neo4j/driver/internal/messaging/encode/logon_message_encoder.rb +0 -15
  242. data/ruby/neo4j/driver/internal/messaging/encode/pull_all_message_encoder.rb +0 -14
  243. data/ruby/neo4j/driver/internal/messaging/encode/pull_message_encoder.rb +0 -15
  244. data/ruby/neo4j/driver/internal/messaging/encode/reset_message_encoder.rb +0 -14
  245. data/ruby/neo4j/driver/internal/messaging/encode/rollback_message_encoder.rb +0 -14
  246. data/ruby/neo4j/driver/internal/messaging/encode/route_message_encoder.rb +0 -24
  247. data/ruby/neo4j/driver/internal/messaging/encode/route_v44_message_encoder.rb +0 -22
  248. data/ruby/neo4j/driver/internal/messaging/encode/run_message_encoder.rb +0 -16
  249. data/ruby/neo4j/driver/internal/messaging/encode/run_with_metadata_message_encoder.rb +0 -17
  250. data/ruby/neo4j/driver/internal/messaging/request/abstract_streaming_message.rb +0 -25
  251. data/ruby/neo4j/driver/internal/messaging/request/begin_message.rb +0 -25
  252. data/ruby/neo4j/driver/internal/messaging/request/commit_message.rb +0 -20
  253. data/ruby/neo4j/driver/internal/messaging/request/discard_all_message.rb +0 -20
  254. data/ruby/neo4j/driver/internal/messaging/request/discard_message.rb +0 -23
  255. data/ruby/neo4j/driver/internal/messaging/request/goodbye_message.rb +0 -20
  256. data/ruby/neo4j/driver/internal/messaging/request/hello_message.rb +0 -30
  257. data/ruby/neo4j/driver/internal/messaging/request/init_message.rb +0 -19
  258. data/ruby/neo4j/driver/internal/messaging/request/logoff_message.rb +0 -13
  259. data/ruby/neo4j/driver/internal/messaging/request/logon_message.rb +0 -13
  260. data/ruby/neo4j/driver/internal/messaging/request/message_with_metadata.rb +0 -17
  261. data/ruby/neo4j/driver/internal/messaging/request/multi_database_util.rb +0 -26
  262. data/ruby/neo4j/driver/internal/messaging/request/pull_all_message.rb +0 -23
  263. data/ruby/neo4j/driver/internal/messaging/request/pull_message.rb +0 -22
  264. data/ruby/neo4j/driver/internal/messaging/request/reset_message.rb +0 -32
  265. data/ruby/neo4j/driver/internal/messaging/request/rollback_message.rb +0 -20
  266. data/ruby/neo4j/driver/internal/messaging/request/route_message.rb +0 -28
  267. data/ruby/neo4j/driver/internal/messaging/request/run_message.rb +0 -23
  268. data/ruby/neo4j/driver/internal/messaging/request/run_with_metadata_message.rb +0 -49
  269. data/ruby/neo4j/driver/internal/messaging/request/transaction_metadata_builder.rb +0 -24
  270. data/ruby/neo4j/driver/internal/messaging/response/failure_message.rb +0 -40
  271. data/ruby/neo4j/driver/internal/messaging/response/ignored_message.rb +0 -29
  272. data/ruby/neo4j/driver/internal/messaging/response/record_message.rb +0 -33
  273. data/ruby/neo4j/driver/internal/messaging/response/success_message.rb +0 -34
  274. data/ruby/neo4j/driver/internal/messaging/v3/bolt_protocol_v3.rb +0 -82
  275. data/ruby/neo4j/driver/internal/messaging/v3/message_format_v3.rb +0 -17
  276. data/ruby/neo4j/driver/internal/messaging/v3/message_writer_v3.rb +0 -27
  277. data/ruby/neo4j/driver/internal/messaging/v4/bolt_protocol_v4.rb +0 -29
  278. data/ruby/neo4j/driver/internal/messaging/v4/message_format_v4.rb +0 -13
  279. data/ruby/neo4j/driver/internal/messaging/v4/message_writer_v4.rb +0 -17
  280. data/ruby/neo4j/driver/internal/messaging/v41/bolt_protocol_v41.rb +0 -25
  281. data/ruby/neo4j/driver/internal/messaging/v42/bolt_protocol_v42.rb +0 -13
  282. data/ruby/neo4j/driver/internal/messaging/v43/bolt_protocol_v43.rb +0 -19
  283. data/ruby/neo4j/driver/internal/messaging/v43/message_format_v43.rb +0 -14
  284. data/ruby/neo4j/driver/internal/messaging/v43/message_writer_v43.rb +0 -20
  285. data/ruby/neo4j/driver/internal/messaging/v44/bolt_protocol_v44.rb +0 -17
  286. data/ruby/neo4j/driver/internal/messaging/v44/message_format_v44.rb +0 -14
  287. data/ruby/neo4j/driver/internal/messaging/v44/message_writer_v44.rb +0 -15
  288. data/ruby/neo4j/driver/internal/messaging/v5/bolt_protocol_v5.rb +0 -21
  289. data/ruby/neo4j/driver/internal/messaging/v5/message_format_v5.rb +0 -18
  290. data/ruby/neo4j/driver/internal/messaging/v5/value_unpacker_v5.rb +0 -17
  291. data/ruby/neo4j/driver/internal/messaging/v51/bolt_protocol_v51.rb +0 -40
  292. data/ruby/neo4j/driver/internal/messaging/v51/message_format_v51.rb +0 -14
  293. data/ruby/neo4j/driver/internal/messaging/v51/message_writer_v51.rb +0 -17
  294. data/ruby/neo4j/driver/internal/metrics/connection_pool_metrics_listener.rb +0 -34
  295. data/ruby/neo4j/driver/internal/metrics/internal_abstract_metrics.rb +0 -46
  296. data/ruby/neo4j/driver/internal/metrics/internal_connection_pool_metrics.rb +0 -105
  297. data/ruby/neo4j/driver/internal/metrics/internal_metrics.rb +0 -82
  298. data/ruby/neo4j/driver/internal/metrics/internal_metrics_provider.rb +0 -18
  299. data/ruby/neo4j/driver/internal/metrics/listener_event.rb +0 -17
  300. data/ruby/neo4j/driver/internal/metrics/metrics_provider.rb +0 -24
  301. data/ruby/neo4j/driver/internal/metrics/time_recorder_listener_event.rb +0 -15
  302. data/ruby/neo4j/driver/internal/packstream/byte_array_incompatible_packer.rb +0 -12
  303. data/ruby/neo4j/driver/internal/packstream/pack_input.rb +0 -47
  304. data/ruby/neo4j/driver/internal/packstream/pack_output.rb +0 -39
  305. data/ruby/neo4j/driver/internal/packstream/pack_stream.rb +0 -324
  306. data/ruby/neo4j/driver/internal/packstream/pack_type.rb +0 -17
  307. data/ruby/neo4j/driver/internal/read_only_bookmark_holder.rb +0 -13
  308. data/ruby/neo4j/driver/internal/resolved_bolt_server_address.rb +0 -35
  309. data/ruby/neo4j/driver/internal/retry/exponential_backoff_retry_logic.rb +0 -150
  310. data/ruby/neo4j/driver/internal/revocation_strategy.rb +0 -19
  311. data/ruby/neo4j/driver/internal/scheme.rb +0 -32
  312. data/ruby/neo4j/driver/internal/security/internal_auth_token.rb +0 -15
  313. data/ruby/neo4j/driver/internal/security/security_plan_impl.rb +0 -48
  314. data/ruby/neo4j/driver/internal/security_setting.rb +0 -66
  315. data/ruby/neo4j/driver/internal/session_factory_impl.rb +0 -32
  316. data/ruby/neo4j/driver/internal/spi/connection.rb +0 -19
  317. data/ruby/neo4j/driver/internal/spi/connection_pool.rb +0 -9
  318. data/ruby/neo4j/driver/internal/spi/response_handler.rb +0 -23
  319. data/ruby/neo4j/driver/internal/summary/internal_database_info.rb +0 -7
  320. data/ruby/neo4j/driver/internal/summary/internal_input_position.rb +0 -11
  321. data/ruby/neo4j/driver/internal/summary/internal_notification.rb +0 -16
  322. data/ruby/neo4j/driver/internal/summary/internal_plan.rb +0 -41
  323. data/ruby/neo4j/driver/internal/summary/internal_profiled_plan.rb +0 -32
  324. data/ruby/neo4j/driver/internal/summary/internal_result_summary.rb +0 -33
  325. data/ruby/neo4j/driver/internal/summary/internal_server_info.rb +0 -6
  326. data/ruby/neo4j/driver/internal/summary/internal_summary_counters.rb +0 -18
  327. data/ruby/neo4j/driver/internal/svm/netty_substitutions.rb +0 -196
  328. data/ruby/neo4j/driver/internal/svm/z_lib_substitutions.rb +0 -21
  329. data/ruby/neo4j/driver/internal/util/certificate_tool.rb +0 -65
  330. data/ruby/neo4j/driver/internal/util/clock.rb +0 -29
  331. data/ruby/neo4j/driver/internal/util/error_util.rb +0 -104
  332. data/ruby/neo4j/driver/internal/util/extract.rb +0 -123
  333. data/ruby/neo4j/driver/internal/util/format.rb +0 -39
  334. data/ruby/neo4j/driver/internal/util/futures.rb +0 -99
  335. data/ruby/neo4j/driver/internal/util/iterables.rb +0 -35
  336. data/ruby/neo4j/driver/internal/util/lock_util.rb +0 -23
  337. data/ruby/neo4j/driver/internal/util/metadata_extractor.rb +0 -101
  338. data/ruby/neo4j/driver/internal/util/mutex.rb +0 -9
  339. data/ruby/neo4j/driver/internal/util/preconditions.rb +0 -16
  340. data/ruby/neo4j/driver/internal/util/result_holder.rb +0 -72
  341. data/ruby/neo4j/driver/internal/util/server_version.rb +0 -60
  342. data/ruby/neo4j/driver/logging1.rb +0 -51
  343. data/ruby/neo4j/driver/net/server_address.rb +0 -9
  344. data/ruby/neo4j/driver/query.rb +0 -48
  345. data/ruby/neo4j/driver/records.rb +0 -13
  346. data/ruby/neo4j/driver/transaction_config.rb +0 -50
  347. data/ruby/neo4j/driver/values.rb +0 -26
  348. data/ruby/neo4j/driver.rb +0 -30
@@ -0,0 +1,255 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Neo4j
4
+ module Driver
5
+ module Bolt
6
+ # Hardened connection pool. Wraps ConnectionPool::TimedStack and
7
+ # layers the three guarantees production callers care about:
8
+ #
9
+ # max_connection_lifetime → connections older than this are
10
+ # dropped on acquire (caps server-side
11
+ # resource growth for long-running
12
+ # processes).
13
+ # connection_liveness_check_timeout → if a connection has been
14
+ # idle longer than this, RESET-probe
15
+ # before handing it out (catches
16
+ # "server reaped me, client didn't
17
+ # notice yet").
18
+ # connection_acquisition_timeout → bounded wait when the pool
19
+ # is at its size cap (raises
20
+ # ClientException, not a hang).
21
+ #
22
+ # Mirrors org.neo4j.driver.internal.async.pool.NettyChannelPool
23
+ # in the Java reference. The acquisition-timeout slice was already
24
+ # in place via TimedStack; this class adds the lifetime + liveness
25
+ # gates and centralises the construction across the two providers.
26
+ class Pool
27
+ DEFAULT_ACQUISITION_TIMEOUT = 60
28
+
29
+ # `connect_factory` is a callable returning a freshly-opened
30
+ # Bolt::Connection. Wrapped, not inherited, because TimedStack
31
+ # owns the threading + size-cap primitive and doesn't expose
32
+ # hooks for "decide whether to hand out the popped item".
33
+ def initialize(size:, options:, connect_factory:, clock: Internal::Clock.new)
34
+ @options = options
35
+ @clock = clock
36
+ # connect_factory takes the auth token a fresh connection should
37
+ # authenticate with. pop hands it to the create block via a
38
+ # thread-local: the create block runs synchronously inside
39
+ # @stack.pop on the *calling* thread, so a thread-local is read
40
+ # back by the same thread that set it and can't be clobbered by a
41
+ # concurrent pop on another thread (a shared ivar could — this
42
+ # pool is shared across sessions). Keyed by object_id so distinct
43
+ # pools don't collide on the same thread. This lets a session
44
+ # create a fresh connection with its own identity (per-session
45
+ # auth) or the manager's current token in a single get_token call,
46
+ # instead of connecting as the manager and re-authing.
47
+ @connect_factory = connect_factory
48
+ @auth_key = :"bolt_pool_next_auth_#{object_id}"
49
+ # Companion thread-local (same pattern as @auth_key) carrying the
50
+ # acquisition deadline a freshly-built connection's handshake must
51
+ # honour — so one budget spans the home-db guess + fallback.
52
+ @deadline_key = :"bolt_pool_next_deadline_#{object_id}"
53
+ # Metrics counters (driver.metrics / testkit GetConnectionPoolMetrics):
54
+ # @created = live connections this pool has built (idle + in use),
55
+ # @leased = currently checked out. idle = created - leased. Guarded by
56
+ # @metrics_lock since pop/push/discard run on many session threads.
57
+ # @created is bumped inside the create block (only on a successful
58
+ # factory call — TimedStack rolls back its own count if it raises).
59
+ @metrics_lock = Mutex.new
60
+ @created = 0
61
+ @leased = 0
62
+ @stack = ConnectionPool::TimedStack.new(size: size) do
63
+ @connect_factory.call(Thread.current[@auth_key], Thread.current[@deadline_key]).tap { bump(created: 1) }
64
+ end
65
+ end
66
+
67
+ # A consistent [in_use, idle] snapshot read under one lock — both
68
+ # counters move together on discard, so reading them separately could
69
+ # observe an intermediate (e.g. negative idle) state.
70
+ def metrics_snapshot
71
+ @metrics_lock.synchronize { [@leased, @created - @leased] }
72
+ end
73
+
74
+ # Pop a connection that's young enough and confirmed alive.
75
+ # Loops until a usable one is found or the acquisition-timeout
76
+ # budget runs out — every discarded slot opens room for the
77
+ # factory to make a fresh one.
78
+ def pop(auth: nil, deadline: nil)
79
+ # The token a freshly-built connection should authenticate with,
80
+ # handed to the create block via a thread-local that lives only
81
+ # for this pop (see #initialize). Cleared in `ensure` so it never
82
+ # leaks into a later create on the same thread.
83
+ Thread.current[@auth_key] = auth
84
+ # A caller-supplied deadline lets one acquisition-timeout budget span
85
+ # several pops (the home-db optimistic acquire + its fallback), and
86
+ # bounds a freshly-built connection's handshake via the create block.
87
+ deadline ||= current_monotonic + acquisition_timeout
88
+ Thread.current[@deadline_key] = deadline
89
+ loop do
90
+ timeout = [deadline - current_monotonic, 0].max
91
+ conn = @stack.pop(timeout: timeout)
92
+ return prepare(conn) if usable?(conn)
93
+
94
+ discard_on_pop(conn)
95
+ # Loop with whatever budget remains. A flapping server
96
+ # would otherwise burn the whole pool in one acquire.
97
+ end
98
+ rescue ::Timeout::Error
99
+ raise Exceptions::ClientException,
100
+ "Unable to acquire connection from the pool within configured maximum time of #{format_acquisition_timeout}"
101
+ ensure
102
+ Thread.current[@auth_key] = nil
103
+ Thread.current[@deadline_key] = nil
104
+ end
105
+
106
+ def push(connection)
107
+ return unless connection
108
+
109
+ # RESET on return to the pool, clearing any residual server-side state
110
+ # so the next lessee gets a clean connection. Reference drivers do this
111
+ # unless they advertise Optimization:MinimalResets (MRI doesn't), and
112
+ # testkit's scripts encode the expectation (#RESET_ON_POOL_RETURN#).
113
+ # It also keeps the liveness probe distinct from the return-RESET, so a
114
+ # silently-dead connection is actually detected on re-acquire
115
+ # (test_should_drop_connections_failing_liveness_check).
116
+ #
117
+ # If that RESET fails the connection is dead — discard it (closing the
118
+ # socket) rather than pooling a broken connection (test_fail_on_reset).
119
+ begin
120
+ connection.reset!(propagate: true)
121
+ rescue StandardError
122
+ discard(connection)
123
+ return
124
+ end
125
+ connection.idle_since = current_monotonic
126
+ @stack.push(connection)
127
+ bump(leased: -1) # returned to the pool, now idle
128
+ end
129
+
130
+ # Close a checked-out connection without putting it back.
131
+ # Mirrors Java's pool-discard: used when the connection is in
132
+ # a known-bad state (server FAILED, write-failure on a
133
+ # NotALeader, etc.) so we don't poison the pool. Frees the
134
+ # TimedStack slot so the next pop can lazily build a fresh
135
+ # one.
136
+ def discard(connection)
137
+ close_quietly(connection)
138
+ @stack.decrement_created
139
+ # A checked-out connection removed for good: no longer created, no
140
+ # longer leased.
141
+ bump(created: -1, leased: -1)
142
+ end
143
+
144
+ def shutdown(&)
145
+ @stack.shutdown(&)
146
+ # Every connection is closed now — keep the metrics truthful so a
147
+ # post-close snapshot reports nothing live.
148
+ @metrics_lock.synchronize { @created = @leased = 0 }
149
+ end
150
+
151
+ private
152
+
153
+ # Both gates: too old OR known dead. We probe only when the
154
+ # connection has been idle past the liveness threshold so the
155
+ # hot path stays single-pop / no-extra-roundtrip.
156
+ def usable?(conn)
157
+ return false if conn.nil?
158
+ return false if conn.closed?
159
+ return false if expired?(conn)
160
+ # A reused connection (idle_since set when it was pushed back) may have
161
+ # been closed by the server while parked — a cheap non-blocking
162
+ # peer-close check, no round-trip, catches that so we don't hand out a
163
+ # dead connection (and the replacement re-resolves the address). Fresh
164
+ # connections (idle_since nil) skip it.
165
+ return false if conn.idle_since && conn.broken?
166
+ return false if needs_liveness_check?(conn) && !conn.alive?
167
+
168
+ true
169
+ end
170
+
171
+ def prepare(conn)
172
+ conn.idle_since = nil
173
+ bump(leased: 1) # checked out of the pool
174
+ conn
175
+ end
176
+
177
+ # Move both counters under a single lock so a concurrent
178
+ # metrics_snapshot never sees a half-applied discard (created < leased).
179
+ def bump(created: 0, leased: 0)
180
+ @metrics_lock.synchronize do
181
+ @created += created
182
+ @leased += leased
183
+ end
184
+ end
185
+
186
+ # Replacement-on-acquire close: TimedStack already counted
187
+ # this connection as "created" (whether it came from the stack
188
+ # or the factory), so we must decrement_created to free the
189
+ # slot — otherwise a saturated pool that keeps producing
190
+ # unusable connections deadlocks: the next pop sees @created
191
+ # == size, has nothing on the stack, and blocks until timeout.
192
+ def discard_on_pop(conn)
193
+ close_quietly(conn)
194
+ @stack.decrement_created
195
+ # Popped but never handed out (unusable) — drop from created; it was
196
+ # never counted as leased.
197
+ bump(created: -1)
198
+ end
199
+
200
+ def close_quietly(conn)
201
+ conn&.close
202
+ rescue StandardError
203
+ # Caller already has a fresh connection coming. A failure
204
+ # during close is noise.
205
+ end
206
+
207
+ def expired?(conn)
208
+ return false unless max_lifetime
209
+ return false unless conn.created_at
210
+
211
+ current_monotonic - conn.created_at > max_lifetime
212
+ end
213
+
214
+ def needs_liveness_check?(conn)
215
+ return false unless liveness_check_timeout
216
+ return false unless conn.idle_since
217
+
218
+ current_monotonic - conn.idle_since > liveness_check_timeout
219
+ end
220
+
221
+ def max_lifetime
222
+ @max_lifetime ||= seconds(@options[:max_connection_lifetime])
223
+ end
224
+
225
+ def liveness_check_timeout
226
+ # Memoise the sentinel separately from the value so a configured
227
+ # 0 (probe-every-time) still bypasses the recompute.
228
+ return @liveness_check_timeout if defined?(@liveness_check_timeout)
229
+
230
+ @liveness_check_timeout = seconds(@options[:connection_liveness_check_timeout])
231
+ end
232
+
233
+ def acquisition_timeout
234
+ @acquisition_timeout ||=
235
+ seconds(@options[:connection_acquisition_timeout]) || DEFAULT_ACQUISITION_TIMEOUT
236
+ end
237
+
238
+ # Accept Numeric seconds or ActiveSupport::Duration (which
239
+ # responds to #to_f). nil stays nil — callers gate on it to
240
+ # decide whether the feature is configured at all.
241
+ def seconds(value)
242
+ value&.to_f
243
+ end
244
+
245
+ def format_acquisition_timeout
246
+ "#{(acquisition_timeout * 1000).to_i}ms"
247
+ end
248
+
249
+ def current_monotonic
250
+ @clock.monotonic
251
+ end
252
+ end
253
+ end
254
+ end
255
+ end
@@ -0,0 +1,146 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Neo4j
4
+ module Driver
5
+ module Bolt
6
+ module Protocol
7
+ # Base of the per-minor protocol class hierarchy. Mirrors Java's
8
+ # BoltProtocolVxY family in `neo4j-bolt-connection-java` — each
9
+ # minor version is its own subclass and only overrides what
10
+ # changed at that version, instead of carrying a swarm of
11
+ # `version >= V5_X` checks inside one big class.
12
+ class Base
13
+ attr_reader :version, :connection
14
+
15
+ def initialize(connection, version)
16
+ @connection = connection
17
+ @version = version
18
+ end
19
+
20
+ # Top-level HELLO builder. The shape is fixed (one map argument);
21
+ # subclasses override `hello_extra` to change which keys it
22
+ # carries at their version. `notification_config` (the driver's
23
+ # NotificationsConfig, a `{minimum_severity:, disabled_categories:}`
24
+ # hash or nil) only lands on the wire from V52 on — older versions
25
+ # return an empty map from `notification_config_extra`.
26
+ def build_hello_message(user_agent:, auth:, routing: nil, notification_config: nil)
27
+ extra = hello_extra(user_agent:, auth:, routing:)
28
+ .merge(notification_config_extra(notification_config))
29
+ PackStream::Structure.new(Message::HELLO, [extra.compact])
30
+ end
31
+
32
+ # The HELLO map. Auth lives inside HELLO through Bolt 5.0;
33
+ # `routing` is the routing context (nil for a direct bolt://
34
+ # connection, compacted away by build_hello_message). V51
35
+ # overrides this to drop `**auth` once auth splits out into a
36
+ # separate LOGON message.
37
+ def hello_extra(user_agent:, auth:, routing:)
38
+ { user_agent:, routing:, **auth }
39
+ end
40
+
41
+ # Notification-filtering keys for the HELLO map. Empty until V52,
42
+ # the first version whose server honours them (V52 overrides this).
43
+ def notification_config_extra(_notification_config) = {}
44
+
45
+ # Hook for V51+ (HELLO/LOGON split): the LOGON message the connection
46
+ # pipelines right after HELLO. nil here — older versions carry auth in
47
+ # the HELLO map and send no separate LOGON.
48
+ def build_logon_message(_auth) = nil
49
+
50
+ # Hook for V5+: lets the protocol flip the packer's UTC
51
+ # datetime flag (0x49 / 0x69 vs legacy 0x46 / 0x66).
52
+ def configure_packer(_packer); end
53
+
54
+ # Hook for per-version unpacker customisation — re-registering
55
+ # handlers for messages whose shape changed at this version
56
+ # (V57 FAILURE) or adding handlers for new struct types
57
+ # (V6 VECTOR / UNSUPPORTED). Called after Connection
58
+ # registers the common ones, so an override here wins.
59
+ def customize_hydration(_unpacker); end
60
+
61
+ # PackStream V2 (Bolt 6.1+) UUID codec. UUID is a version-specific
62
+ # type: only Protocol::V61 packs/unpacks it — every earlier version
63
+ # rejects it. Packing raises a ClientException naming the type;
64
+ # unpacking treats the 0xE0 marker as unknown.
65
+ def pack_uuid(_packer, value)
66
+ Exceptions::ClientException.unable_to_convert(value)
67
+ end
68
+
69
+ def unpack_uuid(unpacker)
70
+ unpacker.raise_unknown_marker(PackStream::Markers::UUID)
71
+ end
72
+
73
+ # --- Message builders -------------------------------------------
74
+ # The protocol handler owns the wire shape of the streaming /
75
+ # transaction messages, mirroring Java's BoltProtocolVxY. The
76
+ # defaults here are the Bolt 4.0+ forms; V3 overrides the three
77
+ # that changed: PULL/DISCARD carry no fields, and RUN/BEGIN have
78
+ # no `db` (3.0 is single-database). The `db` strip is keyed on
79
+ # supports_multiple_databases? so it is automatic for V3.
80
+
81
+ # `notification_config` is the SESSION's NotificationsConfig (the
82
+ # driver's rides on HELLO). It reaches the wire only on V5_2+, where
83
+ # notification_config_extra emits the keys; `.compact` there drops an
84
+ # unset severity while keeping an explicit `disabled_categories: []`.
85
+ def build_run(query, parameters, extra, notification_config: nil)
86
+ enforce_impersonation_support!(extra[:imp_user])
87
+ Message.run(query, parameters,
88
+ strip_db(extra).merge(notification_config_extra(notification_config).compact))
89
+ end
90
+
91
+ def build_begin(extra, notification_config: nil)
92
+ enforce_impersonation_support!(extra[:imp_user])
93
+ Message.begin_transaction(strip_db(extra).merge(notification_config_extra(notification_config).compact))
94
+ end
95
+
96
+ # 4.0+ PULL carries `{n, qid}`. V3 overrides to the
97
+ # parameterless PULL_ALL.
98
+ def build_pull(extra)
99
+ Message.pull(extra)
100
+ end
101
+
102
+ # 4.0+ DISCARD carries `{n, qid}`. V3 overrides to DISCARD_ALL.
103
+ def build_discard(extra)
104
+ Message.discard(extra)
105
+ end
106
+
107
+ def build_telemetry(api)
108
+ Message.telemetry(api)
109
+ end
110
+
111
+ def supports_re_auth? = false
112
+ def supports_multiple_databases? = false
113
+ def supports_notification_filtering? = false
114
+ # TELEMETRY (driver-API usage reporting) arrived with Bolt 5.4;
115
+ # V54 flips this to true.
116
+ def supports_telemetry? = false
117
+ # Impersonation (imp_user on RUN/BEGIN/ROUTE) arrived with Bolt 4.4;
118
+ # V44 flips this to true.
119
+ def supports_impersonation? = false
120
+
121
+ # Fail fast when a caller asks to impersonate over a protocol
122
+ # that can't carry imp_user (Bolt < 4.4) — otherwise the field
123
+ # is silently dropped and the query runs as the authenticated
124
+ # user. Matches Java, which raises ClientException here. Public
125
+ # so Connection#route can enforce the same rule on the discovery
126
+ # path (a routed session impersonating against a 4.3 cluster
127
+ # must fail before sending ROUTE, not silently lose imp_user).
128
+ def enforce_impersonation_support!(imp_user)
129
+ return if imp_user.nil? || supports_impersonation?
130
+
131
+ raise Exceptions::ClientException,
132
+ "Impersonation (impersonated_user) is not supported on Bolt #{version}; requires Bolt 4.4+"
133
+ end
134
+
135
+ private
136
+
137
+ def strip_db(extra)
138
+ return extra if supports_multiple_databases?
139
+
140
+ extra.reject { |key, _| key.to_sym == :db }
141
+ end
142
+ end
143
+ end
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Neo4j
4
+ module Driver
5
+ module Bolt
6
+ module Protocol
7
+ # Bolt 3.0 protocol handler — the oldest version the driver
8
+ # speaks (matches the Java driver's matrix, which starts at 3.0).
9
+ #
10
+ # Differences from V4 that this class encodes:
11
+ # * Routing is the `dbms.cluster.routing.getRoutingTable`
12
+ # procedure (RUN), not a server ROUTE message — but the HELLO
13
+ # still carries the routing context, matching the Java driver
14
+ # (and so JRuby): testkit gates `routing` in the 3.0 HELLO on
15
+ # driver name java/ruby specifically.
16
+ # * Single-database: no `db` field on RUN / BEGIN. Inherits
17
+ # supports_multiple_databases? = false from Base, so the
18
+ # strip_db in build_run / build_begin happens automatically.
19
+ # * Streaming is all-or-nothing: PULL_ALL (0x3F) and
20
+ # DISCARD_ALL (0x2F) take no fields, unlike the 4.0+
21
+ # PULL / DISCARD which carry `{n, qid}`.
22
+ class V3 < Base
23
+ # HELLO is the inherited auth-in-HELLO form. On 3.0, `routing`
24
+ # is the context for a neo4j:// driver and nil for bolt://
25
+ # (compacted away), so a direct 3.0 connection sends no routing
26
+ # key — matching the Java driver, which testkit gates on driver
27
+ # name for the 3.0 HELLO.
28
+
29
+ # PULL_ALL: no metadata map. The caller still passes `{n:}` for
30
+ # the 4.0+ path; on 3.0 we discard it and send the bare struct.
31
+ def build_pull(_extra)
32
+ PackStream::Structure.new(Message::PULL, [])
33
+ end
34
+
35
+ # DISCARD_ALL: no metadata map.
36
+ def build_discard(_extra)
37
+ PackStream::Structure.new(Message::DISCARD, [])
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Neo4j
4
+ module Driver
5
+ module Bolt
6
+ module Protocol
7
+ # Bolt 4.x handler for the pre-4.4 wire form. The driver
8
+ # negotiates it for 4.2 and 4.3 (see ProtocolVersionHandler);
9
+ # 4.4's wire additions (imp_user, the ROUTE map form) live in
10
+ # the V44 subclass, which every 5.x handler descends from.
11
+ class V4 < Base
12
+ def supports_multiple_databases? = true
13
+
14
+ # ROUTE's third field is the target database as a bare string
15
+ # (or null for the home db). 4.4 changed it to a `{db, imp_user}`
16
+ # map — V44 overrides this; imp_user is unused here.
17
+ def build_route(routing_context, bookmarks, database, _imp_user)
18
+ Message.route(routing_context, bookmarks, database)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Neo4j
4
+ module Driver
5
+ module Bolt
6
+ module Protocol
7
+ # Bolt 4.3. First version to offer the "utc" datetime patch
8
+ # (HELLO `patch_bolt: ["utc"]`, opting into UTC-seconds encoding
9
+ # 0x49/0x69). Otherwise identical to V4 — 4.2 does not support the
10
+ # patch. V44 and every 5.x descend from here and inherit the
11
+ # capability; V5 turns it back off since 5.0+ makes UTC native. The
12
+ # packer only switches once the server confirms the patch in the
13
+ # HELLO SUCCESS (Connection#perform_hello).
14
+ class V43 < V4
15
+ # Advertise the "utc" patch in HELLO. Inherited by V44 (and thus the
16
+ # 5.x ladder); V5 resets patch_bolt_extra to {} since 5.0+ makes UTC
17
+ # native. The packer only switches once the server confirms the patch
18
+ # in the HELLO SUCCESS (Connection#perform_hello).
19
+ def hello_extra(user_agent:, auth:, routing:)
20
+ super.merge(patch_bolt_extra)
21
+ end
22
+
23
+ def patch_bolt_extra = { patch_bolt: ['utc'] }
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Neo4j
4
+ module Driver
5
+ module Bolt
6
+ module Protocol
7
+ # Bolt 4.4. Adds impersonation (imp_user on RUN/BEGIN/ROUTE) and
8
+ # changes ROUTE's third field from a bare database string to a
9
+ # `{db, imp_user}` map. Descends from V43 so it inherits the "utc"
10
+ # patch capability; every 5.x handler descends from this class, so
11
+ # they inherit impersonation, the ROUTE map form, and (until V5
12
+ # turns it off) the patch.
13
+ class V44 < V43
14
+ def supports_impersonation? = true
15
+
16
+ def build_route(routing_context, bookmarks, database, imp_user)
17
+ Message.route(routing_context, bookmarks, { db: database, imp_user: }.compact)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Neo4j
4
+ module Driver
5
+ module Bolt
6
+ module Protocol
7
+ # Bolt 5.0. HELLO shape is unchanged from V44 (auth still lives
8
+ # inside HELLO; 5.1 is where it splits out). The visible delta is
9
+ # on the wire: 5.0+ mandates UTC-seconds datetime encoding
10
+ # (structures 0x49 / 0x69) for both pack and hydrate. The 0x46 /
11
+ # 0x66 hydration handlers stay registered for back-compat reads
12
+ # from older sources. Extends V44 so it keeps impersonation and
13
+ # the ROUTE map form.
14
+ class V5 < V44
15
+ def configure_packer(packer)
16
+ packer.use_utc_datetime = true
17
+ end
18
+
19
+ # 5.0+ makes UTC-seconds datetimes native, so drop the "utc" HELLO
20
+ # patch V43 added — V43#hello_extra (inherited via V44) merges this
21
+ # empty map, so 5.0 sends no patch_bolt.
22
+ def patch_bolt_extra = {}
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Neo4j
4
+ module Driver
5
+ module Bolt
6
+ module Protocol
7
+ # Bolt 5.1. HELLO no longer carries auth — a separate LOGON
8
+ # (signature 0x6A) follows immediately. This also unlocks
9
+ # re-authentication on a live connection (`LOGOFF` + `LOGON`),
10
+ # which the public driver doesn't expose yet but the protocol
11
+ # supports from here on.
12
+ class V51 < V5
13
+ def hello_extra(user_agent:, auth:, routing:)
14
+ { user_agent:, routing: }
15
+ end
16
+
17
+ def build_logon_message(auth) = Message.logon(auth)
18
+
19
+ def supports_re_auth? = true
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Neo4j
4
+ module Driver
5
+ module Bolt
6
+ module Protocol
7
+ # Bolt 5.2. Server now honours notification-filtering fields in
8
+ # HELLO (`notifications_minimum_severity`,
9
+ # `notifications_disabled_categories`). The driver's
10
+ # NotificationsConfig (a `{minimum_severity:, disabled_categories:}`
11
+ # hash, or nil) is mapped straight onto those keys here; the outer
12
+ # `build_hello_message.compact` drops an unset severity while keeping
13
+ # an explicit empty `disabled_categories: []` (which the server reads
14
+ # as "re-enable every category").
15
+ class V52 < V51
16
+ def supports_notification_filtering? = true
17
+
18
+ def notification_config_extra(config)
19
+ return {} unless config
20
+
21
+ { notifications_minimum_severity: config[:minimum_severity],
22
+ notifications_disabled_categories: config[:disabled_categories] }
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Neo4j
4
+ module Driver
5
+ module Bolt
6
+ module Protocol
7
+ # Bolt 5.3. HELLO grows a required `bolt_agent` map identifying
8
+ # the driver (product is required; the rest is informational).
9
+ class V53 < V52
10
+ def hello_extra(user_agent:, auth:, routing:)
11
+ super.merge(bolt_agent: bolt_agent)
12
+ end
13
+
14
+ private
15
+
16
+ def bolt_agent
17
+ {
18
+ product: "neo4j-ruby-driver/#{Neo4j::Driver::VERSION}",
19
+ language: "Ruby/#{RUBY_VERSION}",
20
+ platform: RUBY_PLATFORM
21
+ }
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Neo4j
4
+ module Driver
5
+ module Bolt
6
+ module Protocol
7
+ # Bolt 5.4. Adds the TELEMETRY request (signature 0x54).
8
+ class V54 < V53
9
+ def supports_telemetry? = true
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Neo4j
4
+ module Driver
5
+ module Bolt
6
+ module Protocol
7
+ # Bolt 5.5. Server stops emitting the legacy `notifications`
8
+ # list in SUCCESS metadata and switches to GQL status objects
9
+ # (`statuses`). Hydration-side: ResultSummary#notifications
10
+ # already falls back to `statuses` when the legacy key is
11
+ # absent, so there's nothing version-specific to override here.
12
+ class V55 < V54
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Neo4j
4
+ module Driver
5
+ module Bolt
6
+ module Protocol
7
+ # Bolt 5.6. No client-visible wire change vs 5.5 — server-side
8
+ # capability bump only (vector type availability on the server).
9
+ class V56 < V55
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end