class Cutoff
Constants
- CURRENT_STACK_KEY
Attributes
@return [Float] The total number of seconds for this cutoff
Public Class Methods
Raise an exception if there is an active expired cutoff
Does nothing if no active cutoff is set
@raise CutoffExceededError
If there is an active expired cutoff @return [void]
# File lib/cutoff.rb, line 91 def checkpoint!(name = nil) cutoff = current return unless cutoff cutoff.checkpoint!(name) end
Clear the entire stack for this thread
@return [void]
# File lib/cutoff.rb, line 64 def clear_all Thread.current[CURRENT_STACK_KEY] = nil end
Get the current {Cutoff} if one is set
# File lib/cutoff.rb, line 21 def current Thread.current[CURRENT_STACK_KEY]&.last end
Disable Cutoff
globally. Useful for testing and debugging
Should not be used in production
@return [void]
# File lib/cutoff.rb, line 103 def disable! @disabled = true end
True if cutoff was disabled with {.disable!}
@return [Boolean] True if disabled
# File lib/cutoff.rb, line 119 def disabled? @disabled == true end
Enable Cutoff
globally if it has been disabled
Should not be used in production
@return [void]
# File lib/cutoff.rb, line 112 def enable! @disabled = false end
Create a new cutoff
The timer starts immediately upon creation
@param allowed_seconds
[Float, Integer] The total number of seconds to allow @param exclude [Enumberable<Symbol>, Symbol, nil] If given a name or
list of checkpoint names to skip
@param only [Enumberable<Symbol>, Symbol, nil] If given a name or
list of checkpoint names to allow
# File lib/cutoff.rb, line 136 def initialize(allowed_seconds, exclude: nil, only: nil) @allowed_seconds = allowed_seconds.to_f @start_time = Cutoff.now if exclude @exclude = Set.new(exclude.is_a?(Enumerable) ? exclude : [exclude]) end if only @only = Set.new(only.is_a?(Enumerable) ? only : [only]) end end
Add a new {Cutoff} to the stack
This {Cutoff} will be specific to this thread
If a cutoff is already started for this thread, then `start` uses the minimum of the current remaining time and the given time
@param (see initialize) @return [Cutoff] The {Cutoff} instance
# File lib/cutoff.rb, line 34 def start(allowed_seconds, **options) if current allowed_seconds = [allowed_seconds, current.seconds_remaining].min end cutoff = new(allowed_seconds, **options) Thread.current[CURRENT_STACK_KEY] ||= [] Thread.current[CURRENT_STACK_KEY] << cutoff cutoff end
Remove the top {Cutoff} from the stack
@param cutoff [Cutoff] If given, the top instance will only be removed
if it matches the given cutoff instance
@return [Cutoff, nil] If a cutoff was removed it is returned
# File lib/cutoff.rb, line 50 def stop(cutoff = nil) stack = Thread.current[CURRENT_STACK_KEY] return unless stack top = stack.last stack.pop if cutoff.nil? || top == cutoff clear_all if stack.empty? cutoff end
@return [Gem::Version] The current version of the cutoff gem
# File lib/cutoff/version.rb, line 5 def self.version Gem::Version.new('0.4.2') end
Wrap a block in a cutoff
Same as calling {.start} and {.stop} manually, but safer since you can't forget to stop a cutoff and it handles exceptions raised inside the block
@see .start @see .stop @param (see initialize) @return The value that returned from the block
# File lib/cutoff.rb, line 78 def wrap(allowed_seconds, **options) cutoff = start(allowed_seconds, **options) yield cutoff ensure stop(cutoff) end
Public Instance Methods
Raises an error if this Cutoff
has been exceeded
@raise CutoffExceededError
If there is an active expired cutoff @return [void]
# File lib/cutoff.rb, line 183 def checkpoint!(name = nil) unless name.nil? || name.is_a?(Symbol) raise ArgumentError, 'name must be a symbol' end return unless selected?(name) raise CutoffExceededError, self if exceeded? nil end
The number of seconds elapsed since this {Cutoff} was created
@return [Float] The number of seconds
# File lib/cutoff.rb, line 166 def elapsed_seconds return 0 if Cutoff.disabled? Cutoff.now - @start_time end
Has the Cutoff
been exceeded?
@return [Boolean] True if the timer expired
# File lib/cutoff.rb, line 175 def exceeded? seconds_remaining.negative? end
The number of milliseconds left on the clock
@return [Float] The number of milliseconds
# File lib/cutoff.rb, line 159 def ms_remaining seconds_remaining * 1000 end
The number of seconds left on the clock
@return [Float] The number of seconds
# File lib/cutoff.rb, line 152 def seconds_remaining @allowed_seconds - elapsed_seconds end
True if the named checkpoint is selected by the `exclude` and `only` options. If these options are not given, a checkpoint is considered to be selected. If the checkpoint is not named, it is also considered to be selected.
@param name [Symbol, nil] The name of the checkpoint @return [Boolean] True if the checkpoint is selected
# File lib/cutoff.rb, line 201 def selected?(name) return true if name.nil? && @exclude return false if @exclude&.include?(name) return false if @only && !@only.include?(name) true end