neo4j-ruby-driver 5.7.0.alpha.4 → 6.0.0.alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +440 -40
  3. data/lib/neo4j/driver/{auto_closable.rb → auto_closeable.rb} +6 -6
  4. data/lib/neo4j/driver/internal/deprecator.rb +15 -0
  5. data/ruby/neo4j/driver/bookmark.rb +2 -2
  6. data/ruby/neo4j/driver/graph_database.rb +2 -2
  7. data/ruby/neo4j/driver/internal/async/immutable_connection_context.rb +5 -5
  8. data/ruby/neo4j/driver/internal/async/internal_async_session.rb +1 -1
  9. data/ruby/neo4j/driver/internal/async/network_session.rb +7 -7
  10. data/ruby/neo4j/driver/internal/async/unmanaged_transaction.rb +3 -3
  11. data/ruby/neo4j/driver/internal/cluster/routing_table_handler_impl.rb +1 -1
  12. data/ruby/neo4j/driver/internal/default_bookmark_holder.rb +2 -2
  13. data/ruby/neo4j/driver/internal/delegating_transaction.rb +13 -0
  14. data/ruby/neo4j/driver/internal/eager_result_value.rb +5 -0
  15. data/ruby/neo4j/driver/internal/handlers/commit_tx_response_handler.rb +1 -3
  16. data/ruby/neo4j/driver/internal/handlers/pulln/auto_pull_response_handler.rb +3 -2
  17. data/ruby/neo4j/driver/internal/handlers/session_pull_response_completion_listener.rb +1 -1
  18. data/ruby/neo4j/driver/internal/internal_bookmark.rb +2 -29
  19. data/ruby/neo4j/driver/internal/internal_driver.rb +11 -2
  20. data/ruby/neo4j/driver/internal/internal_session.rb +17 -3
  21. data/ruby/neo4j/driver/internal/messaging/encode/route_message_encoder.rb +1 -1
  22. data/ruby/neo4j/driver/internal/messaging/request/begin_message.rb +2 -2
  23. data/ruby/neo4j/driver/internal/messaging/request/run_with_metadata_message.rb +2 -2
  24. data/ruby/neo4j/driver/internal/messaging/request/transaction_metadata_builder.rb +2 -2
  25. data/ruby/neo4j/driver/internal/messaging/v3/bolt_protocol_v3.rb +3 -3
  26. data/ruby/neo4j/driver/internal/packstream/pack_stream.rb +0 -2
  27. data/ruby/neo4j/driver/internal/read_only_bookmark_holder.rb +4 -4
  28. data/ruby/neo4j/driver/internal/session_factory_impl.rb +1 -1
  29. data/ruby/neo4j/driver/internal/summary/internal_notification.rb +2 -2
  30. data/ruby/neo4j/driver/internal/util/metadata_extractor.rb +1 -7
  31. data/ruby/neo4j/driver/version.rb +1 -1
  32. data/ruby/neo4j/driver.rb +2 -0
  33. metadata +26 -17
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6e0343454cd9cf98cab65814233386d198abbd6644152af5b0e514f2e2d152ea
4
- data.tar.gz: fe48e618ebbcacd6148f31055367b5e6feb328a24dca43a6769f0261c9de7a68
3
+ metadata.gz: 2cb3ba5c3c1dda74bf82e77866ac67ad834c3cc0fbe34c60c6f94d15040f56f2
4
+ data.tar.gz: 50a8a7f3c771de94889c3edfc28e2c0d3f26fc80c39bae330d81b5d34aedf4ae
5
5
  SHA512:
6
- metadata.gz: 3d8c347a0cee9ae197dfca6afd2deaed9f144a72df354a18f3298c052c75c6a627eae062993f638b67cace9b4195938845e6fb1917f9c9f034b5a349e2c0b4dd
7
- data.tar.gz: 0c87b4ba135c8ad6626ac0d0fc8678ccc7e255860a163f4d0a862a62b2b6795d9cffab01fdd5c803df93d0ca69007cfb0e27eb77455477789e617e6dcf59a514
6
+ metadata.gz: f2011130ffcc499091ded7d02ff85484ec8f170a4d7adca828bf7d125eaa9d4b3b1ec0d1c93b53b0d1379ac8b378bb5c77ef7f869e0d1ffe4a2fca4442672a1b
7
+ data.tar.gz: bae2f8340186a2f0ad94da8e24c193dfdea98bee1a814ea78df481b35e9f4e4ea93c1827b662a46a9a742eaf94d82b8e09b9721754aad2a26dfb77196429ce5d
data/README.md CHANGED
@@ -1,12 +1,50 @@
1
- # Neo4j::Driver
1
+ # Neo4j Ruby Driver
2
2
 
3
- home :: https://github.com/neo4jrb/neo4j-ruby-driver
3
+ This repository contains 2 implementation of a Neo4j driver for Ruby:
4
4
 
5
- This repository contains 2 implementation of a neo4j driver for ruby:
6
- - based on official java implementation. It provides a thin wrapper over the java driver (only on jruby).
7
- - pure ruby implmementation. Available on all ruby versions >= 3.1.
5
+ - based on official Java implementation. It provides a thin wrapper over the Java driver (only on jruby).
6
+ - pure Ruby implementation. Available on all Ruby versions >= 3.1.
8
7
 
