chanon
Phoenix Websocket Error/Exception Handling
I am using something like this to to handle Websocket requests:
def handle_in("new_msg", data, socket) do
# do something with data that might result in exceptions/exits/errors raised
{:reply, {:ok, output}, socket}
end
And in JavaScript side, something like this
channel.push("new_msg", data, 10000)
.receive("ok", (output) => console.log("created message", output) )
.receive("error", (reasons) => console.log("create failed", reasons) )
.receive("timeout", () => console.log("Networking issue...") )
What happens is, when an exception is raised it seems the whole channel process (?) goes down, and the client which is waiting for a response gets no response and just times out.
What I would like instead is to be able to return an error immediately with maybe “unexpected error” reason kind of like a http 500 error.
I don’t want to leave the client hanging and it isn’t a “Networking issue” so timeout isn’t appropriate result.
After some trial and error, I now have the following, which seems to work nicely:
def handle_in("new_msg", data, socket) do
try do
# do something with data that might result in exceptions/exits/errors raised
{:reply, {:ok, output}, socket}
catch
:exit, error ->
Logger.error(Exception.format_exit(reason))
{:reply, {:error, %{reason: "Unexpected Error"}}, socket}
end
end
But I am a bit unsure, as
- I think for http requests Phoenix handles this and automatically responds with 500 code? But for websocket requests I have to handle this myself?
- And also the Elixir tutorial seems to say that you wouldn’t normally need to use try/catch
- And would I also need a rescue?
EDIT: I am now doing it like this as all my messages need replies:
# try catch here
def handle_in(event, params, socket) do
try do
{:reply, handle(event, params, socket), socket}
catch
:exit, reason ->
Logger.info("responding with unexpected error")
Logger.error(Exception.format_exit(reason))
{:reply, {:error, %{reason: "Unexpected Error."}}, socket}
end
end
# handle each message type, no boilerplate
defp handle("new_msg", params, socket) do
# do stuff
{:ok, %{result: output}}
end
defp handle("another_msg", params, socket) do
# do stuff
{:ok, %{result: output}}
end
Most Liked Responses
idi527
I think there is also channel.onError which is supposed to handle channel process dying and socket disconnecting. I’d guess socket.onError only handles the latter.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #javascript
- #code-sync
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance








