From 130633ba32ec953cebc2163c814c51f6c1a176e1 Mon Sep 17 00:00:00 2001 From: Aleksandr Sysoev Date: Fri, 14 Jun 2024 15:23:29 +0400 Subject: [PATCH 1/5] Refactor `start_workers` fun --- lib/poolex.ex | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/poolex.ex b/lib/poolex.ex index f326ebd..4a450fe 100644 --- a/lib/poolex.ex +++ b/lib/poolex.ex @@ -285,7 +285,7 @@ defmodule Poolex do worker_start_fun: worker_start_fun } - initial_workers_pids = start_workers(workers_count, state, monitor_id) + initial_workers_pids = start_workers(workers_count, state) state = state @@ -303,20 +303,20 @@ defmodule Poolex do {:noreply, state} end - @spec start_workers(non_neg_integer(), State.t(), Monitoring.monitor_id()) :: [pid] - defp start_workers(0, _state, _monitor_id) do + @spec start_workers(non_neg_integer(), State.t()) :: [pid] + defp start_workers(0, _state) do [] end - defp start_workers(workers_count, _state, _monitor_id) when workers_count < 0 do + defp start_workers(workers_count, _state) when workers_count < 0 do msg = "workers_count must be non negative number, received: #{inspect(workers_count)}" raise ArgumentError, msg end - defp start_workers(workers_count, state, monitor_id) do + defp start_workers(workers_count, state) do Enum.map(1..workers_count, fn _ -> {:ok, worker_pid} = start_worker(state) - Monitoring.add(monitor_id, worker_pid, :worker) + Monitoring.add(state.monitor_id, worker_pid, :worker) worker_pid end) From ce323b99cbd12cfca40e1d1a2c30c6ddba32b125 Mon Sep 17 00:00:00 2001 From: Aleksandr Sysoev Date: Wed, 19 Jun 2024 16:05:24 +0300 Subject: [PATCH 2/5] Add scale_idle_workers interface --- lib/poolex.ex | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/poolex.ex b/lib/poolex.ex index 4a450fe..02577b0 100644 --- a/lib/poolex.ex +++ b/lib/poolex.ex @@ -253,6 +253,18 @@ defmodule Poolex do GenServer.call(pool_id, :get_debug_info) end + @spec scale_idle_workers(pool_id(), non_neg_integer()) :: :ok + def scale_idle_workers(_pool_id, target_workers_count) when target_workers_count < 0 do + message = + "target_workers_count must be non negative number, received: #{inspect(target_workers_count)}" + + raise ArgumentError, message + end + + def scale_idle_workers(pool_id, target_workers_count) do + GenServer.cast(pool_id, {:scale_idle_workers, target_workers_count}) + end + @impl GenServer def init(opts) do Process.flag(:trap_exit, true) From d5ef4a95115c1b06f63847bb5ce52bfbb4d90128 Mon Sep 17 00:00:00 2001 From: Aleksandr Sysoev Date: Tue, 25 Jun 2024 16:50:27 +0300 Subject: [PATCH 3/5] Fix misstype --- lib/poolex.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/poolex.ex b/lib/poolex.ex index 02577b0..46c0d45 100644 --- a/lib/poolex.ex +++ b/lib/poolex.ex @@ -379,7 +379,7 @@ defmodule Poolex do {:reply, state, state} end - def handle_call(:get_debug_info, _form, %State{} = state) do + def handle_call(:get_debug_info, _from, %State{} = state) do debug_info = %DebugInfo{ busy_workers_count: BusyWorkers.count(state), busy_workers_impl: state.busy_workers_impl, From 8d40a37918a8cfe2eaf5f05ea0c0d8a5d2816b7d Mon Sep 17 00:00:00 2001 From: Aleksandr Sysoev Date: Tue, 25 Jun 2024 18:02:03 +0300 Subject: [PATCH 4/5] add_idle_workers!/2 --- lib/poolex.ex | 27 +++++++++++++++++++++------ test/poolex_test.exs | 34 +++++++++++++++++++++++++++++++--- 2 files changed, 52 insertions(+), 9 deletions(-) diff --git a/lib/poolex.ex b/lib/poolex.ex index 46c0d45..0e45c01 100644 --- a/lib/poolex.ex +++ b/lib/poolex.ex @@ -253,16 +253,19 @@ defmodule Poolex do GenServer.call(pool_id, :get_debug_info) end - @spec scale_idle_workers(pool_id(), non_neg_integer()) :: :ok - def scale_idle_workers(_pool_id, target_workers_count) when target_workers_count < 0 do - message = - "target_workers_count must be non negative number, received: #{inspect(target_workers_count)}" + @doc """ + Adds some idle workers to existing pool. + """ + @spec add_idle_workers!(pool_id(), pos_integer()) :: :ok | no_return() + def add_idle_workers!(_pool_id, workers_count) when workers_count < 1 do + message = "workers_count must be positive number, received: #{inspect(workers_count)}" raise ArgumentError, message end - def scale_idle_workers(pool_id, target_workers_count) do - GenServer.cast(pool_id, {:scale_idle_workers, target_workers_count}) + def add_idle_workers!(pool_id, workers_count) + when is_atom(pool_id) and is_integer(workers_count) do + GenServer.call(pool_id, {:add_idle_workers, workers_count}) end @impl GenServer @@ -399,6 +402,18 @@ defmodule Poolex do {:reply, debug_info, state} end + @impl GenServer + def handle_call({:add_idle_workers, workers_count}, _from, %State{} = state) do + new_state = + workers_count + |> start_workers(state) + |> Enum.reduce(state, fn worker, acc_state -> + IdleWorkers.add(acc_state, worker) + end) + + {:reply, :ok, new_state} + end + @impl GenServer def handle_cast({:release_busy_worker, worker}, %State{} = state) do if WaitingCallers.empty?(state) do diff --git a/test/poolex_test.exs b/test/poolex_test.exs index ee467bd..76030af 100644 --- a/test/poolex_test.exs +++ b/test/poolex_test.exs @@ -4,6 +4,8 @@ defmodule PoolexTest do doctest Poolex + alias Poolex.Private.DebugInfo + describe "debug info" do test "valid after initialization" do initial_fun = fn -> 0 end @@ -12,7 +14,7 @@ defmodule PoolexTest do debug_info = Poolex.get_debug_info(pool_name) - assert debug_info.__struct__ == Poolex.Private.DebugInfo + assert debug_info.__struct__ == DebugInfo assert debug_info.busy_workers_count == 0 assert debug_info.busy_workers_impl == Poolex.Workers.Impl.List assert debug_info.busy_workers_pids == [] @@ -51,7 +53,7 @@ defmodule PoolexTest do debug_info = Poolex.get_debug_info(pool_name) - assert debug_info.__struct__ == Poolex.Private.DebugInfo + assert debug_info.__struct__ == DebugInfo assert debug_info.busy_workers_count == 0 assert Enum.empty?(debug_info.busy_workers_pids) assert debug_info.idle_workers_count == 5 @@ -80,7 +82,7 @@ defmodule PoolexTest do debug_info = Poolex.get_debug_info(pool_name) - assert debug_info.__struct__ == Poolex.Private.DebugInfo + assert debug_info.__struct__ == DebugInfo assert debug_info.busy_workers_count == 1 assert Enum.count(debug_info.busy_workers_pids) == 1 assert debug_info.idle_workers_count == 4 @@ -582,4 +584,30 @@ defmodule PoolexTest do assert elem(message_3, 3) == pool_pid end end + + describe "add_idle_workers!/2" do + test "adds idle workers to pool" do + initial_fun = fn -> 0 end + + pool_name = start_pool(worker_module: Agent, worker_args: [initial_fun], workers_count: 5) + + assert %DebugInfo{idle_workers_count: 5} = Poolex.get_debug_info(pool_name) + assert :ok = Poolex.add_idle_workers!(pool_name, 5) + assert %DebugInfo{idle_workers_count: 10} = Poolex.get_debug_info(pool_name) + end + + test "raises error on non positive workers_count" do + initial_fun = fn -> 0 end + + pool_name = start_pool(worker_module: Agent, worker_args: [initial_fun], workers_count: 5) + + assert_raise(ArgumentError, fn -> + Poolex.add_idle_workers!(pool_name, -1) + end) + + assert_raise(ArgumentError, fn -> + Poolex.add_idle_workers!(pool_name, 0) + end) + end + end end From e4082d3a7f6af0865080ec28feb90142849f3b28 Mon Sep 17 00:00:00 2001 From: Aleksandr Sysoev Date: Wed, 17 Jul 2024 10:58:55 +0700 Subject: [PATCH 5/5] Update changelog --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f1d1dc..6cb1201 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- Added function `add_idle_workers!/2` for adding some idle workers to the initialized pool in runtime. + +### Changed + +- Refactored private `start_workers` function. It no longer accepts monitor_id as it already is in the state. + ## [0.9.0] - 2024-04-24 ### Added