Question

I am trying to use Ruby's daemon gem and loop the restart of a daemon that has its own loop. My code looks like this now:

require 'daemons'

while true
  listener = Daemons.call(:force => true) do
    users = accounts.get_updated_user_list

    TweetStream::Client.new.follow(users) do |status|
      puts "#{status.text}"
    end
  end
  sleep(60)
  listener.restart
end

Running this gives me the following error (after 60 seconds):

undefined method `restart' for #<Daemons::Application:0x007fc5b29f5658> (NoMethodError)

So obviously Daemons.call doesn't return a controllable daemon like I think it does. What do I need to do to set this up correctly. Is a daemon the right tool here?

Was it helpful?

Solution

I think this is what you're after, although I haven't tested it.

class RestartingUserTracker
  def initialize
    @client = TweetStream::Client.new
  end

  def handle_status(status)
    # do whatever it is you're going to do with the status
  end

  def fetch_users
    accounts.get_updated_user_list
  end

  def restart
    @client.stop_stream
    users = fetch_users
    @client.follow(users) do |status|
      handle_status(status)
    end
  end
end

EM.run do
  client = RestartingUserTracker.new
  client.restart

  EM::PeriodicTimer.new(60) do
    client.restart
  end
end

Here's how it works:

TweetStream uses EventMachine internally, as a way of polling the API forever and handling the responses. I can see why you might have felt stuck, because the normal TweetStream API blocks forever and doesn't give you a way to intervene at any point. However, TweetStream does allow you to set up other things in the same event loop. In your case, a timer. I found the documentation on how to do that here: https://github.com/intridea/tweetstream#removal-of-on_interval-callback

By starting up our own EventMachine reactor, we're able to inject our own code into the reactor as well as use TweetStream. In this case, we're using a simple timer that just restarts the client every 60 seconds.

EventMachine is an implementation of something called the Reactor Pattern. If you want to fully understand and maintain this code, it would serve you well to find some resources about it and gain a full understanding. The reactor pattern is very powerful, but can be difficult to grasp at first.

However, this code should get you started. Also, I'd consider renaming the RestartingUserTracker to something more appropriate.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top