Honestly, it probably is easier to use IO.iodata_length. Feel free to open an issue or PR.
The thing that I don’t know about is checking to see if iodata is valid UTF8 for text frames. Currently I’m using String.valid?/1. If I remember correctly it doesn’t work with iodata. If it does, then I am totally wrong and there is no problem at all.
The thing that I don’t know about is checking to see if iodata is valid UTF8 for text frames. Currently I’m using String.valid?/1. If I remember correctly it doesn’t work with iodata. If it does, then I am totally wrong and there is no problem at all.
Oh, I haven’t thought about it. Is this check required by the spec?
Section 5.6 of the WebSocket Spec says that all complete text data frames need to be valid UTF8. However, closer reading of Section 8.1 implies that you could get away with sending a non-valid text frame and it is on the receiver to verify.
I think for the sake of this being a library and such, it should just work with as many use cases as possible instead of being the most correct version possible. So I am more than willing to forego the outgoing check in favor of making it work for your use case. Especially since the spec implies I can do that.
But there are probably a couple of non-trivial changes to make for iodata. Unless I don’t care about the overall send/write performance and just set it as a binary before it was sent, which would defeat the point of iodata.
This is probably a basic question, but I’ve been having some problems getting modules where I use WebSockex to not crash their supervisors when there’s an issue connecting (e.g. when I turn my wifi off).
* (Mix) Could not start application app: App.Application.start(:normal, []) returned an error: shutdown: failed to start child: App.Sockets.Supervisor
** (EXIT) shutdown: failed to start child: App.Sockets.Foo
** (EXIT) %WebSockex.ConnError{original: :timeout}
I’ve implemented a handle_disconnect/2. What changes should I make so that a networking failure doesn’t crash the whole module (and its supervisors)?
Terminating with :normal after an Exceptional Close or Error
Usually you’ll want to negotiate and handle any abnormal close event or error leading to it, as per WS Spec, but there might be cases where you simply want the socket to exit as if it was a normal event, even if it was abruptly closed or another exception was raised. In those cases you can define the terminate callback and return exit(:normal) from it.
def terminate(reason, state) do
IO.puts(\nSocket Terminating:\n#{inspect reason}\n\n#{inspect state}\n")
exit(:normal)
end
I’ve implemented a terminate very similar to that one. It gets executed if I cut the web connection after connecting but not if the connection is off when start_link() is called. In both cases, this leads to taking down the whole process and its supervisors.
The behavior I want instead is to just keep trying to reconnect to the 3rd party endpoint periodically.
Stumbled on the same problems.
So basically I created a GenServer which is wrapper for the WebSockex process.
Starting the GenServer will return the pid no matter if the WebSockex fails on the start_link or not. You actualy start the websocket connection in the handle_continue/2 func asynchrously.
Then you need to specify handle_initial_conn_failure: true option on the WebSockex start_link func so you can handle the error in the handle_disconnect/2 func. In the handle_disconnect/2 func you can return the tuple {:reconnect, state} for automatic reconnecting. I have added some process sleep there aswell. Here’s the code:
def start_link(args) do
GenServer.start_link(__MODULE__, args)
end
@impl GenServer
def init(state) do
{:ok, state, {:continue, :start_ws}}
end
@impl GenServer
def handle_continue(:start_ws, state) do
{:ok, pid} = WebSockex.start_link(url, __MODULE__, [], [handle_initial_conn_failure: true])
subscribe(pid, state)
{:noreply, state}
end
@impl WebSockex
def handle_disconnect(_conn, state) do
IO.puts("Disconnected!")
# Wait before trying to reconnect.
Process.sleep(5000)
{:reconnect, state}
end
Theres also an option called async on the WebSocex library but this does not seem to work with the sending frame or I am missing something.