changed CHANGELOG.md
 
@@ -1,5 1,11 @@
1
1
# Changelog
2
2
3
## v1.4.0
4
5
### Bug fixes and improvements
6
7
* Introduce `Redix.PubSub.get_client/1`, which can be used to implement [client-side caching](https://redis.io/docs/manual/client-side-caching/).
8
3
9
## v1.3.0
4
10
5
11
### Bug fixes and improvements
changed README.md
 
@@ -27,7 27,7 @@ This README refers to the main branch of Redix, not the latest released version
27
27
Add the `:redix` dependency to your `mix.exs` file. If you plan on connecting to a Redis server [over SSL][docs-ssl] you may want to add the optional [`:castore`][castore] dependency as well:
28
28
29
29
```elixir
30
- defp deps() do
30
defp deps do
31
31
[
32
32
{:redix, "~> 1.1"},
33
33
{:castore, ">= 0.0.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.3.0">>}.
5
{<<"version">>,<<"1.4.0">>}.
6
6
{<<"description">>,<<"Fast, pipelined, resilient Redis driver for Elixir.">>}.
7
7
{<<"elixir">>,<<"~> 1.11">>}.
8
8
{<<"app">>,<<"redix">>}.
 
@@ -24,12 24,12 @@
24
24
{<<"requirement">>,<<"~> 0.5.0 or ~> 1.0">>},
25
25
{<<"repository">>,<<"hexpm">>}]]}.
26
26
{<<"files">>,
27
- [<<"lib">>,<<"lib/redix.ex">>,<<"lib/redix">>,<<"lib/redix/exceptions.ex">>,
28
- <<"lib/redix/pubsub.ex">>,<<"lib/redix/format.ex">>,
29
- <<"lib/redix/start_options.ex">>,<<"lib/redix/pubsub">>,
30
- <<"lib/redix/pubsub/connection.ex">>,<<"lib/redix/protocol.ex">>,
31
- <<"lib/redix/telemetry.ex">>,<<"lib/redix/uri.ex">>,
32
- <<"lib/redix/connection.ex">>,<<"lib/redix/socket_owner.ex">>,
33
- <<"lib/redix/connector.ex">>,<<".formatter.exs">>,<<"mix.exs">>,
34
- <<"README.md">>,<<"LICENSE.txt">>,<<"CHANGELOG.md">>]}.
27
[<<"lib">>,<<"lib/redix">>,<<"lib/redix/start_options.ex">>,
28
<<"lib/redix/uri.ex">>,<<"lib/redix/protocol.ex">>,<<"lib/redix/pubsub">>,
29
<<"lib/redix/pubsub/connection.ex">>,<<"lib/redix/telemetry.ex">>,
30
<<"lib/redix/connection.ex">>,<<"lib/redix/pubsub.ex">>,
31
<<"lib/redix/connector.ex">>,<<"lib/redix/format.ex">>,
32
<<"lib/redix/exceptions.ex">>,<<"lib/redix/socket_owner.ex">>,
33
<<"lib/redix.ex">>,<<".formatter.exs">>,<<"mix.exs">>,<<"README.md">>,
34
<<"LICENSE.txt">>,<<"CHANGELOG.md">>]}.
35
35
{<<"build_tools">>,[<<"mix">>]}.
changed lib/redix/connection.ex
 
@@ -124,7 124,7 @@ defmodule Redix.Connection do
124
124
## Init callbacks
125
125
126
126
@impl true
127
- def callback_mode(), do: :state_functions
127
def callback_mode, do: :state_functions
128
128
129
129
@impl true
130
130
def init(opts) do
changed lib/redix/connector.ex
 
@@ -250,7 250,13 @@ defmodule Redix.Connector do
250
250
end
251
251
end
252
252
253
- defp sync_command(transport, socket, command, timeout) do
253
@spec sync_command(
254
:ssl | :gen_tcp,
255
:gen_tcp.socket() | :ssl.sslsocket(),
256
[String.t()],
257
integer()
258
) :: {:ok, any} | {:error, any}
259
def sync_command(transport, socket, command, timeout) do
254
260
with :ok <- transport.send(socket, Redix.Protocol.pack(command)),
255
261
do: recv_response(transport, socket, &Redix.Protocol.parse/1, timeout)
256
262
end
changed lib/redix/pubsub.ex
 
@@ -416,4 416,26 @@ defmodule Redix.PubSub do
416
416
when is_binary(patterns) or is_list(patterns) do
417
417
:gen_statem.call(conn, {:punsubscribe, List.wrap(patterns), subscriber})
418
418
end
419
420
@doc """
421
Gets the Redis `CLIENT ID` associated with a connection.
422
423
This is useful for implementing [**client-side
424
caching**](https://redis.io/docs/manual/client-side-caching/), where you can
425
subscribe your pub/sub connection to changes on keys.
426
427
If the pub/sub connection is currently disconnected, this function returns
428
`{:error, error}`.
429
430
## Examples
431
432
iex> Redix.PubSub.get_client_id(conn)
433
{:ok, 123}
434
435
"""
436
@doc since: "1.4.0"
437
@spec get_client_id(connection()) :: {:ok, integer()} | {:error, Redix.ConnectionError.t()}
438
def get_client_id(conn) do
439
:gen_statem.call(conn, :get_client_id)
440
end
419
441
end
changed lib/redix/pubsub/connection.ex
 
@@ -13,6 13,7 @@ defmodule Redix.PubSub.Connection do
13
13
:backoff_current,
14
14
:last_disconnect_reason,
15
15
:connected_address,
16
:client_id,
16
17
subscriptions: %{},
17
18
monitors: %{}
18
19
]
 
@@ -20,7 21,7 @@ defmodule Redix.PubSub.Connection do
20
21
@backoff_exponent 1.5
21
22
22
23
@impl true
23
- def callback_mode(), do: :state_functions
24
def callback_mode, do: :state_functions
24
25
25
26
@impl true
26
27
def init(opts) do
 
@@ -28,14 29,14 @@ defmodule Redix.PubSub.Connection do
28
29
data = %__MODULE__{opts: opts, transport: transport}
29
30
30
31
if opts[:sync_connect] do
31
- with {:ok, socket, address} <- Connector.connect(data.opts, _conn_pid = self()),
32
- :ok <- setopts(data, socket, active: :once) do
32
with {:ok, socket, address, client_id} <- connect(data) do
33
33
data = %__MODULE__{
34
34
data
35
35
| socket: socket,
36
36
last_disconnect_reason: nil,
37
37
backoff_current: nil,
38
- connected_address: address
38
connected_address: address,
39
client_id: client_id
39
40
}
40
41
41
42
{:ok, :connected, data}
 
@@ -104,8 105,7 @@ defmodule Redix.PubSub.Connection do
104
105
end
105
106
106
107
def disconnected(:internal, :connect, data) do
107
- with {:ok, socket, address} <- Connector.connect(data.opts, _conn_pid = self()),
108
- :ok <- setopts(data, socket, active: :once) do
108
with {:ok, socket, address, client_id} <- connect(data) do
109
109
:telemetry.execute([:redix, :connection], %{}, %{
110
110
connection: self(),
111
111
connection_name: data.opts[:name],
 
@@ -118,7 118,8 @@ defmodule Redix.PubSub.Connection do
118
118
| socket: socket,
119
119
last_disconnect_reason: nil,
120
120
backoff_current: nil,
121
- connected_address: address
121
connected_address: address,
122
client_id: client_id
122
123
}
123
124
124
125
{:next_state, :connected, data, {:next_event, :internal, :handle_connection}}
 
@@ -193,6 194,11 @@ defmodule Redix.PubSub.Connection do
193
194
{:keep_state, data}
194
195
end
195
196
197
def disconnected({:call, from}, :get_client_id, _data) do
198
reply = {:error, %ConnectionError{reason: :closed}}
199
{:keep_state_and_data, {:reply, from, reply}}
200
end
201
196
202
def connected(:internal, :handle_connection, data) do
197
203
if map_size(data.subscriptions) > 0 do
198
204
case resubscribe_after_reconnection(data) do
 
@@ -224,6 230,10 @@ defmodule Redix.PubSub.Connection do
224
230
end
225
231
end
226
232
233
def connected({:call, from}, :get_client_id, data) do
234
{:keep_state_and_data, {:reply, from, {:ok, data.client_id}}}
235
end
236
227
237
def connected(:info, {transport_closed, socket}, %__MODULE__{socket: socket} = data)
228
238
when transport_closed in [:tcp_closed, :ssl_closed] do
229
239
disconnect(data, transport_closed, _handle_disconnection? = true)
 
@@ -561,6 571,16 @@ defmodule Redix.PubSub.Connection do
561
571
defp key_for_target(:psubscribe, pattern), do: {:pattern, pattern}
562
572
defp key_for_target(:punsubscribe, pattern), do: {:pattern, pattern}
563
573
574
defp connect(%__MODULE__{opts: opts, transport: transport} = data) do
575
timeout = Keyword.fetch!(opts, :timeout)
576
577
with {:ok, socket, address} <- Connector.connect(opts, _conn_pid = self()),
578
{:ok, client_id} <- Connector.sync_command(transport, socket, ["CLIENT", "ID"], timeout),
579
:ok <- setopts(data, socket, active: :once) do
580
{:ok, socket, address, client_id}
581
end
582
end
583
564
584
defp setopts(data, socket, opts) do
565
585
inets_mod(data.transport).setopts(socket, opts)
566
586
end
changed lib/redix/telemetry.ex
 
@@ -123,7 123,7 @@ defmodule Redix.Telemetry do
123
123
124
124
"""
125
125
@spec attach_default_handler() :: :ok | {:error, :already_exists}
126
- def attach_default_handler() do
126
def attach_default_handler do
127
127
events = [
128
128
[:redix, :disconnection],
129
129
[:redix, :connection],
changed mix.exs
 
@@ -5,9 5,9 @@ defmodule Redix.Mixfile do
5
5
6
6
@repo_url "https://github.com/whatyouhide/redix"
7
7
8
- @version "1.3.0"
8
@version "1.4.0"
9
9
10
- def project() do
10
def project do
11
11
[
12
12
app: :redix,
13
13
version: @version,
 
@@ -47,11 47,11 @@ defmodule Redix.Mixfile do
47
47
]
48
48
end
49
49
50
- def application() do
50
def application do
51
51
[extra_applications: [:logger, :ssl]]
52
52
end
53
53
54
- defp package() do
54
defp package do
55
55
[
56
56
maintainers: ["Andrea Leopardi"],
57
57
licenses: ["MIT"],
 
@@ -59,22 59,18 @@ defmodule Redix.Mixfile do
59
59
]
60
60
end
61
61
62
- defp deps() do
62
defp deps do
63
63
[
64
64
{:telemetry, "~> 0.4.0 or ~> 1.0"},
65
65
{:castore, "~> 0.1.0 or ~> 1.0", optional: true},
66
66
{:nimble_options, "~> 0.5.0 or ~> 1.0"},
67
67
68
68
# Dev and test dependencies
69
{:dialyxir, "~> 1.4 and >= 1.4.2", only: [:dev, :test], runtime: false},
69
70
{:ex_doc, "~> 0.28", only: :dev},
70
71
{:excoveralls, "~> 0.17", only: :test},
71
72
{:propcheck, "~> 1.1", only: :test},
72
73
{:stream_data, "~> 0.4", only: [:dev, :test]}
73
- ]
74
- if Version.match?(System.version(), "~> 1.12") do
75
- [{:dialyxir, "~> 1.4", only: [:dev, :test], runtime: false}]
76
- else
77
- []
78
- end
74
]
79
75
end
80
76
end