Skip to content

Support Finch tagged pools via :finch option tuple#539

Open
meox wants to merge 2 commits into
wojtekmach:mainfrom
meox:pool_tag
Open

Support Finch tagged pools via :finch option tuple#539
meox wants to merge 2 commits into
wojtekmach:mainfrom
meox:pool_tag

Conversation

@meox
Copy link
Copy Markdown
Contributor

@meox meox commented Apr 15, 2026

Summary

  • Extend the :finch option to accept a {name, opts} tuple, allowing users to pass :pool_tag and :unix_socket directly to Finch.build/5.
  • Refactor Finch.build call to use the 5th opts argument, replacing the previous Map.replace!/2 mutation pattern.

Motivation

Finch supports configuring multiple connection pools for the same endpoint, differentiated by a tag via Finch.Pool.new/2. This is useful for separating traffic by purpose (e.g., bulk ingestion vs. real-time queries) with different pool sizes and concurrency settings. Previously, there was no way to leverage this feature through Req without resorting to the low-level :finch_request callback.

As suggested by @jswanner, since :pool_tag and :unix_socket are only relevant when using your own Finch name, they are nested under the :finch option rather than exposed as top-level Req options. This also means future Finch.build/5 options won't require Req changes to support.

Usage

# Configure Finch with tagged pools
children = [
  {Finch,
   name: MyFinch,
   pools: %{
     Finch.Pool.new("https://api.example.com") => [size: 50, count: 4],
     Finch.Pool.new("https://api.example.com", tag: :bulk) => [size: 100, count: 1]
   }}
]

# Route a request to the :bulk pool
Req.get!("https://api.example.com/data", finch: {MyFinch, pool_tag: :bulk})

# Connect via UNIX socket
Req.get!("http:///v1.41/_ping", finch: {MyFinch, unix_socket: "/var/run/docker.sock"})

# Plain name still works as before
Req.get!("https://api.example.com/data", finch: MyFinch)

Changes

File Change
lib/req/finch.ex Add finch_build_opts/1 to extract opts from {name, opts} tuple; update finch_name/1 to handle tuple form
lib/req/steps.ex Update run_finch/1 docs to document the tuple API
lib/req.ex Update Req.new/1 docs for the :finch option
test/req/finch_test.exs Tests using finch: {Req.Finch, pool_tag: :bulk}

Backward Compatibility

Fully backward compatible. The :finch option continues to accept a plain atom name. The :unix_socket top-level option still works when not using the tuple form. When :pool_tag is not specified, Finch.build/5 defaults it to :default.

@meox
Copy link
Copy Markdown
Contributor Author

meox commented Apr 20, 2026

are the tests flacky?

@jswanner
Copy link
Copy Markdown
Contributor

jswanner commented Apr 29, 2026

Since :unix_socket and :pool_tag are only options when using one's own Finch name, I wonder if it makes more sense to combine those option under the :finch option. As in:

Req.get!("https://api.example.com/data", finch: MyFinch)
Req.get!("https://api.example.com/data", finch: {MyFinch, pool_tag: :bulk})
Req.get!("https://api.example.com/data", finch: {MyFinch, unix_socket: my_socket})

Then if Finch were to ever add new options to Finch.build/5 then Req wouldn't need to change to support them (other than perhaps to document them). Granted, moving the :unix_socket option would be a breaking change for Req.

@meox meox changed the title Add :pool_tag option to support Finch tagged pools Support Finch tagged pools via :finch option tuple May 15, 2026
@meox
Copy link
Copy Markdown
Contributor Author

meox commented May 15, 2026

PR updated with the last suggestions

@wojtekmach
Copy link
Copy Markdown
Owner

@jswanner I think finch: {name, opts} is an elegant solution, thanks for mentioning this. I'll see if we can avoid breakage though.

@jswanner
Copy link
Copy Markdown
Contributor

I'm sorry, I was wrong before:

Since :unix_socket and :pool_tag are only options when using one's own Finch name

The above is only true for :pool_tag, :unix_socket is a valid option even when a Finch name is not provided. So, I'm not sure it makes sense to allow the unix socket value to appear under two options, certainly not elegant.

What are your thoughts, @wojtekmach?

@wojtekmach
Copy link
Copy Markdown
Owner

As an aside, one of the goals was to support multiple adapters and I still want to pursue it but Finch of course remains the default. That said, :unix_socket option is reasonable for other adapters but :pool_tag is Finch specific.

So let’s keep :unix_socket as is, but suport finch: {name, pool_tag: tag}.

There are some other Finch specific options, like :pool_max_idle_timeout or something like that, that I intend to move under finch: {name, options}.

@meox
Copy link
Copy Markdown
Contributor Author

meox commented May 22, 2026

do we need to add other options? or do u prefer to merge/close this one and open another one?

@wojtekmach
Copy link
Copy Markdown
Owner

I'd prefer to merge just finch: {name, pool_tag: tag} support for now, i.e. please remove passing :unix_domain_socket in pool options.

Gian Lorenzo Meocci added 2 commits May 24, 2026 09:33
…_socket

Align with the new Finch API where pool_tag and unix_socket are build
options passed to Finch.build/5. Instead of exposing :pool_tag as a
top-level Req option, nest it under the :finch tuple:

    Req.get!(url, finch: {MyFinch, pool_tag: :bulk})
    Req.get!(url, finch: {MyFinch, unix_socket: "/tmp/sock"})
@meox
Copy link
Copy Markdown
Contributor Author

meox commented May 24, 2026

I'd prefer to merge just finch: {name, pool_tag: tag} support for now, i.e. please remove passing :unix_domain_socket in pool options.

done!

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.

3 participants