lib/xmpp4r/robot.rb in xmpp4r-robot-0.2.0 vs lib/xmpp4r/robot.rb in xmpp4r-robot-0.2.1

- old
+ new

@@ -1,7 +1,8 @@ require 'set' +require 'thread' require 'xmpp4r' require 'xmpp4r/roster' class Jabber::Robot @@ -16,10 +17,13 @@ :away => Set.new, :unavailable => Set.new} @retry_time = Float(opts[:retry_time] || 0) @auto_accept_subscription = opts[:auto_accept_subscription] + + @roster_mutex = Mutex.new + @helper_mutex = Mutex.new end def inspect "#<#{self.class.name} username=#{username.inspect}>" end @@ -30,19 +34,23 @@ def helper @helper ||= Jabber::Roster::Helper.new(client, false) end + # Start the robot. This is not thread safe. + # + # @api public def start if @client # restart stop @client = nil end initialize_callbacks connect login available + roster self end def stop client.close @@ -122,11 +130,11 @@ private def initialize_callbacks client.on_exception do |exp| errback.call(exp) if errback - next unless retry_time == 0.0 + next if retry_time == 0.0 $stderr.puts "ERROR: #{exp}: #{exp.backtrace}" + " We'll sleep for #{retry_time} seconds and retry." sleep(retry_time) start @@ -138,17 +146,19 @@ end false end notify_presence do |jid, status| - @roster[:unknown].delete(jid) if @roster[:unknown] + @roster_mutex.synchronize do + @roster[:unknown].delete(jid) if @roster[:unknown] - [:available, :away, :unavailable].each do |type| - if type == status - @roster[type].add(jid) - else - @roster[type].delete(jid) + [:available, :away, :unavailable].each do |type| + if type == status + @roster[type].add(jid) + else + @roster[type].delete(jid) + end end end end end @@ -161,15 +171,19 @@ rescue => e errback.call(e) if errback end def sync_roster - clear_roster_semaphore - helper.get_roster - helper.wait_for_roster - @roster[:unknown] = - Set.new(helper.items.keys.map(&method(:jid_to_username))) - - @roster[:available] - @roster[:away] - @roster[:unavailable] + @helper_mutex.synchronize do + clear_roster_semaphore + helper.get_roster + helper.wait_for_roster + end + @roster_mutex.synchronize do + @roster[:unknown] = + Set.new(helper.items.keys.map(&method(:jid_to_username))) - + @roster[:available] - @roster[:away] - @roster[:unavailable] + end end # a hack to let us always get the latest roster def clear_roster_semaphore helper.instance_variable_get(:@roster_wait).