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).