MyMedsAndMe / spell

Spell is a Web Application Messaging Protocol (WAMP) client implementation in Elixir. WAMP is an open standard WebSocket subprotocol that provides two application messaging patterns in one unified protocol: Remote Procedure Calls + Publish & Subscribe: http://wamp.ws/
Apache License 2.0
66 stars 25 forks source link

Spell.Peer.start_link required before Spell.connect #49

Open faultyserver opened 8 years ago

faultyserver commented 8 years ago

While trying to get Spell working with an existing Crossbar setup, I continuously ran into errors with Spell.connect/2 exiting because of a no process error:

iex(1)> Spell.connect("ws://localhost:8080/ws/", realm: "realm1")
** (exit) exited in: GenServer.call(Spell.Peer.Supervisor, {:start_child, [%{owner: #PID<0.149.0>, realm: "realm1", retries: 5, retry_interval: 1000, role: %{features: %{callee: %{}, caller: %{}, publisher: %{}, subscriber: %{}}, options: [{Spell.Role.Session, [realm: "realm1"]}, {Spell.Role.Publisher, []}, {Spell.Role.Subscriber, []}, {Spell.Role.Caller, []}, {Spell.Role.Callee, []}]}, serializer: %{module: Spell.Serializer.JSON, options: []}, transport: %{module: Spell.Transport.WebSocket, options: [host: "localhost", port: 8080, path: "/ws/"]}}]}, :infinity)
    ** (EXIT) no process
    (elixir) lib/gen_server.ex:596: GenServer.call/3
             lib/spell.ex:152: Spell.init_peer/2

I'm fairly new with Elixir, and so I searched around the internet with this rather-unhelpful stacktrace trying to find a solution. Finally, after about 2 days of reading through the source, it turned out that the Peer Supervisor hadn't been started by the time init_peer/2 was being called.

Starting the Supervisor manually by calling Spell.Peer.start_link/0 solved the issue:

iex(1)> Spell.Peer.start_link
{:ok, #PID<0.152.0>}
iex(2)> Spell.connect("ws://localhost:8080/ws/", realm: "realm1")

13:44:25.928 [debug] Connecting to ws://localhost:8080/ws/...
...
{:ok, #PID<0.154.0>}
iex(3)> 

I couldn't find anything in the documentation that hinted towards this, which was rather frustrating.

Would it be possible to either ensure that the Peer Supervisor is running before Spell.connect attempts to initialize a Peer, or add the Spell.Peer.start_link requirement somewhere in the documentation?

jtmoulia commented 8 years ago

Hello @faultyserver -- yeah, that's a pretty bad stack trace, and the documentation can be made clearer.

You're going to typically want to run Spell as an OTP application -- this will start the Spell's process supervision tree which manages the peer supervisor, The simplest way to ensure Spell starts is to make your own application dependent on Spell (this is totally missing from the docs :'( ), adding something like this to your app's mix.exs:

def application do
  [applications: [:spell],
   mod: {Application, []}]
end

Now, if you boot up your application, e.g. iex -S mix, the peer supervisor should be started as part of spell's supervision tree, giving it proper start/stop/restart process behavior.

I'm going to leave this issue open pending improved documentation and potentially exception message. Thanks for reporting! <3

faultyserver commented 8 years ago

Thanks for the information! I added Spell to the application list, but now I'm getting a new error:

=INFO REPORT==== 7-Oct-2016::21:09:24 ===
    application: logger
    exited: stopped
    type: temporary
** (Mix) Could not start application pbkdf2: could not find application file: pbkdf2.app

To me, this says the error is coming somewhere from logger, but it only comes up when I include :spell in the application list, so I'm not sure. Quick googling didn't lead me to a solution.

jtmoulia commented 8 years ago

Progress -- the issue here is that the :pbkdf2 application is a dependency of Spell; it doesn't appear to have been fetched.

Check out PR #50 and try going through the updated Using Spell with your Elixir Project. Let me know if it fixes the issue!

faultyserver commented 8 years ago

Okay, now I'm a little confused. Before adding :spell to application, I was not hitting the pbkdf2 error, and I was able to make and use connections with Spell. After adding :spell, I'm hitting this error.

So, I changed deps to directly require pbkdf2:

defp deps do
  [
    # GTFS wrapper
    {:gtfs, "~> 0.3.1"},
    # WAMP interface
    {:spell, "~> 0.1"},
    # WebSocket transportation
    {:websocket_client, github: "jeremyong/websocket_client", tag: "v0.7"},
    # JSON serialization
    {:poison, "~> 1.4"},
    {:pbkdf2, "~> 2.0"} # << Added pbkdf2
  ]
end

After a mix deps.get, everything worked. Taking out that requirement, running mix deps.clean --all and mix deps.get again caused the error to re-appear.

Forgive me if I'm missing something really obvious, but I see pbkdf2 in Spell's mix.exs:

# TODO: allow transport/serialization deps to be filtered out
defp deps do
  [
   # Req'd by: `Spell.Transport.Websocket`
   {:websocket_client, github: "jeremyong/websocket_client", tag: "v0.7"},
   # Req'd by: `Spell.Serializer.JSON`
   {:poison, "~> 1.4.0"},
   # Req'd by: `Spell.Serializer.MessagePack`
   {:msgpax, "~> 0.7"},
   # Req'd by: `Spell.Authentication.CRA`
   {:pbkdf2, github: "pma/erlang-pbkdf2", branch: "master"},
   # Doc deps
   {:earmark, "~> 0.1", only: :doc},
   {:ex_doc, "~> 0.7", only: :doc}
  ]
end

so, shouldn't it be brought in as a dependency automatically?

PS: The PR looks good to me, but following it led me to this pbkdf2 error.

AndrewDryga commented 7 years ago

Same issue here.

bbean86 commented 7 years ago

@faultyserver you're probably still pulling version 0.1.0 of the code, which is tagged to an earlier commit than master. Changing the reference in mix.exs from {:spell, "~> 0.1.0"} to {:spell, github: "MyMedsAndMe/spell", branch: "master"} will fix your issue. A new tag and release needs to be made to make things work using version references, and the README needs to be updated.