module Salus

A future is an object that incapsulates a block which is called in a different thread, upon retrieval the caller gets blocked until the block has finished running, and its result is returned and cached.

borrowed from github.com/meh/ruby-thread

Constants

VERSION

Public Class Methods

default(opts) click to toggle source
# File lib/salus.rb, line 34
def default(opts)
  return unless opts.is_a?(Hash)
  opts.each do |k, v|
    next if [:value, :timestamp].include?(k)
    @@_opts[k] = v
  end
end
defaults() click to toggle source
# File lib/salus.rb, line 42
def defaults
  @@_opts
end
discover(name, &block) click to toggle source
# File lib/salus/zabbix.rb, line 7
def discover(name, &block)
  raise ArgumentError, "Block should be given" unless block_given?
  @@_discovers[name] = block
end
discovers() click to toggle source
# File lib/salus/zabbix.rb, line 12
def discovers
  @@_discovers
end
discovery(name) click to toggle source
# File lib/salus/zabbix.rb, line 16
def discovery(name)
  return unless @@_discovers.key?(name)
  data = []
  @@_discovers[name].call(data)
  {data: data}.to_json
end
group(title, &block) click to toggle source
# File lib/salus.rb, line 23
def group(title, &block)
  unless @@_groups.key?(title)
    @@_groups[title] = Group.new(@@_opts, &block)
  end
end
groups() click to toggle source
# File lib/salus.rb, line 29
def groups
  @@_groups
end
Also aliased as: root
lazy(&block) click to toggle source
# File lib/salus.rb, line 99
def lazy(&block)
  raise ArgumentError, "Block should be given" unless block_given?
  @@_lazy << block
end
lazy_eval() click to toggle source
# File lib/salus.rb, line 104
def lazy_eval
  # Lazy eval blocks once
  return if @@_lazy.empty?
  @@_lazy.each { |block| instance_eval(&block) }
  @@_lazy.clear
end
let(arg, default=nil, &block)
Alias for: var
load(file) click to toggle source
# File lib/salus.rb, line 111
def load(file)
  instance_eval(File.read(file), File.basename(file), 0) if File.exists?(file)
end
load_state(&block) click to toggle source
# File lib/salus.rb, line 115
def load_state(&block)
  data = block.call
  return unless data
  return if data.empty?
  lazy_eval
  data.each do |k, v|
    @@_groups[k].load(v) if @@_groups.key?(k)
  end
end
on_win?() click to toggle source
# File lib/salus.rb, line 19
def on_win?
  @@_win ||= !(RUBY_PLATFORM =~ /bccwin|cygwin|djgpp|mingw|mswin|wince/i).nil?
end
render(obj=nil, &block) click to toggle source
# File lib/salus.rb, line 71
def render(obj=nil, &block)
  if block_given?
    @@_renders << BlockRenderer.new(&block)
  else
    unless obj.is_a? Salus::BaseRenderer
      log ERROR, "#{obj.class} must be a subclass of Salus::BaseRenderer"
      return
    end
    @@_renders << obj
  end
end
renders() click to toggle source
# File lib/salus.rb, line 83
def renders
  @@_renders
end
reset() click to toggle source
# File lib/salus.rb, line 87
def reset
  @@_groups  = {}
  @@_renders = []
  @@_opts    = {}
  @@_vars    = {}
  @@_lazy    = []
  if defined?(@@_pool) && @@_pool.is_a?(Salus::ThreadPool)
    @@_pool.shutdown!
    @@_pool = nil
  end
end
root()
Alias for: groups
run() click to toggle source
# File lib/salus.rb, line 172
def run
  loop do
    pool.process do
      tick
    end
    sleep Salus.interval
  end
end
save_state(&block) click to toggle source
# File lib/salus.rb, line 125
def save_state(&block)
  data = {}
  @@_groups.each { |k, v| data[k]  = v.to_h }
  block.call(data)
end
tick() click to toggle source
# File lib/salus.rb, line 131
def tick
  log DEBUG, "Tick..."
  lazy_eval
  return if @@_groups.empty?
  pause = (Salus.interval - Salus.tick_timeout - Salus.render_timeout) / 2
  pause = 1 if (pause <= 0)

  log DEBUG, "Starting collection. Top-level groups to spawn: #{@@_groups.count}"
  latch = CountDownLatch.new(@@_groups.count)
  @@_groups.each do |k, v|
    pool.process do
      begin
        v.tick
        latch.count_down
      rescue Exception => e
        log ERROR, e
        latch.count_down
      end
    end.timeout_after(Salus.tick_timeout)
  end
  latch.wait(Salus.tick_timeout + pause)
  log DEBUG, "Collection finished. Threads: #{pool.spawned} spawned, #{pool.waiting} waiting, #{Thread.list.count} total"

  return if @@_renders.empty?
  log DEBUG, "Starting #{@@_renders.count} renderers"
  latch = CountDownLatch.new(@@_renders.count)
  @@_renders.each do |v|
    pool.process do
      begin
        v.render(root)
        latch.count_down
      rescue Exception => e
        log ERROR, e
        latch.count_down
      end
    end.timeout_after(Salus.render_timeout)
  end
  latch.wait(Salus.render_timeout + pause)
  log DEBUG, "Rendering finished. Threads: #{pool.spawned} spawned, #{pool.waiting} waiting, #{Thread.list.count} total"
end
var(arg, default=nil, &block) click to toggle source
# File lib/salus.rb, line 46
def var(arg, default=nil, &block)
  if arg.is_a?(Hash)
    arg.each {|k, v| @@_vars[k] = v}
  elsif block_given?
    @@_vars[arg.to_sym] = block
  else
    value = @@_vars.fetch(arg.to_sym, default)
    # Dumb lazy loading
    @@_vars[arg.to_sym] = if value.is_a?(Proc)
      begin
        value = value.call
      rescue Exception => e
        log DEBUG, e
        value = default
      end
    end
    value
  end
end
Also aliased as: let
vars() click to toggle source
# File lib/salus.rb, line 67
def vars
  @@_vars
end

Protected Class Methods

pool() click to toggle source
# File lib/salus.rb, line 182
def pool
  @@_pool ||= ThreadPool.new(self.min_threads, self.max_threads).auto_trim!
end