How to run more then one same worker (Cachex) inside Supervision

Hi, I’m trying to add inside my application supervision tree two of Cachex (https://hexdocs.pm/cachex/Cachex.html) worker but getting error:

** bad child specification, more than one child specification has the id: Cachex. **

code :
children = [

worker(Cachex, [:requests, [] ]),
worker(Cachex, [:ntf, [] ])
]

As error text suggesting using to use maps as child specifications, i changed code to look like this:

children = [
Supervisor.child_spec({Cachex, [:requests, []]}, id: :my_cache_1),
Supervisor.child_spec({Cachex, [:ntf, []]}, id: :my_cache_2)
]

but now getting ** (EXIT) :invalid_name **
I wonder if there is any way to make it work or if some one more familiar with this library and can help me.

Thanks!

This:

{Cachex, [:requests, []]}

means the supervisor will call Cachex.start_link/1 like this:

Cachex.start_link([:requests, []])

rather than Cachex.start_link/2, which is probably what you expected:

Cachex.start_link(:requests, [])

So passing {Cachex, :requests} instead should work, because it’ll call Cachex.start_link(:requests).

If you want to pass options later on you’ll have to set the start function in the child spec yourself to make sure it calls start_link/2 and not start_link/1.

For context, recent Elixir guidelines are to always use start_link/1, so it’s normally not a problem. Cachex probably predates that.

3 Likes

I see, many thanks!
I will try once get home.

Just in case some one need to see code for implementation:

def start(_type, _args) do
  import Supervisor.Spec
  import Cachex.Spec

  children = [
      %{id: Cache1, start: {Cachex, :start_link, [:requests, []]}},
      %{id: Cache2, start: {Cachex, :start_link, [:messages, []]}}
    ]
  opts = [strategy: :one_for_one]
  Supervisor.start_link(children, opts)
end
8 Likes

After a decade of using elixir, the supervision tree and child spec formats are perhaps my only frustration. For 1.15 and Cachex 3.6, the following seems to work:


  def start(_type, _args) do

    children = [
      Supervisor.child_spec(Cachex.child_spec(name: :tags_cache, limit: 10_000), id: :cachex_tags),
      Supervisor.child_spec(Cachex.child_spec(name: :prefs_cache, limit: 10_000), id: :cachex_prefs),
  ] 

Going to leave this here in case the above responses do not work for later versions of the dependencies as well as elixir.

You can also set the following in your application.ex

children = [
      # Start the Telemetry supervisor
      # Start the Ecto repository
      Supervisor.child_spec({Cachex, :my_cache}, id: :my_cache),
      Supervisor.child_spec({Cachex, :temp_cache}, id: :temp_cache),
      ...
     ]
1 Like