class Diplomat::Event

Methods for interacting with the Consul event API endpoint

Public Instance Methods

fire(name, value = nil, service = nil, node = nil, tag = nil, dc = nil, options = {}) click to toggle source

Send an event @param name [String] the event name @param value [String] the payload of the event @param service [String] the target service name @param node [String] the target node name @param tag [String] the target tag name, must only be used with service @param dc [String] the dc to target @param options [Hash] options parameter hash @return [nil] rubocop:disable Metrics/ParameterLists

# File lib/diplomat/event.rb, line 18
def fire(name, value = nil, service = nil, node = nil, tag = nil, dc = nil, options = {})
  custom_params = []
  custom_params << use_named_parameter('service', service) if service
  custom_params << use_named_parameter('node', node) if node
  custom_params << use_named_parameter('tag', tag) if tag
  custom_params << use_named_parameter('dc', dc) if dc

  send_put_request(@conn, ["/v1/event/fire/#{name}"], options, value, custom_params)
  nil
end
get(name = nil, token = :last, not_found = :wait, found = :return, options = {}) click to toggle source

Get a specific event in the sequence matching name @param name [String] the name of the event (regex) @param token [String|Symbol] the ordinate of the event in the sequence;

String are tokens returned by previous calls to this function
Symbols are the special tokens :first, :last, and :next

@param not_found [Symbol] behaviour if there is no matching event;

:reject with exception, :return degenerate value, or :wait for event

@param found [Symbol] behaviour if there is a matching event;

:reject with exception, or :return its current value

@return [hash] A hash with keys :value and :token;

:value is a further hash of the :name and :payload of the event,
:token is the event's ordinate in the sequence and can be passed to future calls to get the subsequent event

@param options [Hash] options parameter hash @note

Whereas the consul API for events returns all past events that match
name, this method allows retrieval of individual events from that
sequence. However, because consul's API isn't conducive to this, we can
offer first, last, next (last + 1) events, or arbitrary events in the
middle, though these can only be identified relative to the preceding
event. However, this is ideal for iterating through the sequence of
events (while being sure that none are missed).

rubocop:disable Metrics/PerceivedComplexity

# File lib/diplomat/event.rb, line 108
def get(name = nil, token = :last, not_found = :wait, found = :return, options = {})
  @raw = send_get_request(@conn, ['/v1/event/list'], options, use_named_parameter('name', name))
  body = JSON.parse(@raw.body)
  # TODO: deal with unknown symbols, invalid indices (find_index will return nil)
  idx = case token
        when :first then 0
        when :last then body.length - 1
        when :next then body.length
        else body.find_index { |e| e['ID'] == token } + 1
        end
  if JSON.parse(@raw.body).count.zero? || idx == body.length
    case not_found
    when :reject
      raise Diplomat::EventNotFound, name
    when :return
      event_name = ''
      event_payload = ''
      event_token = :last
    when :wait
      @raw = wait_for_next_event(['/v1/event/list'], options, use_named_parameter('name', name))
      @raw = parse_body
      # If it's possible for two events to arrive at once,
      # this needs to #find again:
      event = @raw.last
      event_name = event['Name']
      event_payload = Base64.decode64(event['Payload'])
      event_token = event['ID']
    end
  else
    case found
    when :reject
      raise Diplomat::EventAlreadyExits, name
    when :return
      event = body[idx]
      event_name = event['Name']
      event_payload = event['Payload'].nil? ? nil : Base64.decode64(event['Payload'])
      event_token = event['ID']
    end
  end

  {
    value: { name: event_name, payload: event_payload },
    token: event_token
  }
end
get_all(name = nil, not_found = :reject, found = :return, options = {}) click to toggle source

Get the list of events matching name @param name [String] the name of the event (regex) @param not_found [Symbol] behaviour if there are no events matching name;

:reject with exception, :return degenerate value, or :wait for a non-empty list

@param found [Symbol] behaviour if there are already events matching name;

:reject with exception, :return its current value, or :wait for its next value

@return [Array] The list of { :name, :payload } hashes @param options [Hash] options parameter hash @note

Events are sent via the gossip protocol; there is no guarantee of delivery
success or order, but the local agent will store up to 256 events that do
arrive. This method lists those events.
It has the same semantics as Kv::get, except the value returned is a list
i.e. the current value is all events up until now, the next value is the
current list plus the next event to arrive.
To get a specific event in the sequence, @see #get
When trying to get a list of events matching a name, there are two possibilities:
- The list doesn't (yet) exist / is empty
- The list exists / is non-empty
The combination of not_found and found behaviour gives maximum possible
flexibility. For X: reject, R: return, W: wait
- X X - meaningless; never return a value
- X R - "normal" non-blocking get operation. Default
- X W - get the next value only (must have a current value)
- R X - meaningless; never return a meaningful value
- R R - "safe" non-blocking, non-throwing get-or-default operation
- R W - get the next value or a default
- W X - get the first value only (must not have a current value)
- W R - get the first or current value; always return something, but
        block only when necessary
- W W - get the first or next value; wait until there is an update
# File lib/diplomat/event.rb, line 61
def get_all(name = nil, not_found = :reject, found = :return, options = {})
  # Event list never returns 404 or blocks, but may return an empty list
  @raw = send_get_request(@conn, ['/v1/event/list'], options, use_named_parameter('name', name))
  if JSON.parse(@raw.body).count.zero?
    case not_found
    when :reject
      raise Diplomat::EventNotFound, name
    when :return
      return []
    end
  else
    case found
    when :reject
      raise Diplomat::EventAlreadyExists, name
    when :return
      @raw = parse_body
      return return_payload
    end
  end

  @raw = wait_for_next_event(['/v1/event/list'], options, use_named_parameter('name', name))
  @raw = parse_body
  return_payload
end

Private Instance Methods

wait_for_next_event(url, options = {}, param = nil) click to toggle source

rubocop:enable Metrics/PerceivedComplexity

# File lib/diplomat/event.rb, line 157
def wait_for_next_event(url, options = {}, param = nil)
  if options.nil?
    options = { timeout: 86_400 }
  else
    options[:timeout] = 86_400
  end
  index = @raw.headers['x-consul-index']
  param += use_named_parameter('index', index)
  send_get_request(@conn, url, options, param)
end