# encoding: utf-8 module Moped module Operation # Represents a read from the database that is executed on a specific node # determined by a read preference. # # @since 2.0.0 class Read # @!attribute database # @return [ String ] The database the read is from. # @!attribute operation # @return [ Protocol::Query, Protocol::GetMore, Protocol::Command ] # The read operation. attr_reader :database, :operation # Instantiate the read operation. # # @example Instantiate the read. # Read.new(get_more) # # @param [ Protocol::Query, Protocol::GetMore, Protocol::Command ] operation # The read operation. # # @since 2.0.0 def initialize(operation) @operation = operation @database = operation.database end # Execute the read operation on the provided node. If the query failed, we # will check if the failure was due to authorization and attempt the # operation again. This could sometimes happen in the case of a step down # or reconfiguration on the server side. # # @example Execute the operation. # read.execute(node) # # @param [ Node ] node The node to execute the read on. # # @raise [ Failure ] If the read operation failed. # # @return [ Protocol::Reply ] The reply from the database. # # @since 2.0.0 def execute(node) node.process(operation) do |reply| # Avoid LocalJumpError ret = nil if reply.unauthorized? && node.credentials.key?(@database) node.connection do |conn| username, password = node.credentials[@database] if username && password conn.login(operation.database, username, password) ret = execute(node) end end end if ret.nil? if operation.failure?(reply) raise operation.failure_exception(reply) end ret = operation.results(reply) end ret end end end end end