Phoenix Channel handle_out all events

I have currently implemented a handle_in that accepts all events and then I parse the event names and handle them accordingly so I don’t really know ahead of time the event names to add to the call to intercept. Is there way to implement a handle_out callback that gets called for all events?

Hi themusicman!

Your description reads to me as if you are already doing something like the following:

def handle_in(incoming_signal, payload, socket) do
    (outgoing_signal, payload} = YourCode.parse_and_handle(outgoing_signal)
    broadcast(socket, outgoing_signal, payload)
    {:noreply, socket}
end

So you have a generic handle_in handling function and now you want a matching, generic handle_out handler, that in first case gets activated on every signal, correct? If understood right, this should probably make the trick for you.

def handle_out(outgoing_signal, payload, socket) do
    # things you want to handle go here
    {:noreply, socket}
end

If understood wrong and you want to accomplish something else, it would work best for me, if you’d upload a minimal, “runnable”, sample project github or alike.

That is pretty much what I am trying to do. I tried setting up a handle_out like that but it never gets called. This is what I tried:

def handle_out(event, message, socket) do
    IO.inspect("----------handle_out-----------")
    IO.inspect(event: event)
    push(socket, event, message)
    {:noreply, socket}
  end

I don’t think it will allow you to define a handle_out that does not correspond to a value you pass to intercept.

def __on_definition__(env, :def, :handle_out, [event, _payload, _socket], _, _)
      when is_binary(event) do
    unless event in Module.get_attribute(env.module, :phoenix_intercepts) do
      IO.write(
        "#{Path.relative_to(env.file, File.cwd!())}:#{env.line}: [warning] " <>
          "An intercept for event \"#{event}\" has not yet been defined in #{env.module}.handle_out/3. " <>
          "Add \"#{event}\" to your list of intercepted events with intercept/1"
      )
    end
  end

And since I don’t know the event names beforehand I don’t have any value to pass to intercept so I can’t define a generic handle_out. :frowning:

I used https://github.com/dwyl/phoenix-chat-example as sample project that implements Phoenix channels. Thereby I was able to modify the code to have a generic handle_out.

So your displayed def handle_out(event, message, socket) do code did work, but you haven’t seen any output from the IO.inspect call, since to whatever. Probably the channel’s STDOUT piped anywhere else but to the screen. The output becomes “visible” if you run your code again in IEX (as you can see in the uploaded screenshot).

P.S: The reason why this “generic signature” works so pretty smooth is, the phoenix framework people are making real nice use of elixir’s pattern matching feature, to build a consistent and ready to use API. It actually works the same way with ordinary controller actions btw.

Not possible. You must explicitly list the outgoing events to be intercepted. We require this as it has large performance implications. Your client and server necessarily have some messaging contract, so codifying the list of available events should not be a large burden. Hope this helps :slight_smile:

3 Likes