9
votes

I made a hex package (Channels) that optionally depends on another one (AMQP). My implementation is based on Ecto's optional dependency on Mariaex.

In Channels' mix.exs:

defp deps do
  [{:amqp, "0.1.4", optional: true}]
end

In the Channels' file that depends on AMQP:

if Code.ensure_loaded?(AMQP) do

  defmodule Channels.Adapter.AMQP do
    ...
  end

end

The application is starting properly on dev and test are also passing (including those that depend on AMQP mix test --include amqp_server).

But when I try to use the package from another project some problems arise:

In my project I'm adding the following to my mix.exs file:

def application do
  [applications: [:amqp, :channels, ...],
   ...]
end

defp deps do
  [{:amqp, "0.1.4"},
   {:channels, "~> 0.1.1"},
   ...]
end

When I try to start the application or run the tests I'm getting the following error:

=INFO REPORT==== 27-May-2016::10:28:35 ===
application: logger
exited: stopped
type: temporary
** (Mix) Could not start application channels: Channels.start(:normal, []) returned an error: shutdown: failed to start child: Channels.Monitor.Supervisor
  ** (EXIT) shutdown: failed to start child: :main
    ** (EXIT) an exception was raised:
      ** (UndefinedFunctionError) undefined function Channels.Adapter .AMQP.connect/1 (module Channels.Adapter.AMQP is not available)
          Channels.Adapter.AMQP.connect([])
          (channels) lib/channels/monitor.ex:42: Channels.Monitor.init/1
          (stdlib) gen_server.erl:328: :gen_server.init_it/6
          (stdlib) proc_lib.erl:240: :proc_lib.init_p_do_apply/3

I'm adding AMQP as a dependency but it seems that Code.ensure_loaded?(AMQP) is returning false and therefore Channels.Adapter.AMQP is not being defined.

I've noticed that in the compilation process Channels is being compiled before AMQP:

...
==> channels
...
Generated channels app
==> rabbit_common (compile)
==> amqp_client (compile)
==> amqp
...
Generated amqp app
...

May this be the cause of my problem? If so, is there a way to decide the compilation order of my dependencies?

1
Which version of channels are you using? I only see 0.0.1 published on hex.pm and that doesn't include amqp as an optional dependency. See how optional dependencies are showing up for e.g. ecto.Dogbert
You are totally right. I was using 0.0.1, only changed that on my local. I published the 0.0.2 with amqp as optional dependency and it worked. The fact of adding it as an optional dependency is what changes the compilation order?jcabot
Yes, that would make mix compile them in the right order.Dogbert

1 Answers

2
votes

As Dogbert pointed out it was my mistake because I forgot to push the latest version of the package to hex. I've done it and worked properly.

Specifying the dependency as optional does change the compilation order.