Current section

17 Versions

Jump to

Compare versions

7 files changed
+167 additions
-207 deletions
  @@ -1,59 +1,5 @@
1 1 # Changelog
2 2
3 - ## master
3 + ## v3.0.0 (2020-04-14)
4 4
5 - ## v2.1.8 (2020-1-30)
6 -
7 - * Enhancements
8 - * Allow passing :socket_opts to redix
9 -
10 - ## v2.1.7 (2018-3-28)
11 -
12 - * Bug fixes
13 - * Fix incorrect error structure on :disconnected
14 -
15 - ## v2.1.6 (2018-3-4)
16 -
17 - * Enhancements
18 - * Allow passing :ssl option to redix
19 -
20 - ## v2.1.5 (2018-1-2)
21 -
22 - * Enhancements
23 - * Update redix and redix\_pubsub versions
24 -
25 - ## v2.1.4 (2017-10-9)
26 -
27 - * Enhancements
28 - * Update redix and redix\_pubsub versions
29 -
30 - ## v2.1.3 (2017-2-21)
31 -
32 - * Bug fixes
33 - * Handle disconnected Redis connections
34 -
35 - ## v2.1.2 (2016-7-7)
36 -
37 - * Bug fixes
38 - * Fix fastlane options being discarded
39 -
40 -
41 - ## v2.1.1 (2016-7-7)
42 -
43 - * Bug fixes
44 - * Fix bad use of Keyword.merge
45 -
46 - ## v2.1.0 (2016-7-5)
47 -
48 - * Enhancements
49 - * Support Phoenix 1.2
50 - * Replace `:eredis` with `Redix`
51 -
52 - ## v1.0.0 (2015-9-1)
53 -
54 - * Enhancements
55 - * A redis `:url` can now be given as a configuration option
56 -
57 - * Bug fixes
58 - * Establish optimistic connection on init to fix startup race conditions
59 - * Fix compounding reconnects if redis server is offline
5 + * Depend on Phoenix.PubSub v2.0
  @@ -23,7 +23,7 @@ config :my_app, MyApp.Endpoint,
23 23 Config Options
24 24
25 25 Option | Description | Default |
26 - :--------------|------------------------------------------------------------------------|----------------|
26 + :--------------| :--------------------------------------------------------------------- | :------------- |
27 27 `:name` | The required name to register the PubSub processes, ie: `MyApp.PubSub` | |
28 28 `:node_name` | The required name of the node, ie: `System.get_env("NODE")` | |
29 29 `:url` | The redis-server URL, ie: `redis://username:password@host:port` | |
  @@ -1,15 +1,15 @@
1 1 {<<"app">>,<<"phoenix_pubsub_redis">>}.
2 2 {<<"build_tools">>,[<<"mix">>]}.
3 3 {<<"description">>,<<"The Redis PubSub adapter for the Phoenix framework">>}.
4 - {<<"elixir">>,<<"~> 1.0">>}.
4 + {<<"elixir">>,<<"~> 1.6">>}.
5 5 {<<"files">>,
6 - [<<"lib">>,<<"lib/phoenix_pubsub_redis.ex">>,<<"lib/phoenix_pubsub_redis">>,
6 + [<<"lib">>,<<"lib/phoenix_pubsub_redis">>,
7 7 <<"lib/phoenix_pubsub_redis/redis_server.ex">>,
8 8 <<"lib/phoenix_pubsub_redis/redis.ex">>,<<"mix.exs">>,<<"README.md">>,
9 9 <<"CHANGELOG.md">>]}.
10 10 {<<"licenses">>,[<<"MIT">>]}.
11 11 {<<"links">>,
12 - [{<<"github">>,
12 + [{<<"GitHub">>,
13 13 <<"https://github.com/phoenixframework/phoenix_pubsub_redis">>}]}.
14 14 {<<"name">>,<<"phoenix_pubsub_redis">>}.
15 15 {<<"requirements">>,
  @@ -17,15 +17,15 @@
17 17 {<<"name">>,<<"phoenix_pubsub">>},
18 18 {<<"optional">>,false},
19 19 {<<"repository">>,<<"hexpm">>},
20 - {<<"requirement">>,<<"~> 1.0">>}],
20 + {<<"requirement">>,<<"~> 2.0">>}],
21 21 [{<<"app">>,<<"redix">>},
22 22 {<<"name">>,<<"redix">>},
23 23 {<<"optional">>,false},
24 24 {<<"repository">>,<<"hexpm">>},
25 - {<<"requirement">>,<<"~> 0.9.0">>}],
25 + {<<"requirement">>,<<"~> 0.10.0">>}],
26 26 [{<<"app">>,<<"poolboy">>},
27 27 {<<"name">>,<<"poolboy">>},
28 28 {<<"optional">>,false},
29 29 {<<"repository">>,<<"hexpm">>},
30 30 {<<"requirement">>,<<"~> 1.5.1 or ~> 1.6">>}]]}.
31 - {<<"version">>,<<"2.1.8">>}.
31 + {<<"version">>,<<"3.0.0">>}.
  @@ -1,2 +0,0 @@