9
- ## Installation
8
+ Network communication is handled using [Bolt Protocol](https://7687.org/).
9
+
10
+ <details>
11
+ <summary>Table of Contents</summary>
12
+
13
+ * [Getting started](#getting-started)
14
+ * [Installation](#installation)
15
+ * [Getting a Neo4j instance](#getting-a-neo4j-instance)
16
+ * [Quick start example](#quick-start-example)
17
+ * [Server Compatibility](#server-compatibility)
18
+ * [Usage](#usage)
19
+ * [Connecting to a database](#connecting-to-a-database)
20
+ * [URI schemes](#uri-schemes)
21
+ * [Authentication](#authentication)
22
+ * [Configuration](#configuration)
23
+ * [Connectivity check](#connectivity-check)
24
+ * [Sessions & transactions](#sessions--transactions)
25
+ * [Session](#session)
26
+ * [Auto-commit transactions](#auto-commit-transactions)
27
+ * [Explicit transactions](#explicit-transactions)
28
+ * [Read transactions](#read-transactions)
29
+ * [Write transactions](#write-transactions)
30
+ * [Working with results](#working-with-results)
31
+ * [Accessing Node and Relationship data](#accessing-node-and-relationship-data)
32
+ * [Working with Paths](#working-with-paths)
33
+ * [Working with temporal types](#working-with-temporal-types)
34
+ * [Type mapping](#type-mapping)
35
+ * [Advanced](#advanced)
36
+ * [Connection pooling](#connection-pooling)
37
+ * [Logging](#logging)
38
+ * [For Driver Engineers](#for-driver-engineers)
39
+ * [Testing](#testing)
40
+ * [Contributing](#contributing)
41
+ * [License](#license)
42
+
43
+ </details>
44
+
45
+ ## Getting started
46
+
47
+ ### Installation
10
48
 
11
49
  Add this line to your application's Gemfile:
12
50
 
@@ -16,68 +54,430 @@ gem 'neo4j-ruby-driver'
16
54
 
17
55
  And then execute:
18
56
 
19
- $ bundle
57
+ ```bash
58
+ bundle install
59
+ ```
20
60
 
21
61
  Or install it yourself as:
22
62
 
23
- $ gem install neo4j-ruby-driver
63
+ ```bash
64
+ gem install neo4j-ruby-driver
65
+ ```
66
+
67
+ ### Getting a Neo4j instance
68
+
69
+ You need a running Neo4j database in order to use the driver with it. The easiest way to spin up a **local instance** is
70
+ through a Docker container.
71
+
72
+ The command below runs the latest Neo4j version in Docker, setting the admin username and password to `neo4j` and
73
+ `password` respectively:
74
+
75
+ ```bash
76
+ docker run \
77
+ -p7474:7474 \
78
+ -p7687:7687 \
79
+ -d \
80
+ -e NEO4J_AUTH=neo4j/password \
81
+ neo4j:latest
82
+ ```
83
+
84
+ ### Quick start example
85
+
86
+ ```ruby
87
+ require 'neo4j/driver'
88
+
89
+ Neo4j::Driver::GraphDatabase.driver(
90
+ 'bolt://localhost:7687',
91
+ Neo4j::Driver::AuthTokens.basic('neo4j', 'password')
92
+ ) do |driver|
93
+ driver.session(database: 'neo4j') do |session|
94
+ query_result = session.run('RETURN 2+2 AS value')
95
+ puts "2+2 equals #{query_result.single['value']}"
96
+
97
+ # consume gives the execution summary
98
+ create_result = session.run('CREATE (n)').consume
99
+ puts "Nodes created: #{create_result.counters.nodes_created}"
100
+ end
101
+ end
102
+ ```
24
103
 
25
104
  ## Server Compatibility
26
105
 
27
- The compatibility with Neo4j Server versions is documented in the [Neo4j Knowledge Base](https://neo4j.com/developer/kb/neo4j-supported-versions/).
106
+ The compatibility with Neo4j Server versions is documented in
107
+ the [Neo4j Knowledge Base](https://neo4j.com/developer/kb/neo4j-supported-versions/).
28
108
 
29
109
  ## Usage
30
110
 
31
- The API is to highest possible degree consistent with the official java driver.
32
- At this moment [The Neo4j Drivers Manual v4.4](https://neo4j.com/docs/java-manual/current/) along with the ruby version of the [code fragments](https://github.com/neo4jrb/neo4j-ruby-driver/blob/master/docs/dev_manual_examples.rb) and the ruby specs provide the only documentation.
111
+ The API is to highest possible degree consistent with the official Java driver. Please refer to
112
+ the [Neo4j Java Driver Manual](https://neo4j.com/docs/java-manual/current/), [examples in Ruby](https://github.com/neo4jrb/neo4j-ruby-driver/blob/master/docs/dev_manual_examples.rb),
113
+ and code snippets below to understand how to use it.
114
+ [Neo4j Java Driver API Docs](https://neo4j.com/docs/api/java-driver/current/) can be helpful as well.
115
+
116
+ ### Connecting to a database
117
+
118
+ #### URI schemes
119
+
120
+ The driver supports the following URI schemes:
121
+
122
+ | URI Scheme | Description |
123
+ |----------------|---------------------------------------------------------------------------------|
124
+ | `neo4j://` | Connect using routing to a cluster/causal cluster. |
125
+ | `neo4j+s://` | Same as `neo4j://` but with full TLS encryption. |
126
+ | `neo4j+ssc://` | Same as `neo4j://` but with full TLS encryption, without hostname verification. |
127
+ | `bolt://` | Connect directly to a server using the Bolt protocol. |
128
+ | `bolt+s://` | Same as `bolt://` but with full TLS encryption. |
129
+ | `bolt+ssc://` | Same as `bolt://` but with full TLS encryption, without hostname verification. |
130
+
131
+ Example:
132
+
133
+ ```ruby
134
+ # Connect to a single instance
135
+ driver = Neo4j::Driver::GraphDatabase.driver(
136
+ 'bolt://localhost:7687',
137
+ Neo4j::Driver::AuthTokens.basic('neo4j', 'password')
138
+ )
139
+
140
+ # Connect to a cluster
141
+ driver = Neo4j::Driver::GraphDatabase.driver(
142
+ 'neo4j://graph.example.com:7687',
143
+ Neo4j::Driver::AuthTokens.basic('neo4j', 'password')
144
+ )
145
+ ```
146
+
147
+ #### Authentication
148
+
149
+ The driver provides multiple authentication methods:
150
+
151
+ ```ruby
152
+ # Basic authentication
153
+ auth = Neo4j::Driver::AuthTokens.basic('neo4j', 'password')
154
+
155
+ # With realm specification
156
+ auth = Neo4j::Driver::AuthTokens.basic('neo4j', 'password', 'realm')
157
+
158
+ # Kerberos authentication
159
+ auth = Neo4j::Driver::AuthTokens.kerberos('ticket')
160
+
161
+ # Bearer authentication
162
+ auth = Neo4j::Driver::AuthTokens.bearer('token')
163
+
164
+ # Custom authentication
165
+ auth = Neo4j::Driver::AuthTokens.custom('principal', 'credentials', 'realm', 'scheme')
166
+
167
+ # No authentication
168
+ auth = Neo4j::Driver::AuthTokens.none
169
+ ```
170
+
171
+ #### Configuration
172
+
173
+ You can configure the driver with additional options:
174
+
175
+ ```ruby
176
+ config = {
177
+ connection_timeout: 15.seconds,
178
+ connection_acquisition_timeout: 1.minute,
179
+ max_transaction_retry_time: 30.seconds,
180
+ encryption: true,
181
+ trust_strategy: :trust_all_certificates
182
+ }
183
+
184
+ driver = Neo4j::Driver::GraphDatabase.driver(
185
+ 'neo4j://localhost:7687',
186
+ Neo4j::Driver::AuthTokens.basic('neo4j', 'password'),
187
+ **config
188
+ )
189
+ ```
190
+
191
+ #### Connectivity check
192
+
193
+ ```ruby
194
+ if driver.verify_connectivity
195
+ puts "Driver is connected to the database"
196
+ else
197
+ puts "Driver cannot connect to the database"
198
+ end
199
+ ```
200
+
201
+ ### Sessions & transactions
202
+
203
+ The driver provides sessions to interact with the database and to execute queries.
204
+
205
+ #### Session
206
+
207
+ Sessions are lightweight and disposable database connections. Always close your sessions when done:
208
+
209
+ ```ruby
210
+ session = driver.session(database: 'neo4j')
211
+ begin
212
+ session.run('MATCH (n) RETURN n LIMIT 10')
213
+ ensure
214
+ session.close
215
+ end
216
+ ```
217
+
218
+ Or use a block that automatically closes the session:
219
+
220
+ ```ruby
221
+ driver.session(database: 'neo4j') do |session|
222
+ session.run('MATCH (n) RETURN n LIMIT 10')
223
+ end
224
+ ```
225
+
226
+ Session options:
227
+
228
+ ```ruby
229
+ # Default database
230
+ session = driver.session
231
+
232
+ # Specific database
233
+ session = driver.session(database: 'neo4j')
234
+
235
+ # With access mode
236
+ session = driver.session(database: 'neo4j', default_access_mode: Neo4j::Driver::AccessMode::READ)
237
+
238
+ # With bookmarks for causal consistency
239
+ session = driver.session(
240
+ database: 'neo4j',
241
+ bookmarks: [Neo4j::Driver::Bookmark.from('bookmark-1')]
242
+ )
243
+ ```
244
+
245
+ #### Auto-commit transactions
246
+
247
+ For simple, one-off queries, use auto-commit transactions:
248
+
249
+ ```ruby
250
+ session.run('CREATE (n:Person {name: $name})', name: 'Alice')
251
+ ```
252
+
253
+ #### Explicit transactions
254
+
255
+ For multiple queries that need to be executed as a unit, use explicit transactions:
256
+
257
+ ```ruby
258
+ tx = session.begin_transaction
259
+ begin
260
+ tx.run('CREATE (n:Person {name: $name})', name: 'Alice')
261
+ tx.run('CREATE (n:Person {name: $name})', name: 'Bob')
262
+ tx.commit
263
+ rescue
264
+ tx.rollback
265
+ raise
266
+ end
267
+ ```
268
+
269
+ #### Read transactions
270
+
271
+ Specifically for read operations:
272
+
273
+ ```ruby
274
+ result = session.read_transaction do |tx|
275
+ tx.run('MATCH (n:Person) RETURN n.name').map { |record| record['n.name'] }
276
+ end
277
+ puts result
278
+ ```
279
+
280
+ #### Write transactions
281
+
282
+ Specifically for write operations:
283
+
284
+ ```ruby
285
+ session.write_transaction do |tx|
286
+ tx.run('CREATE (n:Person {name: $name})', name: 'Charlie')
287
+ end
288
+ ```
289
+
290
+ ### Working with results
291
+
292
+ ```ruby
293
+ result = session.run('MATCH (n:Person) RETURN n.name AS name, n.age AS age')
294
+
295
+ # Process results
296
+ result.each do |record|
297
+ puts "#{record['name']} is #{record['age']} years old"
298
+ end
299
+
300
+ # Check if there are more results
301
+ puts "Has more results: #{result.has_next?}"
302
+
303
+ # Get a single record
304
+ single = result.single
305
+ puts single['name'] if single
306
+
307
+ # Get keys available in the result
308
+ puts "Keys: #{result.keys}"
309
+
310
+ # Access by field index
311
+ result.each do |record|
312
+ puts "First field: #{record[0]}"
313
+ end
314
+
315
+ # Convert to array
316
+ records = result.to_a
317
+ ```
318
+
319
+ #### Accessing Node and Relationship data
320
+
321
+ Working with graph entities:
322
+
323
+ ```ruby
324
+ result = session.run('MATCH (p:Person)-[r:KNOWS]->(friend) RETURN p, r, friend')
325
+
326
+ result.each do |record|
327
+ # Working with nodes
328
+ person = record['p']
329
+ puts "Node ID: #{person.id}"
330
+ puts "Labels: #{person.labels.join(', ')}"
331
+ puts "Properties: #{person.properties}"
332
+ puts "Name property: #{person.properties['name']}"
333
+
334
+ # Working with relationships
335
+ relationship = record['r']
336
+ puts "Relationship ID: #{relationship.id}"
337
+ puts "Type: #{relationship.type}"
338
+ puts "Properties: #{relationship.properties}"
339
+
340
+ # Start and end nodes of the relationship
341
+ puts "Relationship: #{relationship.start_node_id} -> #{relationship.end_node_id}"
342
+ end
343
+ ```
344
+
345
+ #### Working with Paths
346
+
347
+ Processing paths returned from Cypher:
348
+
349
+ ```ruby
350
+ result = session.run('MATCH p = (:Person)-[:KNOWS*]->(:Person) RETURN p')
351
+
352
+ result.each do |record|
353
+ path = record['p']
354
+
355
+ # Get all nodes in the path
356
+ nodes = path.nodes
357
+ puts "Nodes in path: #{nodes.map { |n| n.properties['name'] }.join(' -> ')}"
358
+
359
+ # Get all relationships in the path
360
+ relationships = path.relationships
361
+ puts "Relationship types: #{relationships.map(&:type).join(', ')}"
362
+
363
+ # Iterate through the path segments
364
+ path.each do |segment|
365
+ puts "#{segment.start_node.properties['name']} -[#{segment.relationship.type}]-> #{segment.end_node.properties['name']}"
366
+ end
367
+ end
368
+ ```
369
+
370
+ #### Working with temporal types
371
+
372
+ Creating a node with properties of temporal types:
373
+
374
+ ```ruby
375
+ session.run(
376
+ 'CREATE (e:Event {datetime: $datetime, duration: $duration})',
377
+ datetime: DateTime.new(2025, 5, 5, 5, 55, 55), duration: 1.hour
378
+ )
379
+ ```
380
+
381
+ Querying temporal values:
382
+
383
+ ```ruby
384
+ session.run('MATCH (e:Event) LIMIT 1 RETURN e.datetime, e.duration').single.to_h
385
+ # => {"e.datetime": 2025-05-05 05:55:55 +0000, "e.duration": 3600 seconds}
386
+ ```
387
+
388
+ ### Type mapping
33
389
 
34
- [Neo4j Java Driver 4.3 API](https://neo4j.com/docs/api/java-driver/current/) can be helpful as well..
390
+ The Neo4j Ruby Driver maps Cypher types to Ruby types:
35
391
 
36
- ## Development
392
+ | Cypher Type | Ruby Type |
393
+ |----------------|-----------------------------------------------|
394
+ | null | nil |
395
+ | List | Enumerable |
396
+ | Map | Hash (symbolized keys) |
397
+ | Boolean | TrueClass/FalseClass |
398
+ | Integer | Integer/String[^1] |
399
+ | Float | Float |
400
+ | String | String/Symbol[^2] (encoding: UTF-8) |
401
+ | ByteArray | String (encoding: BINARY) |
402
+ | Date | Date |
403
+ | Zoned Time | Neo4j::Driver::Types::OffsetTime |
404
+ | Local Time | Neo4j::Driver::Types::LocalTime |
405
+ | Zoned DateTime | Time/ActiveSupport::TimeWithZone/DateTime[^3] |
406
+ | Local DateTime | Neo4j::Driver::Types::LocalDateTime |
407
+ | Duration | ActiveSupport::Duration |
408
+ | Point | Neo4j::Driver::Types::Point |
409
+ | Node | Neo4j::Driver::Types::Node |
410
+ | Relationship | Neo4j::Driver::Types::Relationship |
411
+ | Path | Neo4j::Driver::Types::Path |
37
412
 
38
- This gem includes 2 different implementations: java driver wrapper and pure ruby driver
413
+ [^1]: An Integer smaller than -2 ** 63 or larger than 2 ** 63 will always be implicitly converted to String
414
+ [^2]: A Symbol passed as a parameter will always be implicitly converted to String. All Strings other than BINARY
415
+ encoded are converted to UTF-8 when stored in Neo4j
416
+ [^3]: A Ruby DateTime passed as a parameter will always be implicitly converted to Time
39
417
 
40
- $ bin/setup
41
-
42
- ## Testing
418
+ ### Advanced
43
419
 
44
- To run the tests the following tools need to be installed:
420
+ #### Connection pooling
45
421
 
46
- $ brew install python
47
- $ pip3 install --user git+https://github.com/klobuczek/boltkit@1.3#egg=boltkit
48
- $ neoctrl-install -e 4.4.5 servers
49
- $ neoctrl-configure servers/neo4j-enterprise-4.4.5 dbms.directories.import= dbms.default_listen_address=::
50
- $ neoctrl-set-initial-password pass servers/neo4j-enterprise-4.4.5
51
- $ neoctrl-start servers/neo4j-enterprise-4.4.5
422
+ The driver handles connection pooling automatically. Configure the connection pool:
423
+
424
+ ```ruby
425
+ config = {
426
+ max_connection_pool_size: 100,
427
+ max_connection_lifetime: 1.hour
428
+ }
52
429
 
53
- To run the tests:
54
- ```console
55
- $ bin/setup
56
- $ rspec spec
430
+ driver = Neo4j::Driver::GraphDatabase.driver('neo4j://localhost:7687', auth, **config)
57
431
  ```
58
432
 
59
- Known errors:
433
+ #### Logging
60
434
 
61
- 1. In case of heap space memory error (`org.neo4j.driver.exceptions.DatabaseException: Java heap space`), you should limit the dbms memory, for example:
435
+ Configure logging for the driver:
62
436
 
63
- ```console
64
- $ neoctrl-configure servers/neo4j-enterprise-4.4.5 dbms.memory.pagecache.size=600m dbms.memory.heap.max_size=600m dbms.memory.heap.initial_size=600m dbms.directories.import= dbms.connectors.default_listen_address=::
437
+ ```ruby
438
+ config = {
439
+ logger: Logger.new(STDOUT).tap { |log| log.level = Logger::DEBUG }
440
+ }
441
+
442
+ driver = Neo4j::Driver::GraphDatabase.driver('neo4j://localhost:7687', auth, **config)
65
443
  ```
66
444
 
67
- 2. When using command `pip3 install --user git+https://github.com/klobuczek/boltkit@1.3#egg=boltkit`, if you have m1 mac chip, you may get error when pip3 tries to install `cryptography`. Steps to take in that case (reference https://stackoverflow.com/a/70074869/2559490)
445
+ ## For Driver Engineers
68
446
 
69
- ```console
70
- $ pip uninstall cffi
71
- $ python -m pip install --upgrade pip
72
- $ pip install cffi
73
- $ pip install cryptography
447
+ This gem includes 2 different implementations: a Java driver wrapper and a pure Ruby driver, so you will have to run
448
+ this command every time you switch the Ruby engine:
449
+
450
+ ```bash
451
+ bin/setup
74
452
  ```
75
453
 
454
+ ### Testing
455
+
456
+ There are two sets of tests for the driver. To run the specs placed in this repository, use a normal rspec command:
457
+
458
+ ```bash
459
+ rspec spec
460
+ ```
461
+
462
+ To run the [Testkit](https://github.com/neo4j-drivers/testkit) that is used to test all Neo4j driver implementations,
463
+ use the following:
464
+
465
+ ```bash
466
+ git clone git@github.com:neo4j-drivers/testkit.git
467
+ cd testkit
468
+ export TEST_DRIVER_NAME=ruby
469
+ export TEST_DRIVER_REPO=`realpath ../neo4j-ruby-driver`
470
+ export TEST_NEO4J_PASS=password
471
+ python3 main.py --tests UNIT_TESTS --configs 4.3-enterprise
472
+ ```
473
+
474
+ Please refer to the [Testkit](https://github.com/neo4j-drivers/testkit) documentation to learn more about its features.
475
+
76
476
  ## Contributing
77
477
 
78
- Suggestions, improvements, bug reports and pull requests are welcome on GitHub at https://github.com/neo4jrb/neo4j-ruby-driver.
478
+ Suggestions, improvements, bug reports and pull requests are welcome on GitHub
479
+ at https://github.com/neo4jrb/neo4j-ruby-driver.
79
480
 
80
481
  ## License
81
482
 
82
483
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
83
-
@@ -2,8 +2,8 @@
2
2
 
3
3
  module Neo4j
4
4
  module Driver
5
- module AutoClosable
6
- def auto_closable(*methods)
5
+ module AutoCloseable
6
+ def auto_closeable(*methods)
7
7
  prepend with_block_definer(methods)
8
8
  end
9
9
 
@@ -13,15 +13,15 @@ module Neo4j
13
13
  Module.new do
14
14
  methods.each do |method|
15
15
  define_method(method) do |*args, **kwargs, &block|
16
- closable = super(*args, **kwargs)
16
+ closeable = super(*args, **kwargs)
17
17
  if block
18
18
  begin
19
- block.arity.zero? ? closable.instance_eval(&block) : block.call(closable)
19
+ block.arity.zero? ? closeable.instance_eval(&block) : block.call(closeable)
20
20
  ensure
21
- closable&.close
21
+ closeable&.close
22
22
  end
23
23
  else
24
- closable
24
+ closeable
25
25
  end
26
26
  end
27
27
  end
@@ -0,0 +1,15 @@
1
+ module Neo4j
2
+ module Driver
3
+ module Internal
4
+ module Deprecator
5
+ def self.deprecator
6
+ @deprecator ||= ActiveSupport::Deprecation.new('6.0', 'neo4j-ruby-driver')
7
+ end
8
+
9
+ def self.log_warning(old_method, new_method, version)
10
+ deprecator.deprecation_warning(old_method, new_method)
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -13,8 +13,8 @@ module Neo4j
13
13
  # Reconstruct bookmark from \bookmarks string values.
14
14
  # @param values values obtained from a previous bookmark.
15
15
  # @return A bookmark.
16
- def self.from(*values)
17
- Internal::InternalBookmark.parse(*values)
16
+ def self.from(value)
17
+ Internal::InternalBookmark.new(value)
18
18
  end
19
19
  end
20
20
  end
@@ -3,8 +3,8 @@
3
3
  module Neo4j::Driver
4
4
  class GraphDatabase
5
5
  class << self
6
- extend AutoClosable
7
- auto_closable :driver, :routing_driver
6
+ extend AutoCloseable
7
+ auto_closeable :driver, :routing_driver
8
8
 
9
9
  def driver(uri, auth_token = nil, **config)
10
10
  internal_driver(uri, auth_token, config)
@@ -2,16 +2,16 @@ module Neo4j::Driver
2
2
  module Internal
3
3
  module Async
4
4
  class ImmutableConnectionContext
5
- attr :database_name, :mode, :rediscovery_bookmark, :impersonated_user
5
+ attr :database_name, :mode, :rediscovery_bookmarks, :impersonated_user
6
6
 
7
- def initialize(database_name, bookmark, mode)
7
+ def initialize(database_name, bookmarks, mode)
8
8
  @database_name = database_name
9
- @rediscovery_bookmark = bookmark
9
+ @rediscovery_bookmarks = bookmarks
10
10
  @mode = mode
11
11
  end
12
12
 
13
- SINGLE_DB_CONTEXT = new(DatabaseNameUtil::DEFAULT_DATABASE, InternalBookmark::EMPTY, AccessMode::READ)
14
- MULTI_DB_CONTEXT = new(DatabaseNameUtil::SYSTEM_DATABASE, InternalBookmark::EMPTY, AccessMode::READ)
13
+ SINGLE_DB_CONTEXT = new(DatabaseNameUtil::DEFAULT_DATABASE, [], AccessMode::READ)
14
+ MULTI_DB_CONTEXT = new(DatabaseNameUtil::SYSTEM_DATABASE, [], AccessMode::READ)
15
15
 
16
16
  # A simple context is used to test connectivity with a remote server/cluster. As long as there is a read only service, the connection shall be established
17
17
  # successfully. Depending on whether multidb is supported or not, this method returns different context for routing table discovery.
@@ -6,7 +6,7 @@ module Neo4j::Driver
6
6
  @session = session
7
7
  end
8
8
 
9
- delegate :last_bookmark, :close_async, to: :@session
9
+ delegate :last_bookmarks, :close_async, to: :@session
10
10
 
11
11
  def run_async(query, parameters = {}, config = {})
12
12
  @session.run_async(org.neo4j.driver.Query.new(query, **parameters), **config)
@@ -11,7 +11,7 @@ module Neo4j::Driver
11
11
  @log = Logging::PrefixedLogger.new("[#{hash}]", logger)
12
12
  @bookmark_holder = bookmark_holder
13
13
  # @database_name = database_name.database_name
14
- @connection_context = NetworkSessionConnectionContext.new(database_name, @bookmark_holder.bookmark, impersonated_user)
14
+ @connection_context = NetworkSessionConnectionContext.new(database_name, @bookmark_holder.bookmarks, impersonated_user)
15
15
  @fetch_size = fetch_size
16
16
  @open = Concurrent::AtomicBoolean.new(true)
17
17
  end
@@ -28,7 +28,7 @@ module Neo4j::Driver
28
28
  acquire_connection(mode).then do |connection|
29
29
  ImpersonationUtil.ensure_impersonation_support(connection, connection.impersonated_user)
30
30
  tx = UnmanagedTransaction.new(connection, @bookmark_holder, @fetch_size)
31
- tx.begin_async(@bookmark_holder.bookmark, config)
31
+ tx.begin_async(@bookmark_holder.bookmarks, config)
32
32
  end&.tap { |new_transaction| @transaction = new_transaction }
33
33
  end
34
34
 
@@ -42,8 +42,8 @@ module Neo4j::Driver
42
42
  end
43
43
  end
44
44
 
45
- def last_bookmark
46
- @bookmark_holder.bookmark
45
+ def last_bookmarks
46
+ @bookmark_holder.bookmarks
47
47
  end
48
48
 
49
49
  def release_connection_async
@@ -131,11 +131,11 @@ module Neo4j::Driver
131
131
  # It has to be the initial bookmark given at the creation of the session.
132
132
  # As only that bookmark could carry extra system bookmarks
133
133
  attr_accessor :database_name
134
- attr :mode, :rediscovery_bookmark, :impersonated_user
134
+ attr :mode, :rediscovery_bookmarks, :impersonated_user
135
135
 
136
- def initialize(database_name, bookmark, impersonated_user)
136
+ def initialize(database_name, bookmarks, impersonated_user)
137
137
  @database_name = database_name
138
- @rediscovery_bookmark = bookmark
138
+ @rediscovery_bookmarks = bookmarks
139
139
  @impersonated_user = impersonated_user
140
140
  end
141
141
 
@@ -35,8 +35,8 @@ module Neo4j::Driver
35
35
  @state = State::ACTIVE
36
36
  end
37
37
 
38
- def begin_async(initial_bookmark, config)
39
- @protocol.begin_transaction(@connection, initial_bookmark, config)
38
+ def begin_async(initial_bookmarks, config)
39
+ @protocol.begin_transaction(@connection, initial_bookmarks, config)
40
40
  self
41
41
  rescue Neo4j::Driver::Exceptions::AuthorizationExpiredException
42
42
  @connection.terminate_and_release(Neo4j::Driver::Exceptions::AuthorizationExpiredException::DESCRIPTION)
@@ -175,7 +175,7 @@ module Neo4j::Driver
175
175
  if exception
176
176
  Util::ResultHolder.failed(exception)
177
177
  else
178
- @protocol.commit_transaction(@connection).then(&@bookmark_holder.method(:bookmark=))
178
+ @protocol.commit_transaction(@connection).then { @bookmark_holder.bookmarks = Set[it] }
179
179
  end
180
180
  end
181
181
 
@@ -33,7 +33,7 @@ module Neo4j::Driver
33
33
  @log.debug("Routing table for database '#{@database_name.description}' is stale. #{@routing_table}")
34
34
 
35
35
  fresh_cluster_composition_fetched(
36
- @rediscovery.lookup_cluster_composition(@routing_table, @connection_pool, context.rediscovery_bookmark,
36
+ @rediscovery.lookup_cluster_composition(@routing_table, @connection_pool, context.rediscovery_bookmarks,
37
37
  nil))
38
38
  else
39
39
  # existing routing table is fresh, use it
@@ -1,8 +1,8 @@
1
1
  module Neo4j::Driver
2
2
  module Internal
3
3
  class DefaultBookmarkHolder < ReadOnlyBookmarkHolder
4
- def bookmark=(bookmark)
5
- @bookmark = bookmark if bookmark.present?
4
+ def bookmarks=(bookmarks)
5
+ @bookmarks = bookmarks
6
6
  end
7
7
  end
8
8
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Neo4j::Driver
4
+ module Internal
5
+ class DelegatingTransaction
6
+ delegate :run, to: :@tx
7
+
8
+ def initialize(tx)
9
+ @tx = tx
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,5 @@
1
+ module Neo4j::Driver
2
+ module Internal
3
+ EagerResultValue = Struct.new(:keys, :records, :summary)
4
+ end
5
+ end
@@ -8,9 +8,7 @@ module Neo4j::Driver
8
8
  @result_holder = result_holder
9
9
  end
10
10
 
11
- def on_success(metadata)
12
- @result_holder.succeed(metadata[:bookmark]&.then(&InternalBookmark.method(:parse)))
13
- end
11
+ def on_success(metadata) = @result_holder.succeed(Util::MetadataExtractor.extract_bookmark(metadata))
14
12
 
15
13
  def on_failure(error)
16
14
  @result_holder.fail(error)
@@ -3,7 +3,7 @@ module Neo4j::Driver
3
3
  module Handlers
4
4
  module Pulln
5
5
  class AutoPullResponseHandler < BasicPullResponseHandler
6
- delegate :signal, to: :@records
6
+ delegate :signal, to: :@queue_notification
7
7
  LONG_MAX_VALUE = 2 ** 63 - 1
8
8
 
9
9
  def initialize(query, run_response_handler, connection, metadata_extractor, completion_listener, fetch_size)
@@ -19,7 +19,8 @@ module Neo4j::Driver
19
19
  @low_record_watermark = fetch_size * 0.3
20
20
  end
21
21
 
22
- @records = ::Async::Queue.new
22
+ @queue_notification = ::Async::Notification.new
23
+ @records = ::Async::Queue.new(available: @queue_notification)
23
24
  @auto_pull_enabled = true
24
25
 
25
26
  install_record_and_summary_consumers
@@ -9,7 +9,7 @@ module Neo4j::Driver
9
9
 
10
10
  def after_success(metadata)
11
11
  release_connection
12
- @bookmark_holder.bookmark = Util::MetadataExtractor.extract_bookmarks(metadata)
12
+ @bookmark_holder.bookmarks = Array(Util::MetadataExtractor.extract_bookmark(metadata)).to_set
13
13
  end
14
14
 
15
15
  def after_failure(error)
@@ -1,36 +1,9 @@
1
1
  module Neo4j::Driver
2
2
  module Internal
3
- class InternalBookmark
3
+ class InternalBookmark < String
4
4
  include Bookmark
5
- attr :values
6
- delegate :hash, :empty?, to: :values
7
5
 
8
- private def initialize(*values)
9
- @values = values.to_set
10
- end
11
- EMPTY = new.freeze
12
-
13
- def ==(other)
14
- equal?(other) || self.class == other.class && values == other.values
15
- end
16
-
17
- alias eql? ==
18
-
19
- def to_s
20
- "Bookmark{values=#{values}}"
21
- end
22
-
23
- class << self
24
- def empty
25
- EMPTY
26
- end
27
-
28
- def from(*bookmarks)
29
- new(*bookmarks.reduce(Set.new) { |set, bookmark| set + bookmark.values })
30
- end
31
-
32
- alias parse new
33
- end
6
+ def to_s = "Bookmark{value=#{super}}"
34
7
  end
35
8
  end
36
9
  end
@@ -1,12 +1,12 @@
1
1
  module Neo4j::Driver
2
2
  module Internal
3
3
  class InternalDriver
4
- extend AutoClosable
4
+ extend AutoCloseable
5
5
  extend Synchronizable
6
6
  attr_reader :session_factory, :metrics_provider
7
7
  # delegate :verify_connectivity, to: :session_factory
8
8
  delegate :metrics, :metrics_enabled?, to: :metrics_provider
9
- auto_closable :session
9
+ auto_closeable :session
10
10
  sync :close, :supports_multi_db?, :verify_connectivity, :session
11
11
 
12
12
  def initialize(security_plan, session_factory, metrics_provider, logger)
@@ -25,6 +25,15 @@ module Neo4j::Driver
25
25
  InternalAsyncSession.new(new_session(**session_config))
26
26
  end
27
27
 
28
+ def execute_query(query, auth_token = nil, config = {}, **parameters)
29
+ # TODO: auth_token not implemented yet
30
+ session(**config.slice(:bookmarks, :database, :impersonated_user, :default_access_mode, :fetch_size)) do |session|
31
+ session.run(query, parameters, config.slice(:timeout, :metadata)).then do
32
+ EagerResultValue.new(it.keys, it.to_a, it.consume)
33
+ end
34
+ end
35
+ end
36
+
28
37
  def encrypted?
29
38
  assert_open!
30
39
  @security_plan.requires_encryption?
@@ -1,11 +1,11 @@
1
1
  module Neo4j::Driver
2
2
  module Internal
3
3
  class InternalSession
4
- extend AutoClosable
4
+ extend AutoCloseable
5
5
  extend Synchronizable
6
6
  # include Ext::RunOverride
7
- delegate :open?, :last_bookmark, to: :@session
8
- auto_closable :begin_transaction
7
+ delegate :open?, :last_bookmarks, to: :@session
8
+ auto_closeable :begin_transaction
9
9
  sync :close, :begin_transaction, :run, :transaction
10
10
 
11
11
  def initialize(session)
@@ -38,15 +38,29 @@ module Neo4j::Driver
38
38
  end
39
39
 
40
40
  def read_transaction(**config, &block)
41
+ Deprecator.log_warning(:read_transaction, :execute_read, '6.0')
41
42
  transaction(AccessMode::READ, **config, &block)
42
43
  end
43
44
 
44
45
  def write_transaction(**config, &block)
46
+ Deprecator.log_warning(:write_transaction, :execute_write, '6.0')
45
47
  transaction(AccessMode::WRITE, **config, &block)
46
48
  end
47
49
 
50
+ def execute_read(**config, &block)
51
+ delegating_transaction(AccessMode::READ, **config, &block)
52
+ end
53
+
54
+ def execute_write(**config, &block)
55
+ delegating_transaction(AccessMode::WRITE, **config, &block)
56
+ end
57
+
48
58
  private
49
59
 
60
+ def delegating_transaction(mode, **config, &block)
61
+ transaction(mode, **config) { |tx| block.call(DelegatingTransaction.new(tx)) }
62
+ end
63
+
50
64
  def transaction(mode, **config)
51
65
  # use different code path compared to async so that work is executed in the caller thread
52
66
  # caller thread will also be the one who sleeps between retries;
@@ -8,7 +8,7 @@ module Neo4j::Driver
8
8
  Util::Preconditions.check_argument(message, Request::RouteMessage)
9
9
  packer.pack_struct_header(3, message.signature)
10
10
  packer.pack(message.routing_context)
11
- packer.pack(message.bookmark&.values || [])
11
+ packer.pack(message.bookmark || [])
12
12
  packer.pack(option(message))
13
13
  end
14
14
 
@@ -5,10 +5,10 @@ module Neo4j::Driver
5
5
  class BeginMessage < MessageWithMetadata
6
6
  SIGNATURE = 0x11
7
7
 
8
- def initialize(bookmark, config, database_name, mode, impersonated_user)
8
+ def initialize(bookmarks, config, database_name, mode, impersonated_user)
9
9
  super(Request::TransactionMetadataBuilder.build_metadata(
10
10
  timeout: config[:timeout], tx_metadata: config[:metadata], database_name: database_name, mode: mode,
11
- bookmark: bookmark, impersonated_user: impersonated_user))
11
+ bookmarks: bookmarks, impersonated_user: impersonated_user))
12
12
  end
13
13
 
14
14
  def signature
@@ -7,10 +7,10 @@ module Neo4j::Driver
7
7
  attr_reader :query, :parameters
8
8
 
9
9
  class << self
10
- def auto_commit_tx_run_message(query, config, database_name, mode, bookmark, impersonated_user)
10
+ def auto_commit_tx_run_message(query, config, database_name, mode, bookmarks, impersonated_user)
11
11
  metadata = Request::TransactionMetadataBuilder.build_metadata(
12
12
  timeout: config[:timeout], tx_metadata: config[:metadata], database_name: database_name, mode: mode,
13
- bookmark: bookmark, impersonated_user: impersonated_user)
13
+ bookmarks: bookmarks, impersonated_user: impersonated_user)
14
14
  new(query.text, query.parameters, metadata)
15
15
  end
16
16
 
@@ -6,9 +6,9 @@ module Neo4j::Driver
6
6
  MODE_READ_VALUE = 'r'
7
7
 
8
8
  class << self
9
- def build_metadata(timeout:, tx_metadata:, mode:, bookmark:, impersonated_user:,
9
+ def build_metadata(timeout:, tx_metadata:, mode:, bookmarks:, impersonated_user:,
10
10
  database_name: DatabaseNameUtil.default_database)
11
- { bookmarks: bookmark.presence,
11
+ { bookmarks: bookmarks.presence,
12
12
  tx_timeout: timeout&.then(&DurationNormalizer.method(:milliseconds)),
13
13
  tx_metadata: tx_metadata.presence,
14
14
  mode: (MODE_READ_VALUE if mode == AccessMode::READ),
@@ -30,9 +30,9 @@ module Neo4j::Driver
30
30
  message_dispatcher.prepare_to_close_channel
31
31
  end
32
32
 
33
- def begin_transaction(connection, bookmark, config)
33
+ def begin_transaction(connection, bookmarks, config)
34
34
  verify_database_name_before_transaction(connection.database_name)
35
- begin_message = Request::BeginMessage.new(bookmark, config, connection.database_name, connection.mode, connection.impersonated_user)
35
+ begin_message = Request::BeginMessage.new(bookmarks, config, connection.database_name, connection.mode, connection.impersonated_user)
36
36
  connection.write_and_flush(begin_message, Handlers::BeginTxResponseHandler.new)
37
37
  end
38
38
 
@@ -51,7 +51,7 @@ module Neo4j::Driver
51
51
  def run_in_auto_commit_transaction(connection, query, bookmark_holder, config, fetch_size)
52
52
  verify_database_name_before_transaction(connection.database_name)
53
53
 
54
- run_message = Request::RunWithMetadataMessage.auto_commit_tx_run_message(query, config, connection.database_name, connection.mode, bookmark_holder.bookmark, connection.impersonated_user)
54
+ run_message = Request::RunWithMetadataMessage.auto_commit_tx_run_message(query, config, connection.database_name, connection.mode, bookmark_holder.bookmarks, connection.impersonated_user)
55
55
 
56
56
  build_result_cursor_factory(connection, query, bookmark_holder, nil, run_message, fetch_size)
57
57
  end
@@ -114,8 +114,6 @@ module Neo4j::Driver
114
114
  value = value.to_a
115
115
  pack_list_header(value.size)
116
116
  value.each(&method(:pack))
117
- when Bookmark
118
- pack(value.values)
119
117
  else
120
118
  unpackable(value)
121
119
  end
@@ -1,13 +1,13 @@
1
1
  module Neo4j::Driver
2
2
  module Internal
3
3
  class ReadOnlyBookmarkHolder
4
- attr_reader :bookmark
4
+ attr_reader :bookmarks
5
5
 
6
- def initialize(bookmark = InternalBookmark.empty)
7
- @bookmark = bookmark
6
+ def initialize(bookmarks = Set[])
7
+ @bookmarks = bookmarks
8
8
  end
9
9
 
10
- def bookmark=(_value) end
10
+ def bookmarks=(_value) end
11
11
  end
12
12
  end
13
13
  end
@@ -13,7 +13,7 @@ module Neo4j::Driver
13
13
  end
14
14
 
15
15
  def new_instance(fetch_size: @default_fetch_size, default_access_mode: AccessMode::WRITE, **config)
16
- bookmark_holder = DefaultBookmarkHolder.new(InternalBookmark.from(*config[:bookmarks]))
16
+ bookmark_holder = DefaultBookmarkHolder.new(Array(config[:bookmarks]).to_set)
17
17
  create_session(parse_database_name(config), default_access_mode, bookmark_holder, fetch_size, config[:impersonated_user])
18
18
  end
19
19
 
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Neo4j::Driver::Internal::Summary
4
- class InternalNotification < Struct.new(:code, :title, :description, :severity, :position)
4
+ class InternalNotification < Struct.new(:code, :title, :description, :severity_level, :position)
5
5
 
6
6
  VALUE_TO_NOTIFICATION = lambda do |value|
7
- severity = value[:severity] || 'N/A'
7
+ severity = value[:severity]
8
8
 
9
9
  position = value[:position]&.then do |pos_value|
10
10
  InternalInputPosition.new(*pos_value.values_at(:offset, :line, :column).map(&:to_i))
@@ -35,13 +35,7 @@ module Neo4j::Driver
35
35
  Summary::InternalDatabaseInfo::DEFAULT_DATABASE_INFO
36
36
  end
37
37
 
38
- def extract_bookmarks(metadata)
39
- bookmark_value = metadata[:bookmark]
40
-
41
- return InternalBookmark.parse(bookmark_value) if bookmark_value&.is_a? String
42
-
43
- InternalBookmark.empty
44
- end
38
+ def extract_bookmark(metadata) = metadata[:bookmark]&.then(&InternalBookmark.method(:new))
45
39
 
46
40
  def extract_neo4j_server_version(metadata)
47
41
  server_value = extract_server(metadata)
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Neo4j
4
4
  module Driver
5
- VERSION = '5.7.0.alpha.4'
5
+ VERSION = '6.0.0.alpha.0'
6
6
  end
7
7
  end
data/ruby/neo4j/driver.rb CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'active_support/core_ext/array/grouping'
4
4
  require 'active_support/core_ext/hash/keys'
5
+ require 'active_support/core_ext/object/blank'
5
6
  require 'active_support/logger'
6
7
  require 'async/io'
7
8
  require 'async/io/stream'
@@ -14,6 +15,7 @@ module Neo4j
14
15
  module Driver
15
16
  Loader.load
16
17
 
18
+ EagerResult = Neo4j::Driver::Internal::EagerResultValue
17
19
  Record = Neo4j::Driver::Internal::InternalRecord
18
20
  Result = Neo4j::Driver::Internal::InternalResult
19
21
  Transaction = Neo4j::Driver::Internal::InternalTransaction
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: neo4j-ruby-driver
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.7.0.alpha.4
4
+ version: 6.0.0.alpha.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Heinrich Klobuczek
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-01-14 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: activesupport
@@ -24,49 +24,55 @@ dependencies:
24
24
  - !ruby/object:Gem::Version
25
25
  version: '7.1'
26
26
  - !ruby/object:Gem::Dependency
27
- name: zeitwerk
27
+ name: csv
28
28
  requirement: !ruby/object:Gem::Requirement
29
29
  requirements:
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
- version: 2.1.10
32
+ version: '3.0'
33
33
  type: :runtime
34
34
  prerelease: false
35
35
  version_requirements: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - ">="
38
38
  - !ruby/object:Gem::Version
39
- version: 2.1.10
39
+ version: '3.0'
40
40
  - !ruby/object:Gem::Dependency
41
- name: async
41
+ name: zeitwerk
42
42
  requirement: !ruby/object:Gem::Requirement
43
43
  requirements:
44
- - - "<"
44
+ - - ">="
45
45
  - !ruby/object:Gem::Version
46
- version: '2.13'
46
+ version: 2.1.10
47
47
  type: :runtime
48
48
  prerelease: false
49
49
  version_requirements: !ruby/object:Gem::Requirement
50
50
  requirements:
51
- - - "<"
51
+ - - ">="
52
52
  - !ruby/object:Gem::Version
53
- version: '2.13'
53
+ version: 2.1.10
54
54
  - !ruby/object:Gem::Dependency
55
- name: async-io
55
+ name: async
56
56
  requirement: !ruby/object:Gem::Requirement
57
57
  requirements:
58
58
  - - ">="
59
59
  - !ruby/object:Gem::Version
60
- version: '0'
60
+ version: '2.13'
61
+ - - "<"
62
+ - !ruby/object:Gem::Version
63
+ version: '2.24'
61
64
  type: :runtime
62
65
  prerelease: false
63
66
  version_requirements: !ruby/object:Gem::Requirement
64
67
  requirements:
65
68
  - - ">="
66
69
  - !ruby/object:Gem::Version
67
- version: '0'
70
+ version: '2.13'
71
+ - - "<"
72
+ - !ruby/object:Gem::Version
73
+ version: '2.24'
68
74
  - !ruby/object:Gem::Dependency
69
- name: connection_pool
75
+ name: async-io
70
76
  requirement: !ruby/object:Gem::Requirement
71
77
  requirements:
72
78
  - - ">="
@@ -80,7 +86,7 @@ dependencies:
80
86
  - !ruby/object:Gem::Version
81
87
  version: '0'
82
88
  - !ruby/object:Gem::Dependency
83
- name: csv
89
+ name: connection_pool
84
90
  requirement: !ruby/object:Gem::Requirement
85
91
  requirements:
86
92
  - - ">="
@@ -224,7 +230,7 @@ files:
224
230
  - README.md
225
231
  - lib/neo4j-ruby-driver.rb
226
232
  - lib/neo4j-ruby-driver_loader.rb
227
- - lib/neo4j/driver/auto_closable.rb
233
+ - lib/neo4j/driver/auto_closeable.rb
228
234
  - lib/neo4j/driver/exceptions/authentication_exception.rb
229
235
  - lib/neo4j/driver/exceptions/authorization_expired_exception.rb
230
236
  - lib/neo4j/driver/exceptions/certificate_exception.rb
@@ -252,6 +258,7 @@ files:
252
258
  - lib/neo4j/driver/exceptions/value/unsizable.rb
253
259
  - lib/neo4j/driver/exceptions/value/value_exception.rb
254
260
  - lib/neo4j/driver/internal/bolt_server_address.rb
261
+ - lib/neo4j/driver/internal/deprecator.rb
255
262
  - lib/neo4j/driver/internal/duration_normalizer.rb
256
263
  - lib/neo4j/driver/internal/validator.rb
257
264
  - lib/neo4j/driver/summary/query_type.rb
@@ -339,8 +346,10 @@ files:
339
346
  - ruby/neo4j/driver/internal/database_name_util.rb
340
347
  - ruby/neo4j/driver/internal/default_bookmark_holder.rb
341
348
  - ruby/neo4j/driver/internal/default_domain_name_resolver.rb
349
+ - ruby/neo4j/driver/internal/delegating_transaction.rb
342
350
  - ruby/neo4j/driver/internal/direct_connection_provider.rb
343
351
  - ruby/neo4j/driver/internal/driver_factory.rb
352
+ - ruby/neo4j/driver/internal/eager_result_value.rb
344
353
  - ruby/neo4j/driver/internal/handlers/begin_tx_response_handler.rb
345
354
  - ruby/neo4j/driver/internal/handlers/channel_releasing_reset_response_handler.rb
346
355
  - ruby/neo4j/driver/internal/handlers/commit_tx_response_handler.rb
@@ -524,7 +533,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
524
533
  - !ruby/object:Gem::Version
525
534
  version: '0'
526
535
  requirements: []
527
- rubygems_version: 3.6.2
536
+ rubygems_version: 3.6.9
528
537
  specification_version: 4
529
538
  summary: ''
530
539
  test_files: []