lib/mongo/cluster.rb in mongo-2.13.0.beta1 vs lib/mongo/cluster.rb in mongo-2.13.0.rc1

- old
+ new

@@ -393,11 +393,11 @@ # # @return [ Array<Server> ] The candidate servers. # # @since 2.0.0 def servers - topology.servers(servers_list.compact).compact + topology.servers(servers_list) end # The addresses in the cluster. # # @example Get the addresses in the cluster. @@ -597,15 +597,18 @@ # @option options [ true | false ] :keep_connection_pool Usually when the # new server description is unknown, the connection pool on the # respective server is cleared. Set this option to true to keep the # existing connection pool (required when handling not master errors # on 4.2+ servers). + # @option aptions [ true | false ] :awaited Whether the updated description + # was a result of processing an awaited ismaster. # # @api private def run_sdam_flow(previous_desc, updated_desc, options = {}) @sdam_flow_lock.synchronize do - flow = SdamFlow.new(self, previous_desc, updated_desc) + flow = SdamFlow.new(self, previous_desc, updated_desc, + awaited: options[:awaited]) flow.server_description_changed # SDAM flow may alter the updated description - grab the final # version for the purposes of broadcasting if a server is available updated_desc = flow.updated_desc @@ -884,38 +887,55 @@ Monitoring::Event::ServerClosed.new(server.address, topology) ) end end - # Returns whether the deployment that the driver is connected to supports - # sessions. + # Raises Error::SessionsNotAvailable if the deployment that the driver + # is connected to does not support sessions. # # Session support may change over time, for example due to servers in the - # deployment being upgraded or downgraded. This method returns the - # current information if the client is connected to at least one data - # bearing server. If the client is currently not connected to any data - # bearing servers, this method returns the last known value for whether - # the deployment supports sessions. + # deployment being upgraded or downgraded. If the client is currently not + # connected to any data bearing servers, this method considers the state + # of session support as of when the client was last connected to at + # least one server. If the client has never connected to any servers, + # the deployment is considered to not support sessions. # - # @return [ true | false ] Whether deployment supports sessions. # @api private - def sessions_supported? - if topology.data_bearing_servers? - return !!topology.logical_session_timeout + def validate_session_support! + @state_change_lock.synchronize do + @sdam_flow_lock.synchronize do + if topology.data_bearing_servers? + unless topology.logical_session_timeout + raise_sessions_not_supported + end + end + end end # No data bearing servers known - perform server selection to try to # get a response from at least one of them, to return an accurate # assessment of whether sessions are currently supported. begin ServerSelector.get(mode: :primary_preferred).select_server(self) - !!topology.logical_session_timeout + @state_change_lock.synchronize do + @sdam_flow_lock.synchronize do + unless topology.logical_session_timeout + raise_sessions_not_supported + end + end + end rescue Error::NoServerAvailable # We haven't been able to contact any servers - use last known - # value for esssion support. - @update_lock.synchronize do - @sessions_supported || false + # value for session support. + @state_change_lock.synchronize do + @sdam_flow_lock.synchronize do + @update_lock.synchronize do + unless @sessions_supported + raise_sessions_not_supported + end + end + end end end end private @@ -949,9 +969,25 @@ if @srv_monitor @srv_monitor.stop! end end end + end + + def raise_sessions_not_supported + # Intentionally using @servers instead of +servers+ here because we + # are supposed to be already holding the @update_lock and we cannot + # recursively acquire it again. + offending_servers = @servers.select do |server| + server.description.data_bearing? && server.logical_session_timeout.nil? + end + reason = if offending_servers.empty? + "There are no known data bearing servers (current seeds: #{@servers.map(&:address).map(&:seed).join(', ')})" + else + "The following servers have null logical session timeout: #{offending_servers.map(&:address).map(&:seed).join(', ')}" + end + msg = "The deployment that the driver is connected to does not support sessions: #{reason}" + raise Error::SessionsNotSupported, msg end end end require 'mongo/cluster/sdam_flow'