Class: Core::Thresholder

Inherits:
Object show all
Defined in:
lib/svcbase/thresholder.rb

Overview

Thresholder is an object that keeps track of how many calls are made to it and uses the volume over time to determine whether or not to run the associated block.

– get or create a thresholder named ‘foo’ thresholder = Core::Thresholder.instance(‘foo’, count: 60, seconds: 60)

– run block only if threshold is exceeded thresholder.exceeded { |count| puts “i have been called #count times” }

– run block only if threshold has not been exceeded thresholder.limit { |count| puts “i have been called #count times” }

– always run block and include current count thresholder.run { |count| puts “i have been called #count times” }

– reset counter thresholder.reset

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.forget(*names) ⇒ Object

forget a previously created thresholder

Raises:

  • (ArgumentError)


42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/svcbase/thresholder.rb', line 42

def self.forget(*names)
  raise ArgumentError, 'no identifiers for threshold instance call' if names.empty?

  return unless @instances.dig(*names)
  @class_mutex.synchronize do
    if names.length == 1
      @instances.delete names.last
    else
      @instances.dig(*names[0..-2])&.delete(names.last)
    end
  end
end

.instance(*names, **args) ⇒ Object

return existing thresholder if it exists, otherwise create one

Raises:

  • (ArgumentError)


28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/svcbase/thresholder.rb', line 28

def self.instance(*names, **args)
  raise ArgumentError, 'no identifiers for threshold instance call' if names.empty?

  obj = @instances.dig(*names, :_instance)
  return obj if obj

  # create the appropriate instance
  @class_mutex.synchronize do
    obj = names.inject(@instances) { |buf, key| buf[key] ||= {} }
    obj[:_instance] ||= new(*names, **args)
  end
end

Instance Method Details

#exceeded {|count| ... } ⇒ Object

run block if threshold is exceeded

Yields:

  • (count)


63
64
65
66
67
# File 'lib/svcbase/thresholder.rb', line 63

def exceeded
  raise 'No block passed to Thresholder#exceeded' unless block_given?
  count = update_and_return_count
  yield(count) if count > @max_count
end

#limit {|count| ... } ⇒ Object

run block if threshold is not exceeded

Yields:

  • (count)


56
57
58
59
60
# File 'lib/svcbase/thresholder.rb', line 56

def limit
  raise 'No block passed to Thresholder#limit' unless block_given?
  count = update_and_return_count
  yield(count) if count <= @max_count
end

#resetObject

reset internal counters



76
77
78
79
80
81
# File 'lib/svcbase/thresholder.rb', line 76

def reset
  @instance_mutex.synchronize do
    @queue = [] # each entry is a tuple [ <time>, <count> ]
    @count = 0  # current total count
  end
end

#run {|update_and_return_count| ... } ⇒ Object

always run block

Yields:

  • (update_and_return_count)


70
71
72
73
# File 'lib/svcbase/thresholder.rb', line 70

def run
  raise 'No block passed to Thresholder#run' unless block_given?
  yield(update_and_return_count)
end