Skip to content

Discard connections whose validation was interrupted - #325

Open
chenty2333 wants to merge 1 commit into
djc:mainfrom
chenty2333:discard-interrupted-validation
Open

chenty2333 wants to merge 1 commit into
djc:mainfrom
chenty2333:discard-interrupted-validation

Conversation

@chenty2333

Copy link
Copy Markdown

Fixes #324.

If get() is dropped while ManageConnection::is_valid is pending (by the caller, or by the pool's own connection_timeout), the connection was returned to the pool as Present, possibly with the validation exchange half done. This marks the connection Invalid before awaiting is_valid and sets it back to Present on success, so dropping discards the connection and the pool replenishes as it does after a failed validation.

test_drop_during_is_valid models a request/response connection whose validation stalls once. It fails on main, where the next get() returns the connection with its validation request still unanswered, and passes with this change. The rest of the test suite passes on stable and 1.75; cargo fmt and cargo clippy --all-targets are clean.

If get() is dropped while is_valid is pending, the connection was returned
to the pool as Present, possibly with the validation exchange half done.
Keep it Invalid until validation succeeds so that dropping discards it.

Fixes djc#324.
chenty2333 added a commit to chenty2333/Dropwise that referenced this pull request Oct 18, 2026
@codecov

codecov Bot commented Oct 18, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 78.06%. Comparing base (6dff1ee) to head (9934aa9).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #325      +/-   ##
==========================================
+ Coverage   77.99%   78.06%   +0.06%     
==========================================
  Files           6        6              
  Lines         659      661       +2     
==========================================
+ Hits          514      516       +2     
  Misses        145      145              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@chenty2333

Copy link
Copy Markdown
Author

Additional real-client validation for this fix: bb8-bolt 0.8.0 resolves bb8 0.8.6, and its is_valid runs bolt_client::Client::reset. With bolt-client 0.11.0 and Neo4j 5.26.0, cancelling Pool::get() while that RESET is pending returns the connection to the idle pool in the original code. The next borrower can consume the leftover Success during validation and then fail with a Reset/Ready-state error.

I applied the invalid-until-validation-completes change from this PR to a separate 0.8.6 copy, without upgrading the driver or adapter. In three checkout-only rounds, all six original cancellation attempts caused a subsequent-use failure; all six patched attempts completed the subsequent write correctly. All cancellation points were reached.

The connection counters distinguish the mechanism: original code has one idle connection immediately after cancellation and replaces it only after the later error. With the patch it has zero connections immediately after cancellation, then creates a new one for the next borrower. Uncancelled reuse and an explicit is_valid -> Err control still work. A one-plan replay also reproduced the original failure.

This adds another concrete affected adapter, rather than a new report of the same bb8 issue. Reproduction, patch copy and results.

This branch was successfully deployed

1 active deployment
Coverage — 9934aa9b Deployed Oct 18, 2026 by chenty2333 via coverage #840
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Connection returned to the pool when get() is dropped during is_valid

1 participant