def publish(exchange, packet, options = {})
      identities = []
      no_serialize = options[:no_serialize] || @serializer.nil?
      message = if no_serialize then packet else @serializer.dump(packet) end
      brokers = use(options)
      brokers.each do |b|
        if b.publish(exchange, packet, message, options.merge(:no_serialize => no_serialize))
          identities << b.identity
          if options[:mandatory] && !no_serialize
            context = Context.new(packet, options, brokers.map { |b| b.identity })
            @published.store(message, context)
          end
          break unless options[:fanout]
        end
      end
      if identities.empty?
        selected = "selected " if options[:brokers]
        list = aliases(brokers.map { |b| b.identity }).join(", ")
        raise NoConnectedBrokers, "None of #{selected}brokers [#{list}] are usable for publishing"
      end
      identities
    end
def publish(exchange, packet, options = {})
      identities = []
      no_serialize = options[:no_serialize] || @serializer.nil?
      message = if no_serialize then packet else @serializer.dump(packet) end
      brokers = use(options)
      brokers.each do |b|
        if b.publish(exchange, packet, message, options.merge(:no_serialize => no_serialize))
          identities << b.identity
          if options[:mandatory] && !no_serialize
            context = Context.new(packet, options, brokers.map { |b| b.identity })
            @published.store(message, context)
          end
          break unless options[:fanout]
        end
      end
      if identities.empty?
        selected = "selected " if options[:brokers]
        list = aliases(brokers.map { |b| b.identity }).join(", ")
        raise NoConnectedBrokers, "None of #{selected}brokers [#{list}] are usable for publishing"
      end
      identities
    end
Publish message to AMQP exchange of first connected broker

 === Parameters
 exchange(Hash):: AMQP exchange to subscribe to with keys :type, :name, and :options,
   which are the standard AMQP ones plus
     :no_declare(Boolean):: Whether to skip declaring this exchange or queue on the broker
       to cause its creation; for use when client does not have create permission or
       knows the object already exists and wants to avoid declare overhead
     :declare(Boolean):: Whether to delete this exchange or queue from the AMQP cache
       to force it to be declared on the broker and thus be created if it does not exist
 packet(Packet):: Message to serialize and publish
 options(Hash):: Publish options -- standard AMQP ones plus
   :mandatory(Boolean):: Return message if the exchange does not have any associated queues
     or if all the associated queues do not have any consumers
   :immediate(Boolean):: Return message for the same reasons as :mandatory plus if all
     of the queues associated with the exchange are not immediately ready to consume the message
   :fanout(Boolean):: true means publish to all connected brokers
   :brokers(Array):: Identity of brokers selected for use, defaults to all brokers
     if nil or empty
   :order(Symbol):: Broker selection order: :random or :priority,
     defaults to @select if :brokers is nil, otherwise defaults to :priority
   :no_serialize(Boolean):: Do not serialize packet because it is already serialized,
     this is an escape for special situations like enrollment, also implicitly disables
     publish logging; this option is implicitly invoked if initialize without a serializer
   :log_filter(Array(Symbol)):: Filters to be applied in to_s when logging packet to :info
   :log_data(String):: Additional data to display at end of log entry
   :no_log(Boolean):: Disable publish logging unless debug level

 === Return
 identities(Array):: Identity of brokers where packet was successfully published

 === Raise
 NoConnectedBrokers:: If cannot find a connected broker