changed
CHANGELOG.md
|
@@ -1,10 1,17 @@
|
1
1
|
# Changelog
|
2
2
|
|
3
|
## v1.4.2
|
4
|
|
5
|
### Bug fixes and improvements
|
6
|
|
7
|
* Speed up `Redix.Protocol` a little bit for common responses (`"OK"` and friends).
|
8
|
* Fix a bug where `:tcp_closed`/`:ssl_closed` and `:tcp_error`/`:ssl_error` messages wouldn't arrive to the socket owner, and Redix would get stuck in a disconnected state when sending would error out. See the discussion in [#265](https://github.com/whatyouhide/redix/issues/265).
|
9
|
|
3
10
|
## v1.4.1
|
4
11
|
|
5
12
|
### Bug fixes and improvements
|
6
13
|
|
7
|
- * `Redix.PubSub.get_client/1` is not available only behind the `:fetch_client_id_on_connect` option that you can pass to `Redix.PubSub.start_link/1`. This option defaults to `false`, so that this version of Redix is compatible with Redis v4 or earlier out of the box. To opt in into the behavior desired for [client-side caching](https://redis.io/docs/manual/client-side-caching/) and use `Redix.PubSub.get_client/1`, pass `fetch_client_id_on_connect: true` to `Redix.PubSub.start_link/1`.
|
14
|
* `Redix.PubSub.get_client_id/1` is not available only behind the `:fetch_client_id_on_connect` option that you can pass to `Redix.PubSub.start_link/1`. This option defaults to `false`, so that this version of Redix is compatible with Redis v4 or earlier out of the box. To opt in into the behavior desired for [client-side caching](https://redis.io/docs/manual/client-side-caching/) and use `Redix.PubSub.get_client_id/1`, pass `fetch_client_id_on_connect: true` to `Redix.PubSub.start_link/1`.
|
8
15
|
|
9
16
|
## v1.4.0
|
changed
hex_metadata.config
|
@@ -2,7 2,7 @@
|
2
2
|
[{<<"GitHub">>,<<"https://github.com/whatyouhide/redix">>},
|
3
3
|
{<<"Sponsor">>,<<"https://github.com/sponsors/whatyouhide">>}]}.
|
4
4
|
{<<"name">>,<<"redix">>}.
|
5
|
- {<<"version">>,<<"1.4.1">>}.
|
5
|
{<<"version">>,<<"1.4.2">>}.
|
6
6
|
{<<"description">>,<<"Fast, pipelined, resilient Redis driver for Elixir.">>}.
|
7
7
|
{<<"elixir">>,<<"~> 1.11">>}.
|
8
8
|
{<<"app">>,<<"redix">>}.
|
|
@@ -25,11 25,11 @@
|
25
25
|
{<<"repository">>,<<"hexpm">>}]]}.
|
26
26
|
{<<"files">>,
|
27
27
|
[<<"lib">>,<<"lib/redix">>,<<"lib/redix/protocol.ex">>,
|
28
|
- <<"lib/redix/telemetry.ex">>,<<"lib/redix/socket_owner.ex">>,
|
29
|
- <<"lib/redix/format.ex">>,<<"lib/redix/start_options.ex">>,
|
28
|
<<"lib/redix/connection.ex">>,<<"lib/redix/format.ex">>,
|
29
|
<<"lib/redix/exceptions.ex">>,<<"lib/redix/telemetry.ex">>,
|
30
|
<<"lib/redix/socket_owner.ex">>,<<"lib/redix/uri.ex">>,
|
31
|
<<"lib/redix/connector.ex">>,<<"lib/redix/start_options.ex">>,
|
30
32
|
<<"lib/redix/pubsub">>,<<"lib/redix/pubsub/connection.ex">>,
|
31
|
- <<"lib/redix/connection.ex">>,<<"lib/redix/uri.ex">>,
|
32
|
- <<"lib/redix/exceptions.ex">>,<<"lib/redix/pubsub.ex">>,
|
33
|
- <<"lib/redix/connector.ex">>,<<"lib/redix.ex">>,<<".formatter.exs">>,
|
33
|
<<"lib/redix/pubsub.ex">>,<<"lib/redix.ex">>,<<".formatter.exs">>,
|
34
34
|
<<"mix.exs">>,<<"README.md">>,<<"LICENSE.txt">>,<<"CHANGELOG.md">>]}.
|
35
35
|
{<<"build_tools">>,[<<"mix">>]}.
|
changed
lib/redix/connection.ex
|
@@ -271,9 271,13 @@ defmodule Redix.Connection do
|
271
271
|
{:keep_state, data, actions}
|
272
272
|
|
273
273
|
{:error, _reason} ->
|
274
|
- # The socket owner will get a closed message at some point, so we just move to the
|
275
|
- # disconnected state.
|
274
|
# The socket owner is not guaranteed to get a "closed" message, even if we close the
|
275
|
# socket here. So, we move to the disconnected state but also notify the owner that
|
276
|
# sending failed. If the owner already got the "closed" message, it exited so this
|
277
|
# message goes nowere, otherwise the socket owner will exit and notify the connection.
|
278
|
# See https://github.com/whatyouhide/redix/issues/265.
|
276
279
|
:ok = data.transport.close(data.socket)
|
280
|
send(data.socket_owner, {:send_errored, self()})
|
277
281
|
{:next_state, :disconnected, data}
|
278
282
|
end
|
279
283
|
else
|
changed
lib/redix/protocol.ex
|
@@ -25,6 25,7 @@ defmodule Redix.Protocol do
|
25
25
|
|
26
26
|
@crlf "\r\n"
|
27
27
|
@crlf_iodata [?\r, ?\n]
|
28
|
@max_integer_digits 18
|
28
29
|
|
29
30
|
@doc ~S"""
|
30
31
|
Packs a list of Elixir terms to a Redis (RESP) array.
|
|
@@ -80,6 81,9 @@ defmodule Redix.Protocol do
|
80
81
|
@spec parse(binary) :: on_parse(redis_value)
|
81
82
|
def parse(data)
|
82
83
|
|
84
|
# Clause for the most common response.
|
85
|
def parse(" OK\r\n" <> rest), do: {:ok, "OK", rest}
|
86
|
|
83
87
|
def parse(" " <> rest), do: parse_simple_string(rest)
|
84
88
|
def parse("-" <> rest), do: parse_error(rest)
|
85
89
|
def parse(":" <> rest), do: parse_integer(rest)
|
|
@@ -135,12 139,25 @@ defmodule Redix.Protocol do
|
135
139
|
|> resolve_cont(&{:ok, %Redix.Error{message: &1}, &2})
|
136
140
|
end
|
137
141
|
|
138
|
- defp parse_integer(""), do: {:continuation, &parse_integer/1}
|
142
|
# Fast integer clauses for non-split packets.
|
143
|
for n <- 1..@max_integer_digits do
|
144
|
defp parse_integer(<<digits::binary-size(unquote(n)), "\r\n", rest::binary>> = binary) do
|
145
|
String.to_integer(digits)
|
146
|
rescue
|
147
|
ArgumentError -> parse_integer_with_splits(binary)
|
148
|
else
|
149
|
int -> {:ok, int, rest}
|
150
|
end
|
151
|
end
|
139
152
|
|
140
|
- defp parse_integer("-" <> rest),
|
153
|
defp parse_integer(bin), do: parse_integer_with_splits(bin)
|
154
|
|
155
|
defp parse_integer_with_splits(""), do: {:continuation, &parse_integer_with_splits/1}
|
156
|
|
157
|
defp parse_integer_with_splits("-" <> rest),
|
141
158
|
do: resolve_cont(parse_integer_without_sign(rest), &{:ok, -&1, &2})
|
142
159
|
|
143
|
- defp parse_integer(bin), do: parse_integer_without_sign(bin)
|
160
|
defp parse_integer_with_splits(bin), do: parse_integer_without_sign(bin)
|
144
161
|
|
145
162
|
defp parse_integer_without_sign("") do
|
146
163
|
{:continuation, &parse_integer_without_sign/1}
|
changed
lib/redix/socket_owner.ex
|
@@ -50,6 50,19 @@ defmodule Redix.SocketOwner do
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
# The connection is notifying the socket owner that sending failed. If the socket owner
|
54
|
# gets this, it can stop normally without waiting for the "closed"/"error" network
|
55
|
# message from the socket.
|
56
|
def handle_info({:send_errored, conn}, %__MODULE__{conn: conn} = state) do
|
57
|
error =
|
58
|
case state.transport do
|
59
|
:ssl -> {:ssl_error, :closed}
|
60
|
:gen_tcp -> {:tcp_error, :closed}
|
61
|
end
|
62
|
|
63
|
stop(error, state)
|
64
|
end
|
65
|
|
53
66
|
def handle_info({transport, socket, data}, %__MODULE__{socket: socket} = state)
|
54
67
|
when transport in [:tcp, :ssl] do
|
55
68
|
:ok = setopts(state, socket, active: :once)
|
changed
lib/redix/start_options.ex
|
@@ -236,7 236,9 @@ defmodule Redix.StartOptions do
|
236
236
|
]
|
237
237
|
]
|
238
238
|
|
239
|
- @redix_start_link_opts_schema start_link_opts_schema |> Keyword.drop([:fetch_client_id_on_connect]) |> NimbleOptions.new!()
|
239
|
@redix_start_link_opts_schema start_link_opts_schema
|
240
|
|> Keyword.drop([:fetch_client_id_on_connect])
|
241
|
|> NimbleOptions.new!()
|
240
242
|
@redix_pubsub_start_link_opts_schema NimbleOptions.new!(start_link_opts_schema)
|
241
243
|
|
242
244
|
@spec options_docs(:redix | :redix_pubsub) :: String.t()
|
changed
mix.exs
|
@@ -5,7 5,7 @@ defmodule Redix.Mixfile do
|
5
5
|
|
6
6
|
@repo_url "https://github.com/whatyouhide/redix"
|
7
7
|
|
8
|
- @version "1.4.1"
|
8
|
@version "1.4.2"
|
9
9
|
|
10
10
|
def project do
|
11
11
|
[
|