Skip to content

Commit 2db952e

Browse files
committed
Force invalid types to binary terms when routing
1 parent 15504b9 commit 2db952e

7 files changed

Lines changed: 42 additions & 17 deletions

File tree

lib/cachex/router.ex

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,17 @@ defmodule Cachex.Router do
2727
2828
Please see all child implementations for supported options.
2929
"""
30-
@callback init(cache :: Cachex.t(), options :: Keyword.t()) :: any
30+
@callback init(cache :: Cachex.t(), options :: Keyword.t()) :: any()
3131

3232
@doc """
3333
Retrieve the list of nodes from a routing state.
3434
"""
35-
@callback nodes(state :: any) :: [atom]
35+
@callback nodes(state :: any()) :: [atom()]
3636

3737
@doc """
3838
Route a key to a node in a routing state.
3939
"""
40-
@callback route(state :: any, key :: any) :: atom
40+
@callback route(state :: any(), key :: any()) :: atom()
4141

4242
@doc """
4343
Create a child specification to back a routing state.
@@ -74,22 +74,22 @@ defmodule Cachex.Router do
7474
@doc """
7575
Retrieve all currently connected nodes (including this one).
7676
"""
77-
@spec connected() :: [atom]
77+
@spec connected() :: [atom()]
7878
def connected(),
7979
do: [node() | :erlang.nodes(:connected)]
8080

8181
@doc """
8282
Retrieve all routable nodes for a cache.
8383
"""
84-
@spec nodes(cache :: Cachex.t()) :: {:ok, [atom]}
84+
@spec nodes(cache :: Cachex.t()) :: {:ok, [atom()]}
8585
def nodes(cache(router: router(module: module, state: state))),
8686
do: {:ok, module.nodes(state)}
8787

8888
@doc """
8989
Executes a previously dispatched action..
9090
"""
9191
# The first match short circuits local-only caches
92-
@spec route(Cachex.t(), atom, {atom, [any]}) :: any
92+
@spec route(Cachex.t(), atom(), {atom(), [any()]}) :: any()
9393
def route(cache(router: router(module: Router.Local)) = cache, module, call),
9494
do: route_local(cache, module, call)
9595

lib/cachex/router/jump.ex

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ defmodule Cachex.Router.Jump do
2929
by using `Node.self/0` and `Node.list/1`.
3030
3131
"""
32-
@spec init(cache :: Cachex.t(), options :: Keyword.t()) :: [atom]
32+
@spec init(cache :: Cachex.t(), options :: Keyword.t()) :: [atom()]
3333
def init(_cache, options) do
3434
options
3535
|> Keyword.get_lazy(:nodes, &Router.connected/0)
@@ -40,14 +40,14 @@ defmodule Cachex.Router.Jump do
4040
@doc """
4141
Retrieve the list of nodes from a jump hash routing state.
4242
"""
43-
@spec nodes(nodes :: [atom]) :: [atom]
43+
@spec nodes(nodes :: [atom()]) :: [atom()]
4444
def nodes(nodes),
4545
do: nodes
4646

4747
@doc """
4848
Route a key to a node in a jump hash routing state.
4949
"""
50-
@spec route(nodes :: [atom], key :: any) :: atom
50+
@spec route(nodes :: [atom()], key :: any) :: atom()
5151
def route(nodes, key) do
5252
slot =
5353
key

lib/cachex/router/local.ex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@ defmodule Cachex.Router.Local do
1010
@doc """
1111
Retrieve the list of nodes from a local routing state.
1212
"""
13-
@spec nodes(state :: nil) :: [atom]
13+
@spec nodes(state :: nil) :: [atom()]
1414
def nodes(_state),
1515
do: [node()]
1616

1717
@doc """
1818
Route a key to a node in a local routing state.
1919
"""
20-
@spec route(state :: nil, key :: any) :: atom
20+
@spec route(state :: nil, key :: any()) :: atom()
2121
def route(_state, _key),
2222
do: node()
2323
end

lib/cachex/router/mod.ex

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ defmodule Cachex.Router.Mod do
2626
by using `Node.self/0` and `Node.list/1`.
2727
2828
"""
29-
@spec init(cache :: Cachex.t(), options :: Keyword.t()) :: [atom]
29+
@spec init(cache :: Cachex.t(), options :: Keyword.t()) :: [atom()]
3030
def init(_cache, options) do
3131
options
3232
|> Keyword.get_lazy(:nodes, &Router.connected/0)
@@ -37,14 +37,14 @@ defmodule Cachex.Router.Mod do
3737
@doc """
3838
Retrieve the list of nodes from a modulo routing state.
3939
"""
40-
@spec nodes(nodes :: [atom]) :: [atom]
40+
@spec nodes(nodes :: [atom()]) :: [atom()]
4141
def nodes(nodes),
4242
do: Enum.sort(nodes)
4343

4444
@doc """
4545
Route a key to a node in a modulo routing state.
4646
"""
47-
@spec route(nodes :: [atom], key :: any) :: atom
47+
@spec route(nodes :: [atom()], key :: any()) :: atom()
4848
def route(nodes, key) do
4949
slot =
5050
key

lib/cachex/router/ring.ex

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ defmodule Cachex.Router.Ring do
6666
@doc """
6767
Retrieve the list of nodes from a ring routing state.
6868
"""
69-
@spec nodes(ring :: Ring.t()) :: {:ok, [atom]}
69+
@spec nodes(ring :: Ring.t()) :: {:ok, [atom()]}
7070
def nodes(ring) do
7171
with {:ok, nodes} <- Ring.get_nodes(ring) do
7272
nodes
@@ -76,8 +76,14 @@ defmodule Cachex.Router.Ring do
7676
@doc """
7777
Route a key to a node in a ring routing state.
7878
"""
79-
@spec route(ring :: Ring.t(), key :: any) :: {:ok, atom}
79+
@spec route(ring :: Ring.t(), key :: any()) :: {:ok, atom()}
8080
def route(ring, key) do
81+
key =
82+
case String.Chars.impl_for(key) do
83+
nil -> :erlang.term_to_binary(key)
84+
_na -> key
85+
end
86+
8187
with {:ok, node} <- Ring.find_node(ring, key) do
8288
node
8389
end

mix.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ defmodule Cachex.Mixfile do
100100
[
101101
# Production dependencies
102102
{:eternal, "~> 1.2"},
103-
{:ex_hash_ring, "~> 6.0"},
103+
{:ex_hash_ring, "~> 7.0"},
104104
{:jumper, "~> 1.0"},
105105
{:sleeplocks, "~> 1.1"},
106106
{:unsafe, "~> 1.0"},

test/cachex/router/ring_test.exs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,25 @@ defmodule Cachex.Router.RingTest do
2020
assert Cachex.Router.Ring.route(state, "erlang") in nodes
2121
end
2222

23+
test "routing keys via a ring router with no protocol" do
24+
# create a test cache cluster for nodes
25+
{cache, nodes, _cluster} =
26+
TestUtils.create_cache_cluster(3,
27+
router: Cachex.Router.Ring
28+
)
29+
30+
# convert the name to a cache and sort
31+
cache = Services.Overseer.lookup(cache)
32+
33+
# fetch the router state after initialize
34+
cache(router: router(state: state)) = cache
35+
36+
# test that we can route to expected nodes
37+
assert Cachex.Router.nodes(cache) == {:ok, nodes}
38+
assert Cachex.Router.Ring.route(state, {"elixir"}) in nodes
39+
assert Cachex.Router.Ring.route(state, {"erlang"}) in nodes
40+
end
41+
2342
test "routing keys via a ring router with defined nodes" do
2443
# create a test cache cluster for nodes
2544
{cache, _nodes, _cluster} =

0 commit comments

Comments
 (0)