# 1.6.0

## Features

### `:fiber_concurrency` plugin

While simple use cases of `httpx` being used inside a fiber scheduler (such as [async](github.com/socketry/async)) worked, a serious of issues were identified when connections were reused across fibers for multiple requests (such as when using the `:persistent` plugin). The `:fiber_concurrency` plugin fixes that, by bookkeeping which requests are being used in which fibers in order to avoid spurious wakeups and busy loops.

This plugin is loaded by default when using the `:persistent` plugin, and by extension the `faraday` adapter.

You can read more about it in https://honeyryderchuck.gitlab.io/httpx/wiki/Fiber-Concurrency

## Improvements

* proxy errors are now retriable (when using the `:retries` plugin alongside the `:proxy` plugin).
* several options improvements:
  * improve initialization by caching options names in the class, which facilitates predictable option ivar initialization, which avoids "too many shapes" performance penalty.
  * when using `HTTPX::Options#merge`, enforce usage of Hash or `HTTPX::Options` object as the argument to merge with, instead of silently ignoring when none of the former.
  * `option_` setter methods are now private.
  * all options ivars are frozen on initialize, which enforces the immutability guarantees (**note**: in case you were relying on it not being truly mutable, this may break your code. Try either passing immutable values to options, or instead use procs).
* several selector loop improvements:
  * move selectable checks a layer above to avoid calling `IO.select` with a single socket at all costs.
  * Improve connection interest calculation to reduce spurious wakeups.
  * skip early when finding closed selectables
* improve connection initialization to avoid "too many shapes" performance penalty.
* Plugins are now able to extend the functionality of both HTTP1 and HTTP2 connections, as well as resolvers.
  * see instructions in the [custom lugins wiki](https://gitlab.com/os85/httpx/-/wikis/Custom-Plugins).
* IP addresses which have expired their TTL (from the respective DNS answer) will be invalidated and force a new name resolution on operations requiring it, such as reconnections or cache lookups.
* connections are removed from errors which store it internally (for internal purposes) before returning the respective error response (so that it can be garbage collected).

## Bugfixes

* remove check for non-unique local ipv6 which was preventing Happy Eyeballs v2 from kicking in.
* recover from "network unreachable" errors triggered by using a cached IP.
* dealing with requests which are rerouted for retries in the main session response handling loop.
* `datadog` adapter: compatibility with support versions under 1.13.0 is working again.
* http2 connection: fix calculation when connection closes and there's no termination handshake
* `callback_for`: check for existence of ivar `@callbacks` first.
* native resolver: do not buffer DNS query if waiting on a previous reply (even across fibers).
* http2: do not allow deactivating connections which finished all requests but are still waiting for the ack of the PING frame (which can happen in a multi-fiber usage scenario).
* pool: fix when connection is acquired after waiting on it; return it immediately, instead of bookkeeping on `:max_connections` (when defined).
* session: fix deactivation flow, when connections get deregistered from selector and removed from the array being iterated on.
* `:proxy` plugin: fix ssl reconnection such as, on close, the IO downgrades to the respective tcp socket, so that reconnection handshake starts from scratch with the original IO.
* `:persistent` plugin: calling `HTTPX::Session#close` will close selectors from other threads (instead of just the thread it was called on).
* `:callbacks` plugin: propagate callbacks to "derived-via `.plugin`" sessions.
* `:callbacks` plugin: do not trigger the `on_response_completed` callback if there was an error (as that's what the `on_request_error` callback is for).

## Chore

*  decoupled form and multipart transcoders, moved "form or multipart" check to request body.