Current section
17 Versions
Jump to
Current section
17 Versions
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…