Skip to content
This repository has been archived by the owner on Dec 7, 2018. It is now read-only.

Unsubscription impossible because #subscribe blocks #16

Closed
paddor opened this issue Sep 24, 2014 · 3 comments
Closed

Unsubscription impossible because #subscribe blocks #16

paddor opened this issue Sep 24, 2014 · 3 comments

Comments

@paddor
Copy link

paddor commented Sep 24, 2014

Due to the blocking nature of Redis#subscribe, I think it's pretty much impossible to unsubscribe from a subscription channel (except maybe from a subscription callback). Have a look at this code:

require 'celluloid'
require 'celluloid/redis'

class RedisListener
  include Celluloid
  include Celluloid::Logger

  CHANNEL = "updates"

  def initialize(redis)
    @redis = redis
    async.subscribe
  end

  # Subscribes to the channel on and forwards messages them via
  # the broker actor.
  def subscribe
    info "Subscribing to Redis channel #{CHANNEL.inspect} ..."
    @redis.subscribe(CHANNEL) do |on|
      on.message do |channel,msg|
        info "Received message from Redis: #{msg.inspect}"
        Actor[:broker].forward(msg)
      end
    end
  end

  def unsubscribe
    info "unsubscribing from Redis ..."
    @redis.unsubscribe(CHANNEL)
  end
  finalizer :unsubscribe
end

class Broker
  include Celluloid
  include Celluloid::Logger

  def forward(msg)
    info "Forwarding message #{msg.inspect}"
  end
end


Celluloid.register_shutdown

Broker.supervise_as :broker
redis = Redis.new(driver: :celluloid)
RedisListener.supervise_as :redis_listener, redis

warn "sleeping in main thread"
sleep

It starts fine and even prints the "sleeping in main thread" message (which it wouldn't if the call to #subscribe wasn't async. When I hit Ctrl-C to stop the program it tries to terminate the actors cleanly but fails.

I, [2014-09-24T22:43:25.555864 #80670]  INFO -- : Subscribing to Redis channel "updates" ...
sleeping in main thread
^CD, [2014-09-24T22:43:28.035428 #80670] DEBUG -- : Terminating 4 actors...
E, [2014-09-24T22:43:38.036333 #80670] ERROR -- : Couldn't cleanly terminate all actors in 10 seconds!
celluloid-redis.report.rb:51:in `sleep': Interrupt
    from celluloid-redis.report.rb:51:in `<main>'

What's the right way to unsubscribe and cleanly shutdown this actor?

@jduarte
Copy link

jduarte commented Mar 14, 2015

I'm having this exact same issue.
Do you know any way to solve this?

@chriseppstein had this issue as well https://twitter.com/chriseppstein/status/275690390185717762

@tarcieri
Copy link
Member

Has anyone looked into whether the monkeypatch this gem implements still actually works? If it does, this should be fine.

@paddor
Copy link
Author

paddor commented Dec 2, 2015

Any updates on this? Should I close this issue?

Back then, I switched from pub/sub to a simple Redis queue (LPUSH/BRPOP).

@paddor paddor closed this as completed Jan 1, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants