def build_packet(kind, type, payload, target, options = {}, &callback)
      validate_target(target, kind == :send_push)
      if kind == :send_push
        packet = Push.new(type, payload)
        packet.selector = target[:selector] || :any if target.is_a?(Hash)
        packet.persistent = true
        packet.confirm = true if callback
        time_to_live = options[:time_to_live] || 0
      else
        packet = Request.new(type, payload)
        packet.selector = :any
        time_to_live = options[:time_to_live] || @options[:time_to_live]
      end
      packet.from = @identity
      packet.token = options[:token] || RightSupport::Data::UUID.generate
      packet.expires_at = Time.now.to_i + time_to_live if time_to_live && time_to_live > 0
      if target.is_a?(Hash)
        if (agent_id = target[:agent_id])
          packet.target = agent_id
        else
          packet.tags = target[:tags] || []
          packet.scope = target[:scope]
        end
      else
        packet.target = target
      end

      if queueing?
        @offline_handler.queue_request(kind, type, payload, target, packet.token, packet.expires_at, packet.skewed_by, &callback)
        nil
      else
        packet
      end
    end
def build_packet(kind, type, payload, target, options = {}, &callback)
      validate_target(target, kind == :send_push)
      if kind == :send_push
        packet = Push.new(type, payload)
        packet.selector = target[:selector] || :any if target.is_a?(Hash)
        packet.persistent = true
        packet.confirm = true if callback
        time_to_live = options[:time_to_live] || 0
      else
        packet = Request.new(type, payload)
        packet.selector = :any
        time_to_live = options[:time_to_live] || @options[:time_to_live]
      end
      packet.from = @identity
      packet.token = options[:token] || RightSupport::Data::UUID.generate
      packet.expires_at = Time.now.to_i + time_to_live if time_to_live && time_to_live > 0
      if target.is_a?(Hash)
        if (agent_id = target[:agent_id])
          packet.target = agent_id
        else
          packet.tags = target[:tags] || []
          packet.scope = target[:scope]
        end
      else
        packet.target = target
      end

      if queueing?
        @offline_handler.queue_request(kind, type, payload, target, packet.token, packet.expires_at, packet.skewed_by, &callback)
        nil
      else
        packet
      end
    end
Build packet or queue it if offline

 === Parameters
 kind(Symbol):: Kind of request: :send_push or :send_request
 type(String):: Dispatch route for the request; typically identifies actor and action
 payload(Object):: Data to be sent with marshalling en route
 target(Hash|NilClass):: Target for request
   :agent_id(String):: Identity of specific target
   :tags(Array):: Tags that must all be associated with a target for it to be selected
   :scope(Hash):: Scoping to be used to restrict routing
     :account(Integer):: Restrict to agents with this account id
     :shard(Integer):: Restrict to agents with this shard id, or if value is Packet::GLOBAL,
       ones with no shard id
   :selector(Symbol):: Which of the matched targets to be selected: :any or :all
 options(Hash):: Request options
   :token(String):: Universally unique ID for request; defaults to random generated
   :time_to_live(Numeric):: Number of seconds before a request expires and is to be ignored;
     non-positive value or nil means never expire for :send_push and means use configured
     time-to-live for :send_request

 === Block
 Optional block used to process response asynchronously with the following parameter:
   result(Result):: Response with an OperationResult of SUCCESS, RETRY, NON_DELIVERY, or ERROR

 === Return
 (Push|Request|NilClass):: Packet created, or nil if queued instead

 === Raise
 ArgumentError:: If target is invalid