Repository: general-CbIC/poolex (elixir)

Issue:
Allow `:worker_module` to be the default `:pool_id` 
Hello! Thanks for maintaining Poolex. I have a small ergonomics suggestion that I think would simplify things for the majority of use-cases: make `:pool_id` optional and use `:worker_module` as its default. 

Assuming that most people have one pool per worker, this change would:

- Simplify the "getting started" story, as there's one less option that you need to know about for the basic case. 
- Make run-site usage more clear; instead of `Poolex.run(:my_pool, ...)` and then having to look up the child spec to know for sure which worker is running, it's immediately visible as `Poolex.run(MyWorker, ...)`.

Alternative considered: Require manually setting the pool ID to be the worker module. This gets the call-site benefit above, but I believe the ergonomic and documentation benefit of letting the module be the default is worth it. 

Thanks for considering!

Pull request description:
Make `pool_id` optional
Add fallback for `pool_id` to `worker_module` init option and update docs.

Closes #107 

Patch:
diff --git a/.tool-versions b/.tool-versions
index 2638d03..bb51a93 100644
--- a/.tool-versions
+++ b/.tool-versions
@@ -1,2 +1,2 @@
-erlang 27.1
-elixir 1.18.0-otp-27
+erlang 27.2
+elixir 1.18.1-otp-27
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 86ce99c..00764ac 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 ### Changed
 
 - Refactored tests with new [ExUnit parameterize feature](https://hexdocs.pm/ex_unit/1.18.0/ExUnit.Case.html#module-parameterized-tests).
+- `:pool_id` is not required init option anymore. For now it is equal to `worker_module` option value.
 
 ### Fixed
 
diff --git a/README.md b/README.md
index 0abde9f..9aa6aba 100644
--- a/README.md
+++ b/README.md
@@ -9,9 +9,12 @@
 
 Poolex is a library for managing pools of workers. Inspired by [poolboy](https://github.com/devinus/poolboy).
 
+> [!IMPORTANT]  
+> Documentation on GitHub corresponds to the current branch. For stable versions' docs see [Hexdocs](https://hexdocs.pm/poolex/).
+
 ## Table of Contents
 
-<img alt="Poolex logo" src="assets/poolex.png" width="200" height="200" style="margin-right: 10px;" align="right"/>
+<img alt="Poolex logo" src="assets/poolex.png" width="250" height="250" align="right"/>
 
 - [Poolex](#poolex)
   - [Table of Contents](#table-of-contents)
@@ -61,8 +64,7 @@ In the most typical use of Poolex, you only need to start a pool of workers as a
 
 ```elixir
 children = [
-  {Poolex, 
-    pool_id: :worker_pool,
+  {Poolex,
     worker_module: SomeWorker,
     workers_count: 5}
 ]
@@ -73,7 +75,7 @@ Supervisor.start_link(children, strategy: :one_for_one)
 Then you can execute any code on the workers with `run/3`:
 
 ```elixir
-iex> Poolex.run(:worker_pool, &(is_pid?(&1)), checkout_timeout: 1_000)
+iex> Poolex.run(SomeWorker, &(is_pid?(&1)), checkout_timeout: 1_000)
 {:ok, true}
 ```
 
diff --git a/docs/guides/example-of-use.cheatmd b/docs/guides/example-of-use.cheatmd
index 1df51ad..4dce357 100644
--- a/docs/guides/example-of-use.cheatmd
+++ b/docs/guides/example-of-use.cheatmd
@@ -38,7 +38,6 @@ defmodule PoolexExample.Application do
   def start(_type, _args) do
     children = [
       {Poolex,
-       pool_id: :worker_pool,
        worker_module: PoolexExample.Worker,
        workers_count: 5,
        max_overflow: 2}
@@ -66,7 +65,7 @@ defmodule PoolexExample.Test do
   defp async_call_square_root(i) do
     Task.async(fn ->
       Poolex.run(
-        :worker_pool,
+        PoolexExample.Worker,
         fn pid ->
           # Let's wrap the genserver call in a try-catch block. This allows us to trap any exceptions
           # that might be thrown and return the worker to Poolex in a clean manner. It also allows
diff --git a/docs/guides/getting-started.cheatmd b/docs/guides/getting-started.cheatmd
index 5a44e27..d6470fb 100644
--- a/docs/guides/getting-started.cheatmd
+++ b/docs/guides/getting-started.cheatmd
@@ -5,7 +5,7 @@
 To start a pool you can use either `start/1` or `start_link/1`.
 
 ```elixir
-Poolex.start_link(pool_id: :my_pool, worker_module: SomeWorker, workers_count: 10)
+Poolex.start_link(worker_module: SomeWorker, workers_count: 10)
 ```
 
 In general, you should place it into your Supervision tree for fault tolerance.
@@ -13,7 +13,6 @@ In general, you should place it into your Supervision tree for fault tolerance.
 ```elixir
 children = [
   {Poolex,
-  pool_id: :my_pool,
   worker_module: SomeWorker,
   workers_count: 10,
   max_overflow: 10}
@@ -22,13 +21,11 @@ children = [
 Supervisor.start_link(children, strategy: :one_for_one)
 ```
 
-The second argument should contain a set of options for starting the pool.
-
 ## Poolex configuration options
 
 | Option                 | Description                                          | Example               | Default value                     |
 |------------------------|------------------------------------------------------|-----------------------|-------------------------|
-| `pool_id`              | Identifier by which you will access the pool         | `:my_pool`            | **option is required**               |
+| `pool_id`              | Identifier by which you will access the pool         | `:my_pool`            | `worker_module` value                    |
 | `worker_module`        | Name of module that implements our worker            | `MyApp.Worker`        | **option is required**               |
 | `workers_count`        | How many workers should be running in the pool       | `5`                   | **option is required**               |
 | `max_overflow`         | How many workers can be created over the limit       | `2`                   | `0`                      |
@@ -51,7 +48,7 @@ The third argument contains run options. Currently, there is only one `checkout_
 
 ```elixir
 iex> Poolex.start_link(pool_id: :agent_pool, worker_module: Agent, worker_args: [fn -> 5 end], workers_count: 1)
-iex> Poolex.run(:agent_pool, fn pid -> Agent.get(pid, &(&1)) end)
+iex> Poolex.run(:agent_pool, fn pid -> Agent.get(pid, &(&1)) end, checkout_timeout: 5_000)
 {:ok, 5}
 ```
 
diff --git a/docs/guides/migration-from-poolboy.cheatmd b/docs/guides/migration-from-poolboy.cheatmd
index ec25efe..cf8da19 100644
--- a/docs/guides/migration-from-poolboy.cheatmd
+++ b/docs/guides/migration-from-poolboy.cheatmd
@@ -43,7 +43,7 @@ def init(_args) do
 -      max_overflow: 50
 -    )
 +    {Poolex,
-+      pool_id: :some_pool,
++      pool_id: {:local, :some_pool},
 +      worker_module: MyApp.SomeWorker,
 +      workers_count: 100,
 +      max_overflow: 50}
@@ -59,12 +59,12 @@ Use `run/3`.
 Be careful, unlike `:poolboy.transaction`, `Poolex.run` returns `{:ok, result}`.
 
 ```diff
--  :poolboy.transaction(
+-  result = :poolboy.transaction(
 -    :some_pool,
 -    fn pid -> some_function(pid) end,
 -    :timer.seconds(10)
 -  )
-+  Poolex.run(
++  {:ok, result} = Poolex.run(
 +    :some_pool,
 +    fn pid -> some_function(pid) end,
 +    checkout_timeout: :timer.seconds(10)
diff --git a/docs/guides/pool-metrics.cheatmd b/docs/guides/pool-metrics.cheatmd
index e76b52c..e605836 100644
--- a/docs/guides/pool-metrics.cheatmd
+++ b/docs/guides/pool-metrics.cheatmd
@@ -13,7 +13,6 @@ To enable pool size metrics, you need to set the pool_size_metrics parameter to
 ```elixir
 children = [
   {Poolex, 
-    pool_id: :worker_pool,
     worker_module: SomeWorker,
     workers_count: 5,
     pool_size_metrics: true}
diff --git a/examples/poolex_example/lib/poolex_example/application.ex b/examples/poolex_example/lib/poolex_example/application.ex
index 273a6c4..5dbd784 100644
--- a/examples/poolex_example/lib/poolex_example/application.ex
+++ b/examples/poolex_example/lib/poolex_example/application.ex
@@ -6,7 +6,6 @@ defmodule PoolexExample.Application do
   def start(_type, _args) do
     children = [
       {Poolex,
-       pool_id: :worker_pool,
        worker_module: PoolexExample.Worker,
        workers_count: 5,
        max_overflow: 2,
diff --git a/lib/poolex.ex b/lib/poolex.ex
index 030f1ce..27fac6f 100644
--- a/lib/poolex.ex
+++ b/lib/poolex.ex
@@ -39,7 +39,7 @@ defmodule Poolex do
   @poolex_options_table """
   | Option                 | Description                                          | Example               | Default value                     |
   |------------------------|------------------------------------------------------|-----------------------|-----------------------------------|
-  | `pool_id`              | Identifier by which you will access the pool         | `:my_pool`            | **option is required**            |
+  | `pool_id`              | Identifier by which you will access the pool         | `:my_pool`            | `worker_module` value             |
   | `worker_module`        | Name of module that implements our worker            | `MyApp.Worker`        | **option is required**            |
   | `workers_count`        | How many workers should be running in the pool       | `5`                   | **option is required**            |
   | `max_overflow`         | How many workers can be created over the limit       | `2`                   | `0`                               |
@@ -101,8 +101,7 @@ defmodule Poolex do
   """
   @spec start(list(poolex_option())) :: GenServer.on_start()
   def start(opts) do
-    pool_id = Keyword.fetch!(opts, :pool_id)
-    GenServer.start(__MODULE__, opts, name: pool_id, spawn_opt: @spawn_opts)
+    GenServer.start(__MODULE__, opts, name: get_pool_id(opts), spawn_opt: @spawn_opts)
   end
 
   @doc """
@@ -125,8 +124,7 @@ defmodule Poolex do
   """
   @spec start_link(list(poolex_option())) :: GenServer.on_start()
   def start_link(opts) do
-    pool_id = Keyword.fetch!(opts, :pool_id)
-    GenServer.start_link(__MODULE__, opts, name: pool_id, spawn_opt: @spawn_opts)
+    GenServer.start_link(__MODULE__, opts, name: get_pool_id(opts), spawn_opt: @spawn_opts)
   end
 
   @doc """
@@ -139,17 +137,16 @@ defmodule Poolex do
   ## Examples
 
       children = [
-        Poolex.child_spec(pool_id: :worker_pool_1, worker_module: SomeWorker, workers_count: 5),
+        Poolex.child_spec(worker_module: SomeWorker, workers_count: 5),
         # or in another way
-        {Poolex, pool_id: :worker_pool_2, worker_module: SomeOtherWorker, workers_count: 5}
+        {Poolex, worker_module: SomeOtherWorker, workers_count: 5}
       ]
 
       Supervisor.start_link(children, strategy: :one_for_one)
   """
   @spec child_spec(list(poolex_option())) :: Supervisor.child_spec()
   def child_spec(opts) do
-    pool_id = Keyword.fetch!(opts, :pool_id)
-    %{id: pool_id, start: {Poolex, :start_link, [opts]}}
+    %{id: get_pool_id(opts), start: {Poolex, :start_link, [opts]}}
   end
 
   @doc """
@@ -275,7 +272,7 @@ defmodule Poolex do
   def init(opts) do
     Process.flag(:trap_exit, true)
 
-    pool_id = Keyword.fetch!(opts, :pool_id)
+    pool_id = get_pool_id(opts)
     worker_module = Keyword.fetch!(opts, :worker_module)
     workers_count = Keyword.fetch!(opts, :workers_count)
 
@@ -312,6 +309,17 @@ defmodule Poolex do
     {:ok, state, {:continue, opts}}
   end
 
+  @doc """
+  Returns pool identifier from initialization options.
+  """
+  @spec get_pool_id(list(poolex_option())) :: pool_id()
+  def get_pool_id(options) do
+    case Keyword.get(options, :pool_id) do
+      nil -> Keyword.fetch!(options, :worker_module)
+      pool_id -> pool_id
+    end
+  end
+
   @impl GenServer
   def handle_continue(opts, state) do
     Metrics.start_poller(opts)
diff --git a/lib/poolex/private/metrics.ex b/lib/poolex/private/metrics.ex
index ecaf656..0db840b 100644
--- a/lib/poolex/private/metrics.ex
+++ b/lib/poolex/private/metrics.ex
@@ -30,7 +30,7 @@ defmodule Poolex.Private.Metrics do
   """
   @spec start_poller(list(Poolex.poolex_option())) :: GenServer.on_start()
   def start_poller(opts) do
-    pool_id = Keyword.fetch!(opts, :pool_id)
+    pool_id = Poolex.get_pool_id(opts)
     measurements = collect_measurements(opts)
 
     if measurements == [] do
@@ -46,7 +46,7 @@ defmodule Poolex.Private.Metrics do
 
   @spec collect_measurements(list(Poolex.poolex_option())) :: list()
   defp collect_measurements(opts) do
-    pool_id = Keyword.fetch!(opts, :pool_id)
+    pool_id = Poolex.get_pool_id(opts)
 
     if Keyword.get(opts, :pool_size_metrics, false) do
       [
diff --git a/mix.exs b/mix.exs
index 3c90068..fa2705b 100644
--- a/mix.exs
+++ b/mix.exs
@@ -45,12 +45,14 @@ defmodule Poolex.MixProject do
 
   defp package do
     [
+      files: ~w(lib mix.exs LICENSE),
       licenses: ["MIT"],
       links: %{
         "Changelog" => "https://github.com/general-CbIC/poolex/blob/develop/CHANGELOG.md",
         "GitHub" => "https://github.com/general-CbIC/poolex",
         "Sponsor" => "https://github.com/sponsors/general-CbIC"
-      }
+      },
+      maintainers: ["Aleksandr Sysoev"]
     ]
   end
 


Test patch:
diff --git a/test/poolex_test.exs b/test/poolex_test.exs
index 7b5e0e1..f643a76 100644
--- a/test/poolex_test.exs
+++ b/test/poolex_test.exs
@@ -1,6 +1,7 @@
 defmodule PoolexTest do
   use ExUnit.Case,
     parameterize: [
+      %{pool_options: [worker_module: SomeWorker, workers_count: 5]},
       %{pool_options: [pool_id: SomeWorker, worker_module: SomeWorker, workers_count: 5]},
       %{pool_options: [pool_id: {:global, SomeWorker}, worker_module: SomeWorker, workers_count: 5]},
       %{
@@ -541,13 +542,19 @@ defmodule PoolexTest do
 
   describe "child_spec" do
     test "child_spec/1", %{pool_options: pool_options} do
-      id = Keyword.fetch!(pool_options, :pool_id)
+      id = Poolex.get_pool_id(pool_options)
 
       assert Poolex.child_spec(pool_options) ==
                %{
                  id: id,
                  start: {Poolex, :start_link, [pool_options]}
                }
+
+      assert Poolex.child_spec(worker_module: SomeWorker, workers_count: 5) ==
+               %{
+                 id: SomeWorker,
+                 start: {Poolex, :start_link, [[worker_module: SomeWorker, workers_count: 5]]}
+               }
     end
   end
 
diff --git a/test/support/pool_helpers.ex b/test/support/pool_helpers.ex
index 643185c..4faf2b5 100644
--- a/test/support/pool_helpers.ex
+++ b/test/support/pool_helpers.ex
@@ -7,7 +7,7 @@ defmodule PoolHelpers do
   def start_pool(options) do
     {:ok, _pid} = ExUnit.Callbacks.start_supervised({Poolex, options})
 
-    Keyword.fetch!(options, :pool_id)
+    Poolex.get_pool_id(options)
   end
 
   @spec launch_long_task(Poolex.pool_id(), timeout()) :: :ok