neo4j / neo4j-go-driver

Neo4j Bolt Driver for Go
Apache License 2.0
485 stars 68 forks source link

Make sure transactions never returns connections to the pool twice #491

Closed fbiville closed 1 year ago

fbiville commented 1 year ago

Before this fix, users could run into situation when a transaction would execute their onClosed callback more than once, meaning the referenced connection could be returned to the idle list of its server's connection several times (i.e. the connection ref could be duplicated and borrowed by more than 1 transaction at a time, which breaks the fundamental invariant of connections).

This could occur when a transaction was committed or rolled back* and then, users would run a query with the same transaction again. This is obviously a misuse of the transaction API but the driver could fail in a more graceful and more understandable manner.

When that subsequent run executed, a transaction ID mismatch error would then be returned (since the connection was reset upon the return to pool after commit/rollback, thus forgetting about its former transaction ID). The tx ID mismatch error would then lead to onClosed being called a second time, and the same connection would end up listed a second time in its server's tracked idle connection list.

One fix could be to make the pool return idempotent. However, we felt that the better fix is to respect the invariant according to which a connection is never returned more than once, thus making the pool return idempotency irrelevant in practice.

*rollback also happens when closing the transaction or closing the enclosing session and the transaction is the currently active workload in that session

Fixes #487