v5.5.0 - Feedback wanted on ExecuteQuery
📣
#441
Replies: 3 comments 1 reply
-
I think that these driver improvements, will get rid of a lot of excess code and work well for my cases. I'm going to give EagerResult a go and implement my own Result Transformers to see how they perform. Once i have done that, I'll be able to provide you with better feedback. However, these changes seem good, so great work! |
Beta Was this translation helpful? Give feedback.
-
Go driver 5.7.0 includes two changes for
|
Beta Was this translation helpful? Give feedback.
-
The feature has been stabilized with 5.8.0. Some minor adjustments were made:
|
Beta Was this translation helpful? Give feedback.
-
5.5.0 is out and we would like to highlight two noteworthy contributions.
Edit: 5.6.0 is now out and slightly changes the
ResultTransformer
contract.ExecuteQuery
API In Action
The first one is a new preview API at the top level:
ExecuteQuery
.Let us see it in action first, just below:
As you can see, this new function does not require much:
context.Context
parameter, like most of the APIs since 5.0DriverWithContext
instancenil
)neo4j.EagerResultTransformer
)Under the hood
A lot happens under the hood:
Moreover, it tracks bookmarks through a default
BookmarkManager
implementation so that subsequentExecuteQuery
reads can read the results of formerExecuteQuery
writes.You can even pass this bookmark manager instance to
SessionConfig
vianeo4j.DefaultExecuteQueryBookmarkManager()
, so the causal consistency is preserved across all the driver calls your application makes.As a consequence, you do not have to worry about all of this!
This is why we believe
ExecuteQuery
is a great starting point for new users. It does many things right by default.And there is more!
Configuration
For more fine-grained scenarios,
ExecuteQuery
accepts extra parameters:You can configure impersonation, select a specific database, change from the default
Writers
routing mode and/or disable bookmark management (or pass a customBookmarkManager
instance withneo4j.ExecuteQueryWithBookmarkManager
).Beyond
EagerResult
*EagerResult
is a good starting point, as it includes all you need about the results of your query.However, as its name suggests, it loads all records in memory, which is not a great thing to do when your query returns huge results (in size and/or quantity).
Fortunately, you can easily switch by providing your own
ResultTransformer
implementation.Starting with 5.6.0, the interface is defined as follows:
In 5.5.0, it was:
Accept
is called as many times as there are records to process.Complete
lets you compute the final result, with access to the result keys and summary.Since a transaction function is used under the hood, there may be several retries until the query executes properly.
Because of this,
ExecuteQuery
requires afunc() ResultTransformer[T]
and not aResultTransformer[T]
.That function should return a new instance every time it is called, so that the returned transformer always starts from an empty slate when the new transaction function execution starts.
Feedback wanted
This new API is currently in the preview stage.
What it means is that we are eagerly (no pun intended) waiting for your feedback.
Does it work well in your scenario? Do you wish there was more?
Could some defaults be improved?
Let us know and we will correct course in the next releases!
Better cancellation handling
Foreword
In 5.0, all the driver APIs were duplicated and revised to accept a
context.Context
parameter.As you may already know, this allows you to propagate key/value pairs across different API/process boundaries.
It also allows you to constrain the execution time of the driver calls and even cancel them as you see fit!
This affected the driver codebase quite deeply.
Indeed, the provided context affects mainly 2 logical parts of the driver.
The first one will probably not come as a surprise: networking.
The driver dechunks messages from or sends messages to the server.
Reads and writes can be interrupted by the context.
The second one has to do with locks.
The driver and its owned objects (connection pool, ...) are thread-safe and can be shared across sessions (which are not thread-safe, each session can execute in its own goroutine instead).
Locks are used to maintain the integrity of objects shared across sessions.
Contexts are used to wait for locks until their deadline is reached or they have been canceled.
Interruptible reads and writes
What happens when, for instance, a driver write gets canceled?
The Bolt server will hold on the related transaction until it's told not to.
Until now, the driver would just stop the write operation, mark the connection as dead (i.e. non-reusable by the connection pool) and move on.
You can imagine how this situation can degrade quickly on the server side if contexts get canceled too early. The server will needlessly accumulate transactions until it cannot anymore.
What's new in 5.5.0 is that the driver now does an extra (brutal) thing: it closes the connection's socket if the provided context gets canceled or reaches it deadline. The server will therefore be able to get rid of the transaction and use the freed resources for other workloads.
Conclusion
context.Context
offers a lot of power to you.With great power, yadda yadda yadda.
Excessive cancellation and early deadline degrade the connection pool and in turn the overall driver performance.
Use with care!
Beta Was this translation helpful? Give feedback.
All reactions