Sha256: e9056f87637c226112cf6072d371d65efe8453201b67b9c8ec43e02f387bf646

Contents?: true

Size: 1.72 KB

Versions: 1

Compression:

Stored size: 1.72 KB

Contents

require_relative 'alarm'

module Ring
class SQA

  class Analyzer
    INTERVAL      = 60 # how often to run analyze loop
    INFLIGHT_WAIT = 1  # how long to wait for inflight records
    def run
      sleep INTERVAL
      loop do
        start = Time.now
        @db.purge
        @db_id_seen, records = @db.nodes_down(@db_id_seen+1)
        sleep INFLIGHT_WAIT
        records = records.all
        @buffer.push records.map { |record| record.peer }
        @buffer.exceed_median? ? @alarm.set(@buffer) : @alarm.clear
        delay = INTERVAL-(Time.now-start)
        if delay > 0
          sleep delay
        else
          Log.error "Analyzer loop took longer than #{INTERVAL}, wanted to sleep for #{delay}s"
        end
      end
    end

    private

    def initialize database, nodes
      @db         = database
      @nodes      = nodes
      @alarm      = Alarm.new
      @buffer     = AnalyzeBuffer.new @nodes.list.size
      @db_id_seen = 0
    end
  end

  class AnalyzeBuffer
    attr_reader :array
    def initialize nodes_count, max_size=30, median_of=27
      @max_size  = max_size
      @median_of = median_of
      init_nodes = Array.new nodes_count * 2, ''
      @array     = Array.new max_size, init_nodes
    end
    def push e
      @array.shift
      @array.push e
    end
    def median
      last   = @median_of-1
      node_count[0..last].sort[last/2]
    end
    def exceed_median? tolerance=CFG.analyzer.tolerance
      violate = (median+1)*tolerance
      node_count[@median_of..-1].all? { |e| e > violate }
    end
    def node_count
      @array.map { |nodes| nodes.size }
    end
    def exceeding_nodes
      exceed = @array[@median_of..-1].inject :&
      exceed - @array[0..@median_of-1].flatten.uniq
    end
  end

end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
ring-sqa-0.0.19 lib/ring/sqa/analyzer.rb