PubSub does not resubscribe to channel
paveltyk opened this issue · comments
When GenServer restarted, it never gets subscribed to channel again. How can I subscribe to channel again, once it goes to pending_subscriptions
?
:sys.get_state(MyApp.Redix.PubSub)
{:connected,
%Redix.PubSub.Connection{
backoff_current: nil,
connected_address: "localhost:6379",
continuation: nil,
last_disconnect_reason: nil,
monitors: %{#PID<0.565.0> => #Reference<0.2331020780.1358430212.183205>},
opts: [
socket_opts: [],
ssl: false,
sync_connect: false,
backoff_initial: 500,
backoff_max: 30000,
log: [
disconnection: :error,
failed_connection: :error,
reconnection: :info
],
exit_on_disconnection: false,
timeout: 5000,
host: 'localhost',
port: 6379
],
pending_subscriptions: %{{:channel, "my-channel"} => #MapSet<[#PID<0.565.0>]>},
socket: #Port<0.111>,
subscriptions: %{},
transport: :gen_tcp
}}
When my GenServer crashes, the Supervisor restarts it. However, it does not receive messages anymore, and remains in the state as :pending_subscriptions
.
My supervision tree:
application.ex
defmodule MyApp.Application
use Application
def start(_type, _args) do
children = [
%{
id: MyApp.Redix,
start: {Redix, :start_link, [redis_uri, [name: MyApp.Redix]]},
restart: :permanent,
shutdown: 5_000,
type: :worker
},
%{
id: MyApp.Redix.PubSub,
start: {Redix.PubSub, :start_link, [redis_uri, [name: MyApp.Redix.PubSub]]},
restart: :permanent,
shutdown: 5_000,
type: :worker
},
MyApp.SystemPubSub
]
opts = [strategy: :one_for_one, name: MyApp.Supervisor]
Supervisor.start_link(children, opts)
end
end
system_pub_sub.ex
defmodule MyApp.SystemPubSub do
use GenServer
def start_link(_opts) do
GenServer.start_link(__MODULE__, :ok, name: __MODULE__)
end
# Callbacks
@impl true
def init(:ok) do
Redix.PubSub.subscribe(MyApp.Redix.PubSub, @channel, self())
{:ok, :ok}
end
@impl true
def handle_info(:die, state) do
{:ok} = {:error}
{:noreply, state}
end
@impl true
def handle_info({:redix_pubsub, _pubsub, _ref, :subscribed, %{channel: channel}}, state) do
Logger.debug("The pub/sub listener is subscribed to the #{inspect(channel)} channel")
{:noreply, state}
end
@impl true
def handle_info({:redix_pubsub, _pubsub, _ref, :message, %{payload: message}}, state) do
Logger.debug("Received message: #{inspect(message)}")
{:noreply, state}
end
@impl true
def handle_info(_, state) do
{:noreply, state}
end
end
Any advice, please?
Happens to mee to, @whatyouhide what do you think?
Hey @paveltyk, I am not sure about what's going on here. I am not 100% sure I understand what you're doing to get in this situation.
When my GenServer crashes, the Supervisor restarts it. However, it does not receive messages anymore, and remains in the state as :pending_subscriptions.
When you say "When my GenServer crashes" do you mean MyApp.SystemPubSub
? Because if MyApp.SystemPubSub
crashes, Redix is not going to resubscribe it, it will have to resubscribe itself. Otherwise, what do you mean is crashing here?
@whatyouhide Yes, I meant MyApp.SystemPubSub
. So when it crashes, supervisor restarts SystemPubSub
, and it subscribes to a channel in the init
callback. However, if I check MyApp.Redix.PubSub
connection, my process remains in pending_subscriptions
: pending_subscriptions: %{{:channel, "my-channel"} => #MapSet<[#PID<0.565.0>]>},
. Does it make sense?
@whatyouhide I've setup an example project here: https://github.com/paveltyk/pub-sub-issue-132
Yes, it was indeed a bug :) Fixed in master!
cool, thanks @whatyouhide !
@whatyouhide confirm it's working now. One thing to note: GenServer now receive :subscribed
message twice - https://github.com/paveltyk/pub-sub-issue-132/blob/master/lib/pub_sub/my_channel.ex#L20