Class: Villein::Agent

Inherits:
Client
  • Object
show all
Defined in:
lib/villein/agent.rb

Overview

Villein::Agent allows you to start new serf agent. Use this when you need to start and manage the serf agents from ruby process.

Defined Under Namespace

Classes: AlreadyStarted, NotRunning, ResponderExists

Constant Summary collapse

EVENT_HANDLER_NATIVE =
File.expand_path(File.join(__dir__, '..', '..', 'misc', 'villein-event-handler'))
EVENT_HANDLER_RB =
File.expand_path(File.join(__dir__, '..', '..', 'misc', 'villein-event-handler.rb'))
EVENT_HANDLER =
if File.exist?(EVENT_HANDLER_NATIVE)
  EVENT_HANDLER_NATIVE
else
  EVENT_HANDLER_RB
end

Instance Attribute Summary collapse

Attributes inherited from Client

#name, #rpc_addr, #serf, #silence

Instance Method Summary collapse

Methods inherited from Client

#delete_tag, #event, #force_leave, #get_tags, #info, #join, #leave, #members, #query, #set_tag, #silence?, #tags

Constructor Details

#initialize(serf: 'serf', node: Socket.gethostname, rpc_addr: '127.0.0.1:7373', bind: nil, iface: nil, advertise: nil, config_file: nil, config_dir: nil, discover: false, join: nil, snapshot: nil, encrypt: nil, profile: nil, protocol: nil, event_handlers: [], replay: nil, tags: {}, tags_file: nil, async_query: true, parallel_events: false, log_level: :info, log: File::NULL, raise_error_on_event_listener_fail: false, villein_handler: EVENT_HANDLER) ⇒ Agent

Returns a new instance of Agent.



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/villein/agent.rb', line 24

def initialize(serf: 'serf',
               node: Socket.gethostname,
               rpc_addr: '127.0.0.1:7373', bind: nil, iface: nil, advertise: nil,
               config_file: nil, config_dir: nil,
               discover: false, join: nil, snapshot: nil,
               encrypt: nil, profile: nil, protocol: nil,
               event_handlers: [], replay: nil,
               tags: {}, tags_file: nil,
               async_query: true,
               parallel_events: false,
               log_level: :info, log: File::NULL,
               raise_error_on_event_listener_fail: false,
               villein_handler: EVENT_HANDLER)
  @serf = serf
  @name = node
  @rpc_addr = rpc_addr
  @bind, @iface, @advertise = bind, iface, advertise
  @config_file, @config_dir = config_file, config_dir
  @discover, @join, @snapshot = discover, join, snapshot
  @encrypt, @profile, @protocol = encrypt, profile, protocol
  @custom_event_handlers, @replay = event_handlers, replay
  @initial_tags, @tags_file = tags, tags_file
  @async_query, @parallel_events = async_query, parallel_events
  @log_level, @log = log_level, log
  @raise_error_on_event_listener_fail = raise_error_on_event_listener_fail
  @villein_handler = villein_handler

  @hooks = {}
  @responders = {}

  @pid, @exitstatus = nil, nil
  @pid_lock = Mutex.new
end

Instance Attribute Details

#exitstatusObject (readonly)

Returns the value of attribute exitstatus.



58
59
60
# File 'lib/villein/agent.rb', line 58

def exitstatus
  @exitstatus
end

#pidObject (readonly)

Returns the value of attribute pid.



58
59
60
# File 'lib/villein/agent.rb', line 58

def pid
  @pid
end

Instance Method Details

#auto_stopObject

Add at_exit hook to safely stop at exit of current ruby process. Note that Kernel#.at_exit hook won’t run when Ruby has crashed.



128
129
130
# File 'lib/villein/agent.rb', line 128

def auto_stop
  at_exit { self.stop! if self.running? }
end

#commandObject

Command line arguments to start serf-agent.



144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/villein/agent.rb', line 144

def command
  cmd = [@serf, 'agent']

  cmd << ['-node', @name] if @name
  cmd << '-replay' if @replay
  cmd << '-discover' if @discover

  @initial_tags.each do |key, val|
    cmd << ['-tag', "#{key}=#{val}"]
  end

  cmd << [
    '-event-handler',
    [@villein_handler, *event_listener_addr].join(' ')
  ]

  @custom_event_handlers.each do |handler|
    cmd << ['-event-handler', handler]
  end

  %w(bind iface advertise config-file config-dir
     encrypt join log-level profile protocol rpc-addr
     snapshot tags-file).each do |key|

    val = instance_variable_get("@#{key.gsub(/-/,'_')}")
    cmd << ["-#{key}", val] if val
  end

  cmd.flatten.map(&:to_s)
end

#dead?Boolean

Returns true when the serf agent has started, but stopped for some reason. Use Agent#exitstatus to get Process::Status object.

Returns:

  • (Boolean)


69
70
71
# File 'lib/villein/agent.rb', line 69

def dead?
  !!@exitstatus
end

#ready?Boolean

Return true when the agent has received events at least once. Useful to wait serf for ready to use.

Returns:

  • (Boolean)


76
77
78
# File 'lib/villein/agent.rb', line 76

def ready?
  running? && @event_received
end

#respond(name, override: false, &block) ⇒ Object

Respond to query events. Raises error when override is false and responder for given query name already exists.



178
179
180
181
182
183
184
185
# File 'lib/villein/agent.rb', line 178

def respond(name, override: false, &block)
  name = name.to_s
  if !override && @responders[name]
    raise ResponderExists, "Responder for #{name} already exists. To force, pass `override: true`"
  end

  @responders[name] = block
end

#running?Boolean

Returns true when the serf agent is running (it has started and not dead yet).

Returns:

  • (Boolean)


82
83
84
# File 'lib/villein/agent.rb', line 82

def running?
  started? && !dead?
end

#start!Object

Start the serf agent.



87
88
89
90
91
92
93
94
95
96
97
# File 'lib/villein/agent.rb', line 87

def start!
  @pid_lock.synchronize do
    raise AlreadyStarted if running?

    @event_received = false

    start_listening_events
    start_process
    start_watchdog
  end
end

#started?Boolean

Returns true when the serf agent has started

Returns:

  • (Boolean)


62
63
64
# File 'lib/villein/agent.rb', line 62

def started?
  !!@pid
end

#stop!(timeout_sec = 10) ⇒ Object

Stop the serf agent. After timeout_sec seconds elapsed, it will attempt to KILL if the agent is still running.



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/villein/agent.rb', line 102

def stop!(timeout_sec = 10)
  @pid_lock.synchronize do
    raise NotRunning unless running?

    Process.kill(:INT, @pid)

    stop_watchdog
    call_hooks 'stop', nil

    kill_process(timeout_sec)

    stop_listening_events

    @pid = nil
  end
end

#wait_for_readyObject

Blocks until #ready? become true.



121
122
123
# File 'lib/villein/agent.rb', line 121

def wait_for_ready
  sleep 0.1 until ready?
end