From c078af3425f76490dd4b4f0d1f42c8f1614139ce Mon Sep 17 00:00:00 2001 From: Yana Lebedeva Date: Thu, 8 Jul 2021 18:58:45 -0400 Subject: [PATCH 1/2] ING-424 extend memcachir to allow multiple herds --- lib/memcachir.ex | 215 +++++++++------------------------------- lib/memcachir/herd.ex | 56 ----------- lib/memcachir_plugin.ex | 203 +++++++++++++++++++++++++++++++++++++ mix.lock | 36 +++---- 4 files changed, 269 insertions(+), 241 deletions(-) delete mode 100644 lib/memcachir/herd.ex create mode 100644 lib/memcachir_plugin.ex diff --git a/lib/memcachir.ex b/lib/memcachir.ex index dc2afd2..330f55c 100644 --- a/lib/memcachir.ex +++ b/lib/memcachir.ex @@ -1,180 +1,61 @@ -defmodule Memcachir do +defmodule Memcachir.Cluster do @moduledoc """ - Module with a friendly API for memcached servers. - - It provides connection pooling, and cluster support. - - ## Example - - {:ok} = Memcachir.set("hello", "world") - {:ok, "world"} = Memcachir.get("hello") - - """ - use Application - - alias Memcachir.{ - Cluster, - Pool, - Supervisor - } - - def start(_type, _args) do - opts = Application.get_all_env(:memcachir) - Supervisor.start_link(opts) - end - - @doc """ - Gets the value associated with the key. Returns `{:error, "Key not found"}` - if the given key doesn't exist. - """ - def get(key, opts \\ []) do - case key_to_node(key) do - {:ok, node} -> execute(&Memcache.get/3, node, [key, opts]) - {:error, reason} -> {:error, "unable to get: #{reason}"} - end - end - - @doc """ - Accepts a list of mcached keys, and returns either `{:ok, %{key => val}}` for each - found key or `{:error, any}` - """ - def mget(keys, opts \\ []) do - case group_by_node(keys) do - {:ok, grouped_keys} -> exec_parallel(&Memcache.multi_get/3, grouped_keys, [opts]) - {:error, reason} -> {:error, "unable to get: #{reason}"} - end - end - - @doc """ - Accepts a list of `{key, val}` pairs and returns the store results for each - node touched - """ - def mset(commands, opts \\ []) do - case group_by_node(commands, &elem(&1, 0)) do - {:ok, grouped_keys} -> exec_parallel(&Memcache.multi_set/3, grouped_keys, [opts], &Enum.concat/2) - {:error, reason} -> {:error, "unable to set: #{reason}"} - end - end - - @doc """ - Multi-set with cas option - """ - def mset_cas(commands, opts \\ []) do - case group_by_node(commands, &elem(&1, 0)) do - {:ok, grouped_keys} -> exec_parallel(&Memcache.multi_set_cas/3, grouped_keys, [opts], &Enum.concat/2) - {:error, reason} -> {:error, "unable to set: #{reason}"} - end - end + Manages cluster state with a regular healthcheck to the configured service discovery + mechanism. Configure it with: + ``` + config :memcachir, :memcachir_cluster, discovery: MyServiceDiscovery + ``` + Additionally the health check can be configured with + ``` + config :memcachir, :health_check, 10_000 + ``` + """ + use Herd.Cluster, otp_app: :memcachir, + pool: Memcachir.Pool, + discovery: Memcachir.ServiceDiscovery, + health_check: Application.get_env(:memcachir, :health_check, 60_000) +end - @doc """ - increments the key by value +defmodule Memcachir.Pool do + @moduledoc """ + Dynamic supervisor for connection pooling. If you want to modify the poolboy params, + configure it with: + ``` + config :memcachir, Memcachir.Pool, poolboy: :params + ``` + Additionally, params that will be sent to the memcachex workers are all found at the top + level of `:memcachir` config """ - def incr(key, value \\ 1, opts \\ []) do - case key_to_node(key) do - {:ok, node} -> execute(&Memcache.incr/3, node, [key, [{:by, value} | opts]]) - {:error, reason} -> {:error, "unable to inc: #{reason}"} - end - end + use Herd.Pool, otp_app: :memcachir - @doc """ - Sets the key to value. - Valid option are: - ttl: The time in seconds that the value will be stored. - """ - def set(key, value, opts \\ []) do - case key_to_node(key) do - {:ok, node} -> execute(&Memcache.set/4, node, [key, value, opts]) - {:error, reason} -> {:error, "unable to set: #{reason}"} - end + def worker_config({host, port}) do + memcachir_config() + |> Keyword.put(:hostname, host) + |> Keyword.put(:port, port) end - @doc """ - Removes the item with the specified key. Returns `{:ok, :deleted}` - """ - def delete(key) do - case key_to_node(key) do - {:ok, node} -> execute(&Memcache.delete/2, node, [key]) - {:error, reason} -> {:error, "unable to delete: #{reason}"} - end + def pool_config(pool) do + Keyword.put_new(pool, :worker_module, Memcache) end - @doc """ - Removes all the items from the server. Returns `{:ok}`. - """ - def flush(opts \\ []) do - execute(&Memcache.flush/2, list_nodes(), [opts]) - end + defp memcachir_config, do: Application.get_all_env(:memcachir) +end - @doc """ - List all currently registered node names, like `[:"localhost:11211"]`. +defmodule Memcachir.Supervisor do + @moduledoc """ + Supervises the memcachir cluster, pool and registry (which is used internally) """ - def list_nodes() do - Cluster.servers() - |> Enum.map(&Pool.poolname(&1)) - end - - defp execute(_fun, [], _args) do - {:error, "unable to flush: no_nodes"} - end - defp execute(fun, [node | nodes], args) do - if length(nodes) > 0 do - execute(fun, nodes, args) - end - - execute(fun, node, args) - end - defp execute(fun, node, args) do - try do - :poolboy.transaction(node, &apply(fun, [&1 | args])) - catch - :exit, _ -> {:error, "Node not available"} - end - end + use Herd.Supervisor, otp_app: :memcachir, + pool: Memcachir.Pool, + cluster: Memcachir.Cluster +end - @doc """ - Accepts a memcache operation closure, a grouped map of %{node => args} and executes - the operations in parallel for all given nodes. The result is of form {:ok, enumerable} - where enumerable is the merged result of all operations. - - Additionally, you can pass `args` to supply memcache ops to each of the executions - and `merge_fun` (a 2-arity func) which configures how the result is merged into the final result set. - For instance, `mget/2` returns a map of key, val pairs in its result, and utilizes `Map.merge/2`. +defmodule Memcachir do + @moduledoc """ + TODO """ - def exec_parallel(fun, grouped, args \\ [], merge_fun \\ &Map.merge/2) do - grouped - |> Enum.map(fn {node, val} -> Task.async(fn -> execute(fun, node, [val | args]) end) end) - |> Enum.map(&Task.await/1) - |> Enum.reduce({%{}, []}, fn - {:ok, result}, {acc, errors} -> {merge_fun.(acc, result), errors} - error, {acc, errors} -> {acc, [error | errors]} - end) - |> case do - {map, [error | _]} when map_size(map) == 0 -> error - {result, _} -> {:ok, result} - end - end - - defp group_by_node(commands, get_key \\ fn k -> k end) do - key_to_command = Enum.into(commands, %{}, fn c -> {get_key.(c), c} end) - - commands - |> Enum.map(get_key) - |> Cluster.get_nodes() - |> case do - {:ok, keys_to_nodes} -> - key_fn = fn {_, n} -> Pool.poolname(n) end - value_fn = fn {k, _} -> key_to_command[k] end - nodes_to_keys = Enum.group_by(keys_to_nodes, key_fn, value_fn) - - {:ok, nodes_to_keys} - {:error, error} -> {:error, error} - end - end - - defp key_to_node(key) do - case Cluster.get_node(key) do - {:error, reason} -> {:error, reason} - {:ok, node} -> {:ok, Pool.poolname(node)} - end - end + use Memcachir.Plugin, otp_app: :memcachir, + pool: Memcachir.Pool, + cluster: Memcachir.Cluster, + supervisor: Memcachir.Supervisor end diff --git a/lib/memcachir/herd.ex b/lib/memcachir/herd.ex deleted file mode 100644 index 6cf4c7c..0000000 --- a/lib/memcachir/herd.ex +++ /dev/null @@ -1,56 +0,0 @@ -defmodule Memcachir.Cluster do - @moduledoc """ - Manages cluster state with a regular healthcheck to the configured service discovery - mechanism. Configure it with: - - ``` - config :memcachir, :memcachir_cluster, discovery: MyServiceDiscovery - ``` - - Additionally the health check can be configured with - - ``` - config :memcachir, :health_check, 10_000 - ``` - """ - use Herd.Cluster, otp_app: :memcachir, - pool: Memcachir.Pool, - discovery: Memcachir.ServiceDiscovery, - health_check: Application.get_env(:memcachir, :health_check, 60_000) -end - -defmodule Memcachir.Pool do - @moduledoc """ - Dynamic supervisor for connection pooling. If you want to modify the poolboy params, - configure it with: - - ``` - config :memcachir, Memcachir.Pool, poolboy: :params - ``` - - Additionally, params that will be sent to the memcachex workers are all found at the top - level of `:memcachir` config - """ - use Herd.Pool, otp_app: :memcachir - - def worker_config({host, port}) do - memcachir_config() - |> Keyword.put(:hostname, host) - |> Keyword.put(:port, port) - end - - def pool_config(pool) do - Keyword.put_new(pool, :worker_module, Memcache) - end - - defp memcachir_config, do: Application.get_all_env(:memcachir) -end - -defmodule Memcachir.Supervisor do - @moduledoc """ - Supervises the memcachir cluster, pool and registry (which is used internally) - """ - use Herd.Supervisor, otp_app: :memcachir, - pool: Memcachir.Pool, - cluster: Memcachir.Cluster -end diff --git a/lib/memcachir_plugin.ex b/lib/memcachir_plugin.ex new file mode 100644 index 0000000..cd02864 --- /dev/null +++ b/lib/memcachir_plugin.ex @@ -0,0 +1,203 @@ +defmodule Memcachir.Plugin do + @moduledoc """ + TODO + """ + + defmacro __using__(opts) do + otp_app = Keyword.get(opts, :otp_app) + pool = Keyword.get(opts, :pool) + cluster = Keyword.get(opts, :cluster) + supervisor = Keyword.get(opts, :supervisor) + + quote do + use Application + import Memcachir.Plugin + + @otp_app unquote(otp_app) + @pool unquote(pool) + @cluster unquote(cluster) + @supervisor unquote(supervisor) + + def start(_, _) do + opts = Application.get_all_env(@otp_app) + @supervisor.start_link(opts) + end + + def get(key, opts \\ []), do: get(@cluster, @pool, key, opts) + + def mget(keys, opts \\ []), do: mget(@cluster, @pool, keys, opts) + + def mset(commands, opts \\ []), do: mset(@cluster, @pool, commands, opts) + + def mset_cas(commands, opts \\ []), do: mset_cas(@cluster, @pool, commands, opts) + + def incr(key, value \\ 1, opts \\ []), do: incr(@cluster, @pool, key, value, opts) + + def set(key, value, opts \\ []), do: set(@cluster, @pool, key, value, opts) + + def delete(key), do: delete(@cluster, @pool, key) + + def list_nodes(), do: list_nodes(@cluster, @pool) + + def flush(opts \\ []), do: flush(@cluster, @pool, opts) + + def key_to_node(key), do: key_to_node(@cluster, @pool, key) + + def group_by_node(commands, get_key \\ fn k -> k end), do: group_by_node(@cluster, @pool, commands, get_key) + end + end + + @doc """ + Gets the value associated with the key. Returns `{:error, "Key not found"}` + if the given key doesn't exist. + """ + def get(cluster_mod, pool_mod, key, opts) do + case key_to_node(cluster_mod, pool_mod, key) do + {:ok, node} -> execute(&Memcache.get/3, node, [key, opts]) + {:error, reason} -> {:error, "unable to get: #{reason}"} + end + end + + @doc """ + Accepts a list of mcached keys, and returns either `{:ok, %{key => val}}` for each + found key or `{:error, any}` + """ + def mget(cluster_mod, pool_mod, keys, opts) do + case group_by_node(cluster_mod, pool_mod, keys) do + {:ok, grouped_keys} -> exec_parallel(&Memcache.multi_get/3, grouped_keys, [opts]) + {:error, reason} -> {:error, "unable to get: #{reason}"} + end + end + + @doc """ + Accepts a list of `{key, val}` pairs and returns the store results for each + node touched + """ + def mset(cluster_mod, pool_mod, commands, opts) do + case group_by_node(cluster_mod, pool_mod, commands, &elem(&1, 0)) do + {:ok, grouped_keys} -> exec_parallel(&Memcache.multi_set/3, grouped_keys, [opts], &Enum.concat/2) + {:error, reason} -> {:error, "unable to set: #{reason}"} + end + end + + @doc """ + Multi-set with cas option + """ + def mset_cas(cluster_mod, pool_mod, commands, opts) do + case group_by_node(cluster_mod, pool_mod, commands, &elem(&1, 0)) do + {:ok, grouped_keys} -> exec_parallel(&Memcache.multi_set_cas/3, grouped_keys, [opts], &Enum.concat/2) + {:error, reason} -> {:error, "unable to set: #{reason}"} + end + end + + @doc """ + increments the key by value + """ + def incr(cluster_mod, pool_mod, key, value, opts) do + case key_to_node(cluster_mod, pool_mod, key) do + {:ok, node} -> execute(&Memcache.incr/3, node, [key, [{:by, value} | opts]]) + {:error, reason} -> {:error, "unable to inc: #{reason}"} + end + end + + @doc """ + Sets the key to value. + Valid option are: + ttl: The time in seconds that the value will be stored. + """ + def set(cluster_mod, pool_mod, key, value, opts) do + case key_to_node(cluster_mod, pool_mod, key) do + {:ok, node} -> execute(&Memcache.set/4, node, [key, value, opts]) + {:error, reason} -> {:error, "unable to set: #{reason}"} + end + end + + @doc """ + Removes the item with the specified key. Returns `{:ok, :deleted}` + """ + def delete(cluster_mod, pool_mod, key) do + case key_to_node(cluster_mod, pool_mod, key) do + {:ok, node} -> execute(&Memcache.delete/2, node, [key]) + {:error, reason} -> {:error, "unable to delete: #{reason}"} + end + end + + @doc """ + Removes all the items from the server. Returns `{:ok}`. + """ + def flush(cluster_mod, pool_mod, opts \\ []) do + execute(&Memcache.flush/2, list_nodes(cluster_mod, pool_mod), [opts]) + end + + @doc """ + List all currently registered node names, like `[:"localhost:11211"]`. + """ + def list_nodes(cluster_mod, pool_mod) do + Enum.map(cluster_mod.servers(), &pool_mod.poolname(&1)) + end + + defp execute(_fun, [], _args) do + {:error, "unable to flush: no_nodes"} + end + defp execute(fun, [node | nodes], args) do + if length(nodes) > 0 do + execute(fun, nodes, args) + end + + execute(fun, node, args) + end + defp execute(fun, node, args) do + try do + :poolboy.transaction(node, &apply(fun, [&1 | args])) + catch + :exit, _ -> {:error, "Node not available"} + end + end + + @doc """ + Accepts a memcache operation closure, a grouped map of %{node => args} and executes + the operations in parallel for all given nodes. The result is of form {:ok, enumerable} + where enumerable is the merged result of all operations. + + Additionally, you can pass `args` to supply memcache ops to each of the executions + and `merge_fun` (a 2-arity func) which configures how the result is merged into the final result set. + For instance, `mget/2` returns a map of key, val pairs in its result, and utilizes `Map.merge/2`. + """ + def exec_parallel(fun, grouped, args \\ [], merge_fun \\ &Map.merge/2) do + grouped + |> Enum.map(fn {node, val} -> Task.async(fn -> execute(fun, node, [val | args]) end) end) + |> Enum.map(&Task.await/1) + |> Enum.reduce({%{}, []}, fn + {:ok, result}, {acc, errors} -> {merge_fun.(acc, result), errors} + error, {acc, errors} -> {acc, [error | errors]} + end) + |> case do + {map, [error | _]} when map_size(map) == 0 -> error + {result, _} -> {:ok, result} + end + end + + def group_by_node(cluster_mod, pool_mod, commands, get_key \\ fn k -> k end) do + key_to_command = Enum.into(commands, %{}, fn c -> {get_key.(c), c} end) + + commands + |> Enum.map(get_key) + |> cluster_mod.get_nodes() + |> case do + {:ok, keys_to_nodes} -> + key_fn = fn {_, n} -> pool_mod.poolname(n) end + value_fn = fn {k, _} -> key_to_command[k] end + nodes_to_keys = Enum.group_by(keys_to_nodes, key_fn, value_fn) + + {:ok, nodes_to_keys} + {:error, error} -> {:error, error} + end + end + + def key_to_node(cluster_mod, pool_mod, key) do + case cluster_mod.get_node(key) do + {:error, reason} -> {:error, reason} + {:ok, node} -> {:ok, pool_mod.poolname(node)} + end + end +end diff --git a/mix.lock b/mix.lock index c7b5158..8a50ca7 100644 --- a/mix.lock +++ b/mix.lock @@ -1,20 +1,20 @@ %{ - "benchfella": {:hex, :benchfella, "0.3.5", "b2122c234117b3f91ed7b43b6e915e19e1ab216971154acd0a80ce0e9b8c05f5", [:mix], [], "hexpm"}, - "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm"}, - "connection": {:hex, :connection, "1.0.4", "a1cae72211f0eef17705aaededacac3eb30e6625b04a6117c1b2db6ace7d5976", [:mix], [], "hexpm"}, - "credo": {:hex, :credo, "0.10.2", "03ad3a1eff79a16664ed42fc2975b5e5d0ce243d69318060c626c34720a49512", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"}, - "dialyxir": {:hex, :dialyxir, "0.5.1", "b331b091720fd93e878137add264bac4f644e1ddae07a70bf7062c7862c4b952", [:mix], [], "hexpm"}, - "earmark": {:hex, :earmark, "1.3.2", "b840562ea3d67795ffbb5bd88940b1bed0ed9fa32834915125ea7d02e35888a5", [:mix], [], "hexpm"}, - "elasticachex": {:hex, :elasticachex, "1.1.2", "2ba314ac7bd3c161aeb44e2600d3d256263593c6042aff2d1de1df722b820bc7", [:mix], [{:socket, "~> 0.3", [hex: :socket, repo: "hexpm", optional: false]}], "hexpm"}, - "ex_doc": {:hex, :ex_doc, "0.20.2", "1bd0dfb0304bade58beb77f20f21ee3558cc3c753743ae0ddbb0fd7ba2912331", [:mix], [{:earmark, "~> 1.3", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.10", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"}, - "herd": {:hex, :herd, "0.4.3", "97469cf289c1e89a4f2b356da486ae5a354751f91c10cd3749af6aedebd9a775", [:mix], [{:libring, "~> 1.1", [hex: :libring, repo: "hexpm", optional: false]}, {:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: false]}], "hexpm"}, - "jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"}, - "libring": {:hex, :libring, "1.4.0", "41246ba2f3fbc76b3971f6bce83119dfec1eee17e977a48d8a9cfaaf58c2a8d6", [:mix], [], "hexpm"}, - "makeup": {:hex, :makeup, "0.8.0", "9cf32aea71c7fe0a4b2e9246c2c4978f9070257e5c9ce6d4a28ec450a839b55f", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"}, - "makeup_elixir": {:hex, :makeup_elixir, "0.13.0", "be7a477997dcac2e48a9d695ec730b2d22418292675c75aa2d34ba0909dcdeda", [:mix], [{:makeup, "~> 0.8", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm"}, - "memcachex": {:hex, :memcachex, "0.5.0", "87152a0d5151d2d59abdaba76b47f78af28ab87d71f603bd6e0d90a541eb4fe9", [:mix], [{:connection, "~> 1.0.3", [hex: :connection, repo: "hexpm", optional: false]}, {:poison, "~> 2.1 or ~> 3.0 or ~> 4.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"}, - "nimble_parsec": {:hex, :nimble_parsec, "0.5.0", "90e2eca3d0266e5c53f8fbe0079694740b9c91b6747f2b7e3c5d21966bba8300", [:mix], [], "hexpm"}, - "poolboy": {:hex, :poolboy, "1.5.2", "392b007a1693a64540cead79830443abf5762f5d30cf50bc95cb2c1aaafa006b", [:rebar3], [], "hexpm"}, - "socket": {:hex, :socket, "0.3.13", "98a2ab20ce17f95fb512c5cadddba32b57273e0d2dba2d2e5f976c5969d0c632", [:mix], [], "hexpm"}, - "telemetry": {:hex, :telemetry, "0.4.1", "ae2718484892448a24470e6aa341bc847c3277bfb8d4e9289f7474d752c09c7f", [:rebar3], [], "hexpm"}, + "benchfella": {:hex, :benchfella, "0.3.5", "b2122c234117b3f91ed7b43b6e915e19e1ab216971154acd0a80ce0e9b8c05f5", [:mix], [], "hexpm", "23f27cbc482cbac03fc8926441eb60a5e111759c17642bac005c3225f5eb809d"}, + "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"}, + "connection": {:hex, :connection, "1.0.4", "a1cae72211f0eef17705aaededacac3eb30e6625b04a6117c1b2db6ace7d5976", [:mix], [], "hexpm", "4a0850c9be22a43af9920a71ab17c051f5f7d45c209e40269a1938832510e4d9"}, + "credo": {:hex, :credo, "0.10.2", "03ad3a1eff79a16664ed42fc2975b5e5d0ce243d69318060c626c34720a49512", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "539596b6774069260d5938aa73042a2f5157e1c0215aa35f5a53d83889546d14"}, + "dialyxir": {:hex, :dialyxir, "0.5.1", "b331b091720fd93e878137add264bac4f644e1ddae07a70bf7062c7862c4b952", [:mix], [], "hexpm", "6c32a70ed5d452c6650916555b1f96c79af5fc4bf286997f8b15f213de786f73"}, + "earmark": {:hex, :earmark, "1.3.2", "b840562ea3d67795ffbb5bd88940b1bed0ed9fa32834915125ea7d02e35888a5", [:mix], [], "hexpm", "e3be2bc3ae67781db529b80aa7e7c49904a988596e2dbff897425b48b3581161"}, + "elasticachex": {:hex, :elasticachex, "1.1.2", "2ba314ac7bd3c161aeb44e2600d3d256263593c6042aff2d1de1df722b820bc7", [:mix], [{:socket, "~> 0.3", [hex: :socket, repo: "hexpm", optional: false]}], "hexpm", "cbdc4a52a4df2350d1dbc006529d5c069d1eec9fca6d5ae304949bfc4602ebf5"}, + "ex_doc": {:hex, :ex_doc, "0.20.2", "1bd0dfb0304bade58beb77f20f21ee3558cc3c753743ae0ddbb0fd7ba2912331", [:mix], [{:earmark, "~> 1.3", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.10", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm", "8e24fc8ff9a50b9f557ff020d6c91a03cded7e59ac3e0eec8a27e771430c7d27"}, + "herd": {:hex, :herd, "0.4.3", "97469cf289c1e89a4f2b356da486ae5a354751f91c10cd3749af6aedebd9a775", [:mix], [{:libring, "~> 1.1", [hex: :libring, repo: "hexpm", optional: false]}, {:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: false]}], "hexpm", "44bfd2c42a206431495d5103a77f52a992f4f1391a13459a9e8fd7b143cd99c9"}, + "jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fdf843bca858203ae1de16da2ee206f53416bbda5dc8c9e78f43243de4bc3afe"}, + "libring": {:hex, :libring, "1.4.0", "41246ba2f3fbc76b3971f6bce83119dfec1eee17e977a48d8a9cfaaf58c2a8d6", [:mix], [], "hexpm", "1feaf05ee886815ad047cad7ede17d6910710986148ae09cf73eee2989717b81"}, + "makeup": {:hex, :makeup, "0.8.0", "9cf32aea71c7fe0a4b2e9246c2c4978f9070257e5c9ce6d4a28ec450a839b55f", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "5fbc8e549aa9afeea2847c0769e3970537ed302f93a23ac612602e805d9d1e7f"}, + "makeup_elixir": {:hex, :makeup_elixir, "0.13.0", "be7a477997dcac2e48a9d695ec730b2d22418292675c75aa2d34ba0909dcdeda", [:mix], [{:makeup, "~> 0.8", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "adf0218695e22caeda2820eaba703fa46c91820d53813a2223413da3ef4ba515"}, + "memcachex": {:hex, :memcachex, "0.5.0", "87152a0d5151d2d59abdaba76b47f78af28ab87d71f603bd6e0d90a541eb4fe9", [:mix], [{:connection, "~> 1.0.3", [hex: :connection, repo: "hexpm", optional: false]}, {:poison, "~> 2.1 or ~> 3.0 or ~> 4.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d62c835edfad36241e0c0bcba4cbdd03c3950d9386bfce49dab684f0574bde79"}, + "nimble_parsec": {:hex, :nimble_parsec, "0.5.0", "90e2eca3d0266e5c53f8fbe0079694740b9c91b6747f2b7e3c5d21966bba8300", [:mix], [], "hexpm", "5c040b8469c1ff1b10093d3186e2e10dbe483cd73d79ec017993fb3985b8a9b3"}, + "poolboy": {:hex, :poolboy, "1.5.2", "392b007a1693a64540cead79830443abf5762f5d30cf50bc95cb2c1aaafa006b", [:rebar3], [], "hexpm", "dad79704ce5440f3d5a3681c8590b9dc25d1a561e8f5a9c995281012860901e3"}, + "socket": {:hex, :socket, "0.3.13", "98a2ab20ce17f95fb512c5cadddba32b57273e0d2dba2d2e5f976c5969d0c632", [:mix], [], "hexpm", "f82ea9833ef49dde272e6568ab8aac657a636acb4cf44a7de8a935acb8957c2e"}, + "telemetry": {:hex, :telemetry, "0.4.1", "ae2718484892448a24470e6aa341bc847c3277bfb8d4e9289f7474d752c09c7f", [:rebar3], [], "hexpm", "4738382e36a0a9a2b6e25d67c960e40e1a2c95560b9f936d8e29de8cd858480f"}, } From 812d2ee1c967c28281d56f87fe6be3b0124d279b Mon Sep 17 00:00:00 2001 From: Yana Lebedeva Date: Thu, 8 Jul 2021 21:03:28 -0400 Subject: [PATCH 2/2] ING-424 remove Application from Memcachir.Plugin --- lib/memcachir.ex | 9 ++++----- lib/memcachir_plugin.ex | 8 -------- mix.exs | 1 - test/failure_handling_test.exs | 1 + test/memcachir/discovery/elasticache_test.exs | 3 ++- test/memcachir_test.exs | 1 + 6 files changed, 8 insertions(+), 15 deletions(-) diff --git a/lib/memcachir.ex b/lib/memcachir.ex index 330f55c..151d358 100644 --- a/lib/memcachir.ex +++ b/lib/memcachir.ex @@ -46,8 +46,8 @@ defmodule Memcachir.Supervisor do Supervises the memcachir cluster, pool and registry (which is used internally) """ use Herd.Supervisor, otp_app: :memcachir, - pool: Memcachir.Pool, - cluster: Memcachir.Cluster + pool: Memcachir.Pool, + cluster: Memcachir.Cluster end defmodule Memcachir do @@ -55,7 +55,6 @@ defmodule Memcachir do TODO """ use Memcachir.Plugin, otp_app: :memcachir, - pool: Memcachir.Pool, - cluster: Memcachir.Cluster, - supervisor: Memcachir.Supervisor + pool: Memcachir.Pool, + cluster: Memcachir.Cluster end diff --git a/lib/memcachir_plugin.ex b/lib/memcachir_plugin.ex index cd02864..bf8afa7 100644 --- a/lib/memcachir_plugin.ex +++ b/lib/memcachir_plugin.ex @@ -7,21 +7,13 @@ defmodule Memcachir.Plugin do otp_app = Keyword.get(opts, :otp_app) pool = Keyword.get(opts, :pool) cluster = Keyword.get(opts, :cluster) - supervisor = Keyword.get(opts, :supervisor) quote do - use Application import Memcachir.Plugin @otp_app unquote(otp_app) @pool unquote(pool) @cluster unquote(cluster) - @supervisor unquote(supervisor) - - def start(_, _) do - opts = Application.get_all_env(@otp_app) - @supervisor.start_link(opts) - end def get(key, opts \\ []), do: get(@cluster, @pool, key, opts) diff --git a/mix.exs b/mix.exs index deab85c..b0a1551 100644 --- a/mix.exs +++ b/mix.exs @@ -21,7 +21,6 @@ defmodule Memcachir.Mixfile do # Type "mix help compile.app" for more information def application do [ - mod: {Memcachir, []}, extra_applications: [:logger, :libring] ] end diff --git a/test/failure_handling_test.exs b/test/failure_handling_test.exs index 80be931..96c6cf5 100644 --- a/test/failure_handling_test.exs +++ b/test/failure_handling_test.exs @@ -8,6 +8,7 @@ defmodule FailureHandlingTest do setup do Application.delete_env(:memcachir, :hosts) Application.put_env(:memcachir, :elasticache, "localhost:11211") + start_supervised(Memcachir.Supervisor) :ok end diff --git a/test/memcachir/discovery/elasticache_test.exs b/test/memcachir/discovery/elasticache_test.exs index 56a326e..70854e1 100644 --- a/test/memcachir/discovery/elasticache_test.exs +++ b/test/memcachir/discovery/elasticache_test.exs @@ -3,7 +3,8 @@ defmodule Memcachir.ServiceDiscovery.ElasticacheTest do alias Memcachir.ServiceDiscovery.Elasticache test "read elasticache configuration" do + start_supervised(Memcachir.Supervisor) MockSocketModule.update(["localhost|localhost|11211"]) assert Elasticache.nodes == [{'localhost', 11_211}] end -end \ No newline at end of file +end diff --git a/test/memcachir_test.exs b/test/memcachir_test.exs index 7650a60..9120a55 100644 --- a/test/memcachir_test.exs +++ b/test/memcachir_test.exs @@ -4,6 +4,7 @@ defmodule MemcachirTest do setup do Application.delete_env(:memcachir, :elasticache) Application.put_env(:memcachir, :hosts, "localhost:11211") + start_supervised(Memcachir.Supervisor) assert {:ok} == Memcachir.flush() :ok end