Class: Diplomat::Event

Inherits:
RestClient show all
Defined in:
lib/diplomat/event.rb

Overview

Methods for interacting with the Consul event API endpoint

Instance Method Summary collapse

Methods inherited from RestClient

access_method?, #concat_url, #configuration, #initialize, method_missing, respond_to?, respond_to_missing?, #use_named_parameter

Constructor Details

This class inherits a constructor from Diplomat::RestClient

Instance Method Details

#fire(name, value = nil, service = nil, node = nil, tag = nil, dc = nil, options = {}) ⇒ nil

Send an event rubocop:disable Metrics/ParameterLists

Parameters:

  • name (String)

    the event name

  • value (String) (defaults to: nil)

    the payload of the event

  • service (String) (defaults to: nil)

    the target service name

  • node (String) (defaults to: nil)

    the target node name

  • tag (String) (defaults to: nil)

    the target tag name, must only be used with service

  • dc (String) (defaults to: nil)

    the dc to target

  • options (Hash) (defaults to: {})

    options parameter hash

Returns:

  • (nil)

18
19
20
21
22
23
24
25
26
27
# 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 = {}) ⇒ 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).

Get a specific event in the sequence matching name rubocop:disable Metrics/PerceivedComplexity

Parameters:

  • name (String) (defaults to: nil)

    the name of the event (regex)

  • token (String|Symbol) (defaults to: :last)

    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

  • not_found (Symbol) (defaults to: :wait)

    behaviour if there is no matching event; :reject with exception, :return degenerate value, or :wait for event

  • found (Symbol) (defaults to: :return)

    behaviour if there is a matching event; :reject with exception, or :return its current value

  • options (Hash) (defaults to: {})

    options parameter hash

Returns:

  • (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


108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# 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 = {}) ⇒ Array[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

Get the list of events matching name

Parameters:

  • name (String) (defaults to: nil)

    the name of the event (regex)

  • not_found (Symbol) (defaults to: :reject)

    behaviour if there are no events matching name; :reject with exception, :return degenerate value, or :wait for a non-empty list

  • found (Symbol) (defaults to: :return)

    behaviour if there are already events matching name; :reject with exception, :return its current value, or :wait for its next value

  • options (Hash) (defaults to: {})

    options parameter hash

Returns:

  • (Array[hash])

    The list of { :name, :payload } hashes


61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# 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