1 - defmodule PhoenixPubsubRedis do
2 - end
  @@ -1,14 +1,13 @@
1 1 defmodule Phoenix.PubSub.Redis do
2 - use Supervisor
3 -
4 2 @moduledoc """
5 3 Phoenix PubSub adapter based on Redis.
6 4
7 - To use Redis as your PubSub adapter, simply add it to your Endpoint's config:
5 + To start it, list it in your supervision tree as:
8 6
9 - config :my_app, MyApp.Endpoint,
10 - pubsub: [adapter: Phoenix.PubSub.Redis,
11 - host: "192.168.1.100", node_name: System.get_env("NODE")]
7 + {Phoenix.PubSub,
8 + adapter: Phoenix.PubSub.Redis,
9 + host: "192.168.1.100",
10 + node_name: System.get_env("NODE")}
12 11
13 12 You will also need to add `:phoenix_pubsub_redis` to your deps:
14 13
  @@ -16,13 +15,6 @@ defmodule Phoenix.PubSub.Redis do
16 15 [{:phoenix_pubsub_redis, "~> 2.1.0"}]
17 16 end
18 17
19 - And also add `:phoenix_pubsub_redis` to your list of applications:
20 -
21 - def application do
22 - [mod: {MyApp, []},
23 - applications: [..., :phoenix, :phoenix_pubsub_redis]]
24 - end
25 -
26 18 ## Options
27 19
28 20 * `:url` - The url to the redis server ie: `redis://username:password@host:port`
  @@ -33,74 +25,81 @@ defmodule Phoenix.PubSub.Redis do
33 25 * `:password` - The redis-server password, defaults `""`
34 26 * `:ssl` - The redis-server ssl option, defaults `false`
35 27 * `:redis_pool_size` - The size of the redis connection pool. Defaults `5`
36 - * `:pool_size` - Both the size of the local pubsub server pool and subscriber
37 - shard size. Defaults `1`. A single pool is often enough for most use-cases,
38 - but for high subscriber counts on a single topic or greater than 1M
39 - clients, a pool size equal to the number of schedulers (cores) is a well
40 - rounded size.
41 28 * `:socket_opts` - List of options that are passed to the network layer when connecting to the Redis server. Default `[]`
42 29
43 30 """
44 31
32 + use Supervisor
33 +
34 + @behaviour Phoenix.PubSub.Adapter
45 35 @redis_pool_size 5
36 + @redis_opts [:host, :port, :password, :database, :ssl, :socket_opts]
46 37 @defaults [host: "127.0.0.1", port: 6379]
47 38
39 + ## Adapter callbacks
48 40
49 - def start_link(name, opts) do
50 - supervisor_name = Module.concat(name, Supervisor)
51 - Supervisor.start_link(__MODULE__, [name, opts], name: supervisor_name)
52 - end
41 + @impl true
42 + defdelegate node_name(adapter_name),
43 + to: Phoenix.PubSub.RedisServer
44 +
45 + @impl true
46 + defdelegate broadcast(adapter_name, topic, message, dispatcher),
47 + to: Phoenix.PubSub.RedisServer
48 +
49 + @impl true
50 + defdelegate direct_broadcast(adapter_name, node_name, topic, message, dispatcher),
51 + to: Phoenix.PubSub.RedisServer
52 +
53 + ## GenServer callbacks
53 54
54 55 @doc false
55 - def init([server_name, opts]) do
56 - pool_size = Keyword.fetch!(opts, :pool_size)
56 + def start_link(opts) do
57 + adapter_name = Keyword.fetch!(opts, :adapter_name)
58 + supervisor_name = Module.concat(adapter_name, "Supervisor")
59 + Supervisor.start_link(__MODULE__, opts, name: supervisor_name)
60 + end
61 +
62 + @impl true
63 + def init(opts) do
64 + pubsub_name = Keyword.fetch!(opts, :name)
65 + adapter_name = Keyword.fetch!(opts, :adapter_name)
57 66
58 67 opts = handle_url_opts(opts)
59 68 opts = Keyword.merge(@defaults, opts)
60 - redis_opts = Keyword.take(opts, [:host, :port, :password, :database, :ssl])
69 + redis_opts = Keyword.take(opts, @redis_opts)
70 +
71 + node_name = opts[:node_name] || node()
72 + validate_node_name!(node_name)
73 +
74 + :ets.new(adapter_name, [:public, :named_table, read_concurrency: true])
75 + :ets.insert(adapter_name, {:node_name, node_name})
61 76
62 - pool_name = Module.concat(server_name, Pool)
63 - namespace = redis_namespace(server_name)
64 - node_ref = :crypto.strong_rand_bytes(24)
65 - node_name = validate_node_name!(opts)
66 - fastlane = opts[:fastlane]
67 - server_opts = Keyword.merge(opts, name: server_name,
68 - server_name: server_name,
69 - pool_name: pool_name,
70 - namespace: namespace,
71 - node_ref: node_ref)
72 77 pool_opts = [
73 - name: {:local, pool_name},
78 + name: {:local, adapter_name},
74 79 worker_module: Redix,
75 80 size: opts[:redis_pool_size] || @redis_pool_size,
76 81 max_overflow: 0
77 82 ]
78 83
79 - dispatch_rules = [{:broadcast, Phoenix.PubSub.RedisServer, [fastlane, pool_name, pool_size, namespace, node_ref]},
80 - {:direct_broadcast, Phoenix.PubSub.RedisServer, [fastlane, pool_name, pool_size, namespace, node_ref]},
81 - {:node_name, __MODULE__, [node_name]}]
82 -
83 84 children = [
84 - supervisor(Phoenix.PubSub.LocalSupervisor, [server_name, pool_size, dispatch_rules]),
85 - worker(Phoenix.PubSub.RedisServer, [server_opts]),
86 - :poolboy.child_spec(pool_name, pool_opts, redis_opts),
85 + {Phoenix.PubSub.RedisServer, {pubsub_name, adapter_name, node_name, redis_opts}},
86 + :poolboy.child_spec(adapter_name, pool_opts, redis_opts)
87 87 ]
88 88
89 - supervise children, strategy: :rest_for_one
89 + Supervisor.init(children, strategy: :rest_for_one)
90 90 end
91 91
92 - defp redis_namespace(server_name), do: "phx:#{server_name}"
93 -
94 92 defp handle_url_opts(opts) do
95 93 if opts[:url] do
96 - do_handle_url_opts(opts)
94 + merge_url_opts(opts)
97 95 else
98 96 opts
99 97 end
100 98 end
101 99
102 - defp do_handle_url_opts(opts) do
100 + defp merge_url_opts(opts) do
103 101 info = URI.parse(opts[:url])
102 +
104 103 user_opts =
105 104 case String.split(info.userinfo || "", ":") do
106 105 [""] -> []
  @@ -113,16 +112,11 @@ defmodule Phoenix.PubSub.Redis do
113 112 |> Keyword.merge(host: info.host, port: info.port || @defaults[:port])
114 113 end
115 114
116 - @doc false
117 - def node_name(nil), do: node()
118 - def node_name(configured_name), do: configured_name
119 -
120 -
121 - defp validate_node_name!(opts) do
122 - case opts[:node_name] || node() do
123 - name when name in [nil, :nonode@nohost] ->
115 + defp validate_node_name!(node_name) do
116 + if node_name in [nil, :nonode@nohost] do
124 117 raise ArgumentError, ":node_name is a required option for unnamed nodes"
125 - name -> name
126 - end
118 + end
119 +
120 + :ok
127 121 end
128 122 end
Loading more files…