fix: allow retrying failed connection pool stream closures
AD
2d ago+162+162+012345678901234567890123456789-14-14-01234567890123456789
Summary
Fixes #1328.
PoolByteStream previously marked itself as closed before closing the underlying stream. If that operation raised an exception, subsequent close attempts were skipped, leaving the request registered in the connection pool.
This PR fixes that behaviour for both synchronous and asynchronous streams by resetting _closed when the underlying close fails, allowing a later attempt to retry.
Pool cleanup still occurs only after the underlying stream closes successfully.
Testing:
- Added regression tests for sync and async streams.
- Covered repeated failures, retries,
BaseExceptionand idempotent cleanup. - All 2,125 tests passed across Python 3.11 to 3.15.
- Achieved 100% test coverage.
- Ruff, MyPy, build and consistency checks passed.
[Successful CI run](https://github.com/AdityaSreevatsaK/httpx2/actions/runs/43093935454)
Checklist
- I understand that this PR may be closed in case there was no previous discussion. (This doesn't apply to typos!)
- I've added a test for each change that was introduced, and I tried as much as possible to make a single atomic change.
- I've reviewed the documentation requirements. No documentation changes are needed because this is an internal bug fix with no public API changes.