diff --git a/README.md b/README.md index d89e486..30bab53 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,7 @@ iex(1)> GenMagic.Helpers.perform_once(Path.join(File.cwd!(), "Makefile")) ### Supervised Requests -The Server should be run under a pool which provides concurrency *and* resiliency. +The Server should be run under a supervisor which provides resiliency. Here we run it under a supervisor: @@ -96,6 +96,17 @@ iex(2)> GenMagic.Server.perform(:gen_magic, Path.expand("~/.bash_history")) Note that in this case we have opted to use a named process. +### Pool + +For concurrency *and* resiliency, you may start the `GenMagic.Pool`. By default, it will start a `GenMagic.Server` +worker per online scheduler: + +```elixir +iex(1)> GenMagic.Pool.start_link([]) +iex(2)> GenMagic.Pool.perform(GenMagic.Pool, Path.expand("~/.bash_history")) +{:ok, [mime_type: "text/plain", encoding: "us-ascii", content: "ASCII text"]} +``` + ### Check Uploaded Files If you use Phoenix, you can inspect the file from your controller: diff --git a/lib/gen_magic/pool.ex b/lib/gen_magic/pool.ex new file mode 100644 index 0000000..fac4cd6 --- /dev/null +++ b/lib/gen_magic/pool.ex @@ -0,0 +1,55 @@ +defmodule GenMagic.Pool do + @behaviour NimblePool + + def start_link(options, pool_size \\ nil) do + pool_size = pool_size || System.schedulers_online() + NimblePool.start_link(worker: {__MODULE__, options}, pool_size: pool_size) + end + + def perform(pool, path, opts \\ []) do + pool_timeout = Keyword.get(opts, :pool_timeout, 5000) + timeout = Keyword.get(opts, :timeout, 5000) + + NimblePool.checkout!(pool, :checkout, fn _from, server -> + {GenMagic.perform(server, path, timeout), server} + end, pool_timeout) + end + + @impl NimblePool + def init_pool(options) do + {name, options} = case Keyword.pop(options, :name) do + {name, options} when is_atom(name) -> {name, options} + {nil, options} -> {__MODULE__, options} + {_, options} -> {nil, options} + end + if name, do: Process.register(self(), atom) + {:ok, options} + end + + @impl NimblePool + def init_worker(options) do + {:ok, server} = GenMagic.Server.start_link(options) + {:ok, server, nil} + end + + @impl NimblePool + def handle_checkout(:checkout, _, server, state) do + {:ok, server, server, pool_state} + end + + @impl NimblePool + def handle_checkin(server, _from, _old_server, state) do + {:ok, server, state} + end + + @impl NimblePool + def terminate_worker(_reason, _worker, state) do + {:ok, state} + end + + @impl NimblePool + def terminate(_reason, _conn, state) do + {:ok, state} + end + +end diff --git a/mix.exs b/mix.exs index 11ebdaf..83c1597 100644 --- a/mix.exs +++ b/mix.exs @@ -44,7 +44,8 @@ defmodule GenMagic.MixProject do {:credo, "~> 1.4.0", only: [:dev, :test], runtime: false}, {:dialyxir, "~> 1.0.0-rc.6", only: :dev, runtime: false}, {:ex_doc, ">= 0.0.0", only: :dev, runtime: false}, - {:elixir_make, "~> 0.4", runtime: false} + {:elixir_make, "~> 0.4", runtime: false}, + {:nimble_pool, "~> 0.1"} ] end diff --git a/mix.lock b/mix.lock index 3ebe0c6..3317183 100644 --- a/mix.lock +++ b/mix.lock @@ -12,4 +12,5 @@ "makeup": {:hex, :makeup, "1.0.1", "82f332e461dc6c79dbd82fbe2a9c10d48ed07146f0a478286e590c83c52010b5", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "49736fe5b66a08d8575bf5321d716bac5da20c8e6b97714fec2bcd6febcfa1f8"}, "makeup_elixir": {:hex, :makeup_elixir, "0.14.0", "cf8b7c66ad1cff4c14679698d532f0b5d45a3968ffbcbfd590339cb57742f1ae", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "d4b316c7222a85bbaa2fd7c6e90e37e953257ad196dc229505137c5e505e9eff"}, "nimble_parsec": {:hex, :nimble_parsec, "0.5.3", "def21c10a9ed70ce22754fdeea0810dafd53c2db3219a0cd54cf5526377af1c6", [:mix], [], "hexpm", "589b5af56f4afca65217a1f3eb3fee7e79b09c40c742fddc1c312b3ac0b3399f"}, + "nimble_pool": {:hex, :nimble_pool, "0.1.0", "ffa9d5be27eee2b00b0c634eb649aa27f97b39186fec3c493716c2a33e784ec6", [:mix], [], "hexpm", "343a1eaa620ddcf3430a83f39f2af499fe2370390d4f785cd475b4df5acaf3f9"}, } diff --git a/test/gen_magic/pool_test.exs b/test/gen_magic/pool_test.exs new file mode 100644 index 0000000..f336e12 --- /dev/null +++ b/test/gen_magic/pool_test.exs @@ -0,0 +1,9 @@ +defmodule GenMagic.PoollTest do + use GenMagic.MagicCase + + test "pool" do + {:ok, _} = GenMagic.Pool.start_link([name: TestPool]) + assert {:ok, _} = GenMagic.Pool.perform(TestPool, absolute_path("Makefile")) + end + +end