Skip to content

Commit

Permalink
replace :gun with Mint.WebSocket (#38)
Browse files Browse the repository at this point in the history
* remove :gun from documentation

* switch out gun for mint_web_socket dep

* add dependency on Connection

* upgrade to elixir 1.12 locally

* remove dep on connection

* add bodies to pings and pongs

* add options for using mint websocket to config

* switch out gun for mint websocket

* remove connection test with gun mock

* fix failure return patterns in sync test

* remove hard gun matches in conn telemetry test

* format

* fix coverage

* use published mint_web_socket

* resolve dialyzer errors

* remove remaining references to gun

* set release date for v0.8.0
  • Loading branch information
the-mikedavis committed Jul 1, 2021
1 parent 4b17c8b commit 319fd66
Show file tree
Hide file tree
Showing 27 changed files with 335 additions and 640 deletions.
4 changes: 3 additions & 1 deletion .dialyzer_ignore.exs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
[
~r"MACRO",
~r"lib/slipstream/socket_test.ex:\d+:pattern_match The pattern can never match the type nil | {atom(), atom()}.",
~r"lib/phoenix/router.ex"
~r"lib/phoenix/router.ex",
~r"lib/slipstream/connection/impl.ex",
~r"lib/slipstream/connection/pipeline.ex"
]
4 changes: 2 additions & 2 deletions .tool-versions
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
elixir 1.11.2-otp-23
erlang 23.2
elixir 1.12.1-otp-24
erlang 24.0
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,24 @@ The format is based on [Keep a
Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## 0.8.0 - 2021-07-01

### Changed

- Switched out `:gun` for Mint.WebSocket as the low-level websocket client

### Removed

- Removed the `:gun_open_options` key from configuration
- Use the new `:mint_opts` key instead to configure TLS options

### Added

- Added the `:mint_opts` key to configuration for controlling the options
passed to `Mint.HTTP.connect/4`
- Added the `:extensions` key to configuration for specifying
`Mint.WebSocket.Extension` configuration passed to `Mint.WebSocket.upgrade/4`

## 0.7.0 - 2021-06-21

### Added
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Slipstream

![CI](https://github.com/NFIBrokerage/slipstream/workflows/CI/badge.svg)
[![Coverage Status](https://coveralls.io/repos/github/NFIBrokerage/slipstream/badge.svg)](https://coveralls.io/github/NFIBrokerage/slipstream)
[![hex.pm version](https://img.shields.io/hexpm/v/slipstream.svg)](https://hex.pm/packages/slipstream)
Expand All @@ -11,7 +12,7 @@ See the [online documentation](https://hexdocs.pm/slipstream)

## Main Features

- backed by `:gun` instead of `:websocket_client` (see [why](https://hexdocs.pm/slipstream/why_gun.html#content))
- backed by [Mint.WebSocket](https://github.com/NFIBrokerage/mint_web_socket)
- an `await_*` interface for a interacting [synchronously](https://hexdocs.pm/slipstream/Slipstream.html#module-synchronicity)
- built-in [re-connect and re-join mechanisms](https://hexdocs.pm/slipstream/Slipstream.html#module-retry-mechanisms) matching `phoenix.js`
- a [testing framework](https://hexdocs.pm/slipstream/Slipstream.SocketTest.html#content) for clients
Expand All @@ -24,7 +25,7 @@ Add slipstream to your dependencies in `mix.exs`:
```elixir
def deps do
[
{:slipstream, "~> 0.5"}
{:slipstream, "~> 0.8"}
]
end
```
Expand Down
2 changes: 0 additions & 2 deletions config/dev.exs
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,3 @@ config :slipstream, Slipstream.TestModeClient,
# N.B. this client will _not_ connect
uri: "ws://localhost:54321/socket/websocket",
test_mode?: true

config :slipstream, :gun_client, :gun
2 changes: 0 additions & 2 deletions config/test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,3 @@ config :slipstream, Slipstream.TestModeClient,
# N.B. this client will _not_ connect
uri: "ws://localhost:54321/socket/websocket",
test_mode?: true

config :slipstream, :gun_client, :gun
7 changes: 3 additions & 4 deletions guides/implementation.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,9 @@ Slipstream starts two processes to run a websocket connection:
- the client process (modules with `use Slipstream`)
- the connection process

The connection process is spawned and killed upon `Slipstream.connect/2` and
`Slipstream.disconnect/1`, respectively. It directly interfaces with `:gun` in
active mode, meaning that messages from `:gun` connections and requests are
forwarded to the mailbox of the connection process.
The connection process is spawned and killed upon `Slipstream.connect/2`
and `Slipstream.disconnect/1`, respectively. It directly interfaces with
the WebSocket connection via `Mint.WebSocket`.

The client process is simply a GenServer that has `c:GenServer.handle_info/2`
clauses injected to handle slipstream events. The entire purpose of the client
Expand Down
55 changes: 0 additions & 55 deletions guides/why_gun.md

This file was deleted.

5 changes: 4 additions & 1 deletion lib/slipstream.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ defmodule Slipstream do
Slipstream is a websocket client for connection to `Phoenix.Channel`s.
Slipstream is a bit different from existing websocket implementations in that:
- it's backed by `:gun` instead of `:websocket_client`
- it's backed by `Mint.WebSocket`
- it has an `await_*` interface for performing actions synchronously
- smart retry strategies for reconnection and rejoining work out-of-the-box
- a testing framework for clients
Expand Down Expand Up @@ -1232,8 +1232,11 @@ defmodule Slipstream do
event(%Events.TopicJoinSucceeded{topic: ^topic} = event) ->
{:ok, Socket.apply_event(socket, event)}

# coveralls-ignore-start
event(%Events.TopicJoinFailed{topic: ^topic} = event) ->
{:error, Events.TopicJoinFailed.to_reason(event)}

# coveralls-ignore-stop
after
timeout -> {:error, :timeout}
end
Expand Down
6 changes: 6 additions & 0 deletions lib/slipstream/callback.ex
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,13 @@ defmodule Slipstream.Callback do
callback :handle_leave, [event.topic]
end

# coveralls-ignore-start
defp _determine_callback(%Events.TopicLeaveAccepted{} = event) do
callback :__no_op__, [event]
end

# coveralls-ignore-stop

defp _determine_callback(%Events.ReplyReceived{} = event) do
callback :handle_reply, [event.ref, event.reply]
end
Expand All @@ -129,7 +132,10 @@ defmodule Slipstream.Callback do
callback :handle_disconnect, [event.reason]
end

# coveralls-ignore-start
defp _determine_callback(event) do
callback :handle_info, [event]
end

# coveralls-ignore-stop
end
38 changes: 22 additions & 16 deletions lib/slipstream/configuration.ex
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,22 @@ defmodule Slipstream.Configuration do
type: {:list, :non_neg_integer},
default: [100, 500, 1_000, 2_000, 5_000, 10_000]
],
gun_open_options: [
mint_opts: [
doc: """
A map of options to pass to `:gun.open/3`. See the `:gun` documentation
for more information. Note that `:gun` does not support websocket over
HTTP2 and that `:gun` naively prefers HTTP2 when connecting over TLS.
The `:protocols => [:http]` option will be merged in by default to allow
`"wss"` connections out of the box.
A keywordlist of options to pass to `Mint.HTTP.connect/4` when opening
connections. This can be used to set up custom TLS certificate
configuration. See the `Mint.HTTP.connect/4` documentation for available
options.
""",
type: {:custom, __MODULE__, :parse_gun_open_options, []},
default: %{protocols: [:http]}
type: :keyword_list,
default: [protocols: [:http1]]
],
extensions: [
doc: """
A list of extensions to pass to `Mint.WebSocket.upgrade/4`.
""",
type: :any,
default: []
],
test_mode?: [
doc: """
Expand Down Expand Up @@ -168,20 +174,26 @@ defmodule Slipstream.Configuration do
{:port, port} when is_integer(port) and port > 0 <- {:port, uri.port} do
{:ok, uri}
else
# coveralls-ignore-start
{:port, bad_port} ->
{:error,
"unparseable port value #{inspect(bad_port)}: please provide a positive-integer value"}

# coveralls-ignore-stop

{:scheme, scheme} ->
{:error,
"unknown scheme #{inspect(scheme)}: only #{inspect(@known_schemes)} are accepted"}
end
end

# coveralls-ignore-start
def parse_uri(unparsed) do
{:error, "could not parse #{inspect(unparsed)} as a binary or URI struct"}
end

# coveralls-ignore-stop

defp assume_port(%URI{scheme: "ws", port: nil} = uri),
do: %URI{uri | port: 80}

Expand All @@ -191,6 +203,7 @@ defmodule Slipstream.Configuration do
defp assume_port(uri), do: uri

@doc false
# coveralls-ignore-start
def parse_pair_of_strings({key, value})
when is_binary(key) and is_binary(value) do
{:ok, {key, value}}
Expand All @@ -200,12 +213,5 @@ defmodule Slipstream.Configuration do
{:error, "could not parse #{inspect(unparsed)} as a two-tuple of strings"}
end

@doc false
def parse_gun_open_options(options) when is_map(options) do
{:ok, Map.merge(%{protocols: [:http]}, options)}
end

def parse_gun_open_options(unknown) do
{:error, "gun options must be a map, got #{inspect(unknown)}"}
end
# coveralls-ignore-stop
end
2 changes: 1 addition & 1 deletion lib/slipstream/connection.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ defmodule Slipstream.Connection do
@moduledoc false

# the Connection _is_ the socket client
# Connection interfaces with :gun and any module that implements the
# Connection interfaces with Mint.WebSocket and any module that implements the
# Slipstream behaviour to offer websocket client functionality

use GenServer, restart: :temporary
Expand Down
Loading

0 comments on commit 319fd66

Please sign in to comment.