lib/ably/realtime/presence/members_map.rb in ably-0.8.1 vs lib/ably/realtime/presence/members_map.rb in ably-0.8.2

- old
+ new

@@ -24,14 +24,10 @@ :in_sync, :failed ) include Ably::Modules::StateEmitter - # Number of absent members to cache internally whilst channel is in sync. - # Cache is unlimited until initial sync is complete ensuring users who have left are never reported as present. - MAX_ABSENT_MEMBER_CACHE = 100 - def initialize(presence) @presence = presence @state = STATE(:initialized) @members = Hash.new @@ -64,18 +60,18 @@ # Get the list of presence members # # @param [Hash,String] options an options Hash to filter members # @option options [String] :client_id optional client_id for the member # @option options [String] :connection_id optional connection_id for the member - # @option options [String] :wait_for_sync defaults to true, if false the get method returns the current list of members and does not wait for the presence sync to complete + # @option options [String] :wait_for_sync defaults to false, if true the get method waits for the initial presence sync following channel attachment to complete before returning the members present # # @yield [Array<Ably::Models::PresenceMessage>] array of present members # # @return [Ably::Util::SafeDeferrable] Deferrable that supports both success (callback) and failure (errback) callbacks # def get(options = {}, &block) - wait_for_sync = options.fetch(:wait_for_sync, true) + wait_for_sync = options.fetch(:wait_for_sync, false) deferrable = Ably::Util::SafeDeferrable.new(logger) result_block = proc do present_members.tap do |members| members.keep_if { |member| member.connection_id == options[:connection_id] } if options[:connection_id] @@ -162,10 +158,14 @@ resume_sync_proc = method(:resume_sync).to_proc connection.on_resume &resume_sync_proc once(:in_sync, :failed) do connection.off_resume &resume_sync_proc end + + once(:in_sync) do + clean_up_absent_members + end end # Trigger a manual SYNC operation to resume member synchronisation from last known cursor position def resume_sync connection.send_protocol_message( @@ -196,20 +196,18 @@ when Ably::Models::PresenceMessage::ACTION.Leave remove_presence_member presence_message else Ably::Exceptions::ProtocolError.new("Protocol error, unknown presence action #{presence_message.action}", 400, 80013) end - - clean_up_absent_members end def ensure_presence_message_is_valid(presence_message) return true if presence_message.connection_id error = Ably::Exceptions::ProtocolError.new("Protocol error, presence message is missing connectionId", 400, 80013) logger.error "PresenceMap: On channel '#{channel.name}' error: #{error}" - channel.trigger :error, error + channel.emit :error, error end # If the message received is older than the last known event for presence # then skip. This can occur during a SYNC operation. For example: # - SYNC starts @@ -232,12 +230,18 @@ presence.emit_message presence_message.action, presence_message end def remove_presence_member(presence_message) logger.debug "#{self.class.name}: Member '#{presence_message.member_key}' removed.\n#{presence_message.to_json}" - members[presence_message.member_key] = { present: false, message: presence_message } - absent_member_cleanup_queue << presence_message.member_key + + if in_sync? + members.delete presence_message.member_key + else + members[presence_message.member_key] = { present: false, message: presence_message } + absent_member_cleanup_queue << presence_message.member_key + end + presence.emit_message presence_message.action, presence_message end def present_members members.select do |key, presence| @@ -254,11 +258,10 @@ presence.fetch(:message) end end def clean_up_absent_members - return unless sync_complete? - members.delete absent_member_cleanup_queue.shift until absent_member_cleanup_queue.count <= MAX_ABSENT_MEMBER_CACHE + members.delete absent_member_cleanup_queue.shift end end end end