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,321 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Neo4j
4
+ module Driver
5
+ module Bolt
6
+ # Sans-I/O Bolt protocol core: a pure state machine with **no socket**.
7
+ #
8
+ # * `enqueue(message)` packs + chunk-frames a request into an outbound
9
+ # byte buffer; `take_outbound` hands those bytes to whoever owns the
10
+ # socket.
11
+ # * `receive(bytes)` feeds inbound bytes and returns the complete
12
+ # messages now decodable (Success / Failure / Record / Ignored), in
13
+ # order — reassembling chunks across calls, skipping NOOP keepalives,
14
+ # and retaining any trailing partial bytes for the next call.
15
+ #
16
+ # Because it never touches a socket, the whole Bolt framing + hydration
17
+ # path is unit-testable without a network, and stays identical regardless
18
+ # of how I/O is driven (blocking thread, fiber pump, on-demand). See
19
+ # docs/sans-io-pump.md.
20
+ #
21
+ # Created after the handshake — it needs the negotiated protocol to
22
+ # configure the packer (UTC datetime flag) and to customise hydration for
23
+ # version-specific message shapes.
24
+ class Wire
25
+ # Bolt message chunking: a message is a sequence of `[u16 size][size
26
+ # bytes]` chunks terminated by a zero-size chunk (the 0x00 0x00 end
27
+ # marker). A bare end marker with no preceding chunks is a NOOP — an
28
+ # inline keepalive the server sends to keep a slow response under the
29
+ # recv-timeout; it carries no message.
30
+ END_MARKER = "\x00\x00".b
31
+ MAX_CHUNK = 65_535
32
+
33
+ def initialize(protocol)
34
+ @protocol = protocol
35
+ @packer = PackStream::Packer.new(@protocol)
36
+ @protocol.configure_packer(@packer)
37
+ @outbound = binary_string # consumer-only (enqueue/take_outbound)
38
+ @inbound = binary_string # reader-only: received bytes not yet parsed
39
+ @message = binary_string # reader-only: chunks of the in-progress message
40
+ # Response-ordering FIFO. Bolt replies in request order, so each sent
41
+ # request pushes the handler that will receive its response(s); the
42
+ # front handler always owns the next reply. A handler is any response
43
+ # visitor (responds to on_record/on_success/on_failure/on_ignored —
44
+ # the same interface Message#accept dispatches to).
45
+ #
46
+ # This FIFO is the one piece of wire state touched by two threads: the
47
+ # consumer pushes (enqueue) while the dedicated reader shifts/dispatches
48
+ # (receive) and may clear it on failure (fail_pending). @mutex serialises
49
+ # those — without it JRuby (no GVL) races the Array and loses handlers,
50
+ # which strands a consumer parked on a buffer that never fills. Handler
51
+ # delivery is non-blocking (records/replies land on unbounded queues —
52
+ # flow control is the cursor's watermark, not a bounded buffer), so
53
+ # dispatching under the lock can't stall the reader.
54
+ @handlers = []
55
+ @mutex = Mutex.new
56
+ end
57
+
58
+ # Switch datetime packing to UTC-seconds (0x49/0x69). Connection calls
59
+ # this when the Bolt 4.3/4.4 HELLO confirms `patch_bolt: ["utc"]`; on
60
+ # 5.0+ configure_packer already set it, so this only fires on 4.x.
61
+ def enable_utc_datetime = @packer.use_utc_datetime = true
62
+
63
+ # Pack + chunk-frame `message` into the outbound buffer and register the
64
+ # handler for its reply. Several enqueues before a take_outbound are
65
+ # exactly the pipelining Bolt expects (HELLO+LOGON, RUN+PULL); the FIFO
66
+ # keeps each request matched to its response.
67
+ def enqueue(message, handler)
68
+ @packer.reset
69
+ @packer.pack_message(message)
70
+ data = @packer.bytes
71
+
72
+ offset = 0
73
+ while offset < data.bytesize
74
+ size = [data.bytesize - offset, MAX_CHUNK].min
75
+ @outbound << [size].pack('S>') << data.byteslice(offset, size)
76
+ offset += size
77
+ end
78
+ @outbound << END_MARKER
79
+ @mutex.synchronize { @handlers.push(handler) }
80
+ self
81
+ end
82
+
83
+ def pending_outbound? = !@outbound.empty?
84
+
85
+ # Requests still awaiting their terminal reply.
86
+ def in_flight = @mutex.synchronize { @handlers.size }
87
+
88
+ # Hand over (and clear) the framed bytes to write to the socket.
89
+ def take_outbound
90
+ out = @outbound
91
+ @outbound = binary_string
92
+ out
93
+ end
94
+
95
+ # Feed inbound bytes and route each fully-decoded message to the front
96
+ # handler (via its own #accept visitor). A RECORD keeps the handler at
97
+ # the front (one request streams many); a terminal (SUCCESS/FAILURE/
98
+ # IGNORED) completes the request and pops it. NOOP keepalives carry no
99
+ # message and are skipped. Partial bytes are retained for the next call.
100
+ def receive(bytes)
101
+ @inbound << bytes
102
+ # @inbound/@message/next_message are reader-only; only the @handlers
103
+ # touch needs the lock. Dispatch (accept) happens under it too — that's
104
+ # safe because delivery is non-blocking — and shifting after accept keeps
105
+ # in_flight from hitting zero until the terminal has actually been
106
+ # delivered (the quiescence contract reset!/drain_quiesced rely on).
107
+ @mutex.synchronize do
108
+ while (message = next_message)
109
+ next if message == :noop || @handlers.empty?
110
+
111
+ message.accept(@handlers.first)
112
+ @handlers.shift if message.terminal?
113
+ end
114
+ end
115
+ end
116
+
117
+ # Connection failure fan-out: tell every outstanding request's handler
118
+ # the connection died, so a consumer parked on that handler's buffer
119
+ # (or completion) wakes and re-raises rather than hanging. Drops them
120
+ # from the FIFO — the wire is done.
121
+ def fail_pending(error)
122
+ @mutex.synchronize do
123
+ @handlers.each { |handler| handler.fail(error) }
124
+ @handlers.clear
125
+ end
126
+ end
127
+
128
+ private
129
+
130
+ # Pull one complete message off the front of @inbound, or nil if more
131
+ # bytes are needed. Reassembles all of a message's chunks; returns
132
+ # :noop for a bare end marker. Consumes only what it fully parses.
133
+ def next_message
134
+ consumed = 0
135
+ loop do
136
+ return retain(consumed) if @inbound.bytesize - consumed < 2
137
+
138
+ size = @inbound.byteslice(consumed, 2).unpack1('S>')
139
+ consumed += 2
140
+
141
+ if size.zero? # end marker
142
+ if @message.empty?
143
+ advance(consumed)
144
+ return :noop
145
+ end
146
+ advance(consumed)
147
+ return unpack(take_message)
148
+ end
149
+
150
+ return retain(consumed - 2) if @inbound.bytesize - consumed < size
151
+
152
+ @message << @inbound.byteslice(consumed, size)
153
+ consumed += size
154
+ end
155
+ end
156
+
157
+ # Not enough bytes for the next chunk: drop what we've consumed so far
158
+ # (its chunks are already accumulated in @message) and signal "need
159
+ # more" with nil.
160
+ def retain(consumed)
161
+ advance(consumed)
162
+ nil
163
+ end
164
+
165
+ def advance(consumed)
166
+ return if consumed.zero?
167
+
168
+ @inbound = @inbound.byteslice(consumed..) || binary_string
169
+ end
170
+
171
+ def take_message
172
+ data = @message
173
+ @message = binary_string
174
+ data
175
+ end
176
+
177
+ def unpack(data)
178
+ unpacker = PackStream::Unpacker.new(StringIO.new(data), @protocol)
179
+ register_hydration_handlers(unpacker)
180
+ unpacker.unpack
181
+ end
182
+
183
+ def binary_string = String.new(encoding: Encoding::BINARY)
184
+
185
+ # --- Hydration (owned by the core; identical to the legacy path) -----
186
+
187
+ def register_hydration_handlers(unpacker)
188
+ unpacker.register_hydration_handler(Message::SUCCESS) { |fields| Message::Success.new(fields[0] || {}) }
189
+ unpacker.register_hydration_handler(Message::FAILURE) { |fields| Message::Failure.new(fields[0] || {}) }
190
+ unpacker.register_hydration_handler(Message::RECORD) { |fields| Message::Record.new(fields[0] || []) }
191
+ unpacker.register_hydration_handler(Message::IGNORED) { |_| Message::Ignored.new }
192
+
193
+ # Signature 0x4E - Node
194
+ unpacker.register_hydration_handler(0x4E) do |fields|
195
+ Types::Node.new(fields[0], fields[1].map(&:to_sym), fields[2], fields[3])
196
+ end
197
+
198
+ # Signature 0x52 - Relationship (bound). Bolt 5.0+ adds
199
+ # startNodeElementId/endNodeElementId as fields[6]/fields[7].
200
+ unpacker.register_hydration_handler(0x52) do |fields|
201
+ Types::Relationship.new(fields[0], fields[1], fields[2], fields[3].to_sym,
202
+ fields[4], fields[5], fields[6], fields[7])
203
+ end
204
+
205
+ # Signature 0x72 - UnboundRelationship. Bolt 5.0+ adds elementId.
206
+ unpacker.register_hydration_handler(0x72) do |fields|
207
+ Types::UnboundRelationship.new(fields[0], fields[1].to_sym, fields[2], fields[3])
208
+ end
209
+
210
+ # Signature 0x50 - Path
211
+ unpacker.register_hydration_handler(0x50) do |fields|
212
+ nodes = fields[0]
213
+ unbound_rels = fields[1]
214
+ indices = fields[2]
215
+
216
+ segments = []
217
+ bound_rels = []
218
+ current_node = nodes.first
219
+
220
+ indices.each_slice(2) do |rel_idx, node_idx|
221
+ next_node = nodes[node_idx]
222
+
223
+ if rel_idx < 0
224
+ unbound_rel = unbound_rels[rel_idx.abs - 1]
225
+ bound_rel = unbound_rel.bind(next_node.id, current_node.id,
226
+ next_node.element_id, current_node.element_id)
227
+ else
228
+ unbound_rel = unbound_rels[rel_idx - 1]
229
+ bound_rel = unbound_rel.bind(current_node.id, next_node.id,
230
+ current_node.element_id, next_node.element_id)
231
+ end
232
+ segments << Types::Path::Segment.new(current_node, next_node, bound_rel)
233
+
234
+ bound_rels << bound_rel
235
+ current_node = next_node
236
+ end
237
+
238
+ Types::Path.new(nodes, bound_rels, segments)
239
+ end
240
+
241
+ register_temporal_handlers(unpacker)
242
+
243
+ # Version-specific re-registration (V5_7 FAILURE, V6_0 VECTOR /
244
+ # UNSUPPORTED) wins, so it runs last.
245
+ @protocol&.customize_hydration(unpacker)
246
+ end
247
+
248
+ def register_temporal_handlers(unpacker)
249
+ # Date (0x44) → ::Date
250
+ unpacker.register_hydration_handler(0x44) { |fields| ::Date.new(1970, 1, 1) + fields[0] }
251
+ # OffsetTime (0x54)
252
+ unpacker.register_hydration_handler(0x54) { |fields| Types::OffsetTime.from_nanos(fields[0], fields[1]) }
253
+ # LocalTime (0x74)
254
+ unpacker.register_hydration_handler(0x74) { |fields| Types::LocalTime.from_nanos(fields[0]) }
255
+ # DateTime with offset, legacy LOCAL seconds (0x46): subtract offset.
256
+ unpacker.register_hydration_handler(0x46) do |fields|
257
+ ::Time.at(fields[0] - fields[2], fields[1], :nanosecond).getlocal(fields[2])
258
+ end
259
+ # DateTime with offset, UTC seconds (0x49, Bolt 5.0+).
260
+ unpacker.register_hydration_handler(0x49) do |fields|
261
+ ::Time.at(fields[0], fields[1], :nanosecond).getlocal(fields[2])
262
+ end
263
+ # LocalDateTime (0x64)
264
+ unpacker.register_hydration_handler(0x64) { |fields| Types::LocalDateTime.from_epoch(fields[0], fields[1]) }
265
+ # DateTimeZoneId, legacy LOCAL seconds (0x66).
266
+ unpacker.register_hydration_handler(0x66) do |fields|
267
+ wall_clock = ::Time.at(fields[0], fields[1], :nanosecond).utc
268
+ hydrate_named_zone(wall_clock, fields[2], local_seconds: true)
269
+ end
270
+ # DateTimeZoneId, UTC seconds (0x69, Bolt 5.0+).
271
+ unpacker.register_hydration_handler(0x69) do |fields|
272
+ utc_instant = ::Time.at(fields[0], fields[1], :nanosecond).utc
273
+ hydrate_named_zone(utc_instant, fields[2], local_seconds: false)
274
+ end
275
+ # Duration (0x45)
276
+ unpacker.register_hydration_handler(0x45) { |fields| Types::Duration.new(fields[0], fields[1], fields[2], fields[3]) }
277
+ # Point2D (0x58)
278
+ unpacker.register_hydration_handler(0x58) { |fields| Types::Point.new(srid: fields[0], x: fields[1], y: fields[2]) }
279
+ # Point3D (0x59)
280
+ unpacker.register_hydration_handler(0x59) do |fields|
281
+ Types::Point.new(srid: fields[0], x: fields[1], y: fields[2], z: fields[3])
282
+ end
283
+ end
284
+
285
+ # See CLAUDE.md "LOCAL seconds encoding". Both 0x66 (legacy local) and
286
+ # 0x69 (UTC) resolve a named tz at an instant; the only difference is
287
+ # whether the caller already has the UTC instant.
288
+ def hydrate_named_zone(instant, zone_name, local_seconds:)
289
+ if defined?(ActiveSupport::TimeZone)
290
+ tz = ActiveSupport::TimeZone[zone_name]
291
+ # A nil lookup is an unknown zone id — defer it (see below).
292
+ return unresolvable_zone(zone_name) if tz.nil?
293
+
294
+ utc_instant = local_seconds ? tz.tzinfo.local_to_utc(instant) : instant
295
+ tz.at(utc_instant)
296
+ else
297
+ tz = TZInfo::Timezone.get(zone_name) # raises InvalidTimezoneIdentifier if unknown
298
+ utc_instant = local_seconds ? tz.local_to_utc(instant) : instant
299
+ utc_instant.getlocal(tz.period_for_utc(utc_instant).utc_total_offset)
300
+ end
301
+ rescue TZInfo::InvalidTimezoneIdentifier
302
+ unresolvable_zone(zone_name)
303
+ rescue StandardError
304
+ # The zone id IS known, but the local->UTC mapping failed (a DST gap /
305
+ # overlap: TZInfo::PeriodNotFound / AmbiguousTime, or similar). Keep
306
+ # the prior lenient fallback — returning the raw instant — rather than
307
+ # misreport it as an unknown zone.
308
+ instant
309
+ end
310
+
311
+ # Placeholder for a zone id this runtime's tz database doesn't know (the
312
+ # server sent a name we can't resolve). We're on the reader thread
313
+ # mid-record; raising here would break the connection and strand the
314
+ # whole result, so defer it — the value raises (naming the zone) only
315
+ # when a consumer uses it, leaving the record + connection intact so an
316
+ # open transaction can still roll back.
317
+ def unresolvable_zone(zone_name) = Types::UnresolvableZonedDateTime.new(zone_name)
318
+ end
319
+ end
320
+ end
321
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Neo4j
4
+ module Driver
5
+ # Bookmark for transaction causality
6
+ class Bookmark < String
7
+ # Compatibility alias with jruby driver (which wraps java driver)
8
+ alias value itself
9
+
10
+ class << self
11
+ alias from new
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Neo4j
4
+ module Driver
5
+ # Factory for the driver's default BookmarkManager. Mirrors
6
+ # `org.neo4j.driver.BookmarkManagers#defaultManager` — but with a
7
+ # Ruby keyword-arg surface instead of a config builder, matching
8
+ # the JRuby flavour's ext shim (lib/jruby/.../ext/bookmark_managers.rb).
9
+ #
10
+ # The returned object is duck-typed: any value responding to
11
+ #
12
+ # bookmarks -> Set<Bookmark>
13
+ # update_bookmarks(previous, new) -> void
14
+ #
15
+ # is a manager. Pass your own instance to `Driver#session` or
16
+ # `Driver#execute_query` via `:bookmark_manager` if you want a
17
+ # store backed by something other than the in-memory default
18
+ # (e.g. Redis); no inheritance or interface declaration needed.
19
+ #
20
+ # `initial_bookmarks` — seed the manager with bookmarks the caller
21
+ # already has (e.g. from a persisted store).
22
+ # `bookmarks_supplier` — callable returning extra bookmarks to merge
23
+ # into every `bookmarks` call (lets external
24
+ # bookmark sources participate without being
25
+ # folded into the manager's own state).
26
+ # `bookmarks_consumer` — callable receiving the new bookmark snapshot
27
+ # after every successful update (lets external
28
+ # observers persist or forward bookmarks).
29
+ module BookmarkManagers
30
+ def self.default_manager(initial_bookmarks: nil, bookmarks_supplier: nil, bookmarks_consumer: nil)
31
+ Internal::DefaultBookmarkManager.new(
32
+ initial_bookmarks:,
33
+ bookmarks_supplier:,
34
+ bookmarks_consumer:
35
+ )
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Neo4j
4
+ module Driver
5
+ # A client certificate for mutual TLS (Feature:API:SSLClientCertificate):
6
+ # the certificate PEM file, its private-key PEM file, and the key's
7
+ # optional password. Built via ClientCertificates.of and served by a
8
+ # ClientCertificateManager. Mirrors org.neo4j.driver.ClientCertificate.
9
+ class ClientCertificate
10
+ attr_reader :certfile, :keyfile, :password
11
+
12
+ def initialize(certfile, keyfile, password = nil)
13
+ @certfile = certfile
14
+ @keyfile = keyfile
15
+ @password = password
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Neo4j
4
+ module Driver
5
+ # Supplies the current client certificate for mutual TLS
6
+ # (Feature:API:SSLClientCertificate). Wrap a block that returns a
7
+ # ClientCertificate — or nil when nothing changed since the last call, in
8
+ # which case the previously supplied certificate is kept. Pass an instance
9
+ # to GraphDatabase.driver via `client_certificate_manager:`; the driver
10
+ # consults it whenever a connection needs a (possibly rotated) certificate.
11
+ #
12
+ # The MRI counterpart of the Java driver's org.neo4j.driver
13
+ # .ClientCertificateManager (whose get returns null for "no change"); the
14
+ # last non-nil certificate is retained here so a fresh per-connection TLS
15
+ # context always presents the current one.
16
+ class ClientCertificateManager
17
+ def initialize(&get_client_certificate)
18
+ @get_client_certificate = get_client_certificate
19
+ @current = nil
20
+ @mutex = Mutex.new
21
+ end
22
+
23
+ # The current client certificate. Polls the block; a non-nil result
24
+ # rotates the retained certificate, a nil result keeps it. Connections
25
+ # are acquired concurrently, so the poll-and-update is serialized: it
26
+ # keeps @current consistent and stops a blocking provider (the testkit
27
+ # callback round-trips to the frontend) from being entered concurrently.
28
+ def get_client_certificate
29
+ @mutex.synchronize do
30
+ certificate = @get_client_certificate.call
31
+ @current = certificate if certificate
32
+ @current
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Neo4j
4
+ module Driver
5
+ # Factory for ClientCertificateManager, mirroring
6
+ # org.neo4j.driver.ClientCertificateManagers.
7
+ module ClientCertificateManagers
8
+ # A manager that presents the given (static) client certificate on every
9
+ # request — the non-rotating case.
10
+ def self.rotating(client_certificate)
11
+ ClientCertificateManager.new { client_certificate }
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Neo4j
4
+ module Driver
5
+ # Factory for ClientCertificate, mirroring org.neo4j.driver.ClientCertificates.
6
+ # Accepts path strings (or anything with #to_s, e.g. a Pathname) for the
7
+ # certificate and private-key PEM files, plus the key's optional password.
8
+ module ClientCertificates
9
+ def self.of(certfile, keyfile, password = nil)
10
+ ClientCertificate.new(certfile.to_s, keyfile.to_s, password)
11
+ end
12
+ end
13
+ end
14
+ end