Class: Mongoid::Matcher::RegexpBudget::Budget Private

Inherits:
Object
  • Object
show all
Defined in:
lib/mongoid/matcher/regexp_budget.rb

Overview

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

The state of one open budget: what is left of the limit, and the patterns compiled under it.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(limit) ⇒ Budget

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a new instance of Budget.

Parameters:

  • limit (Float)

    The seconds this budget may spend.



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/mongoid/matcher/regexp_budget.rb', line 62

def initialize(limit)
  @limit = limit
  @remaining = limit
  @cache = {}
  # A per-Regexp timeout bounds one match; the cumulative budget bounds
  # the operation. So the timeout is fixed for the life of the scope
  # rather than following the drawdown, which is what lets a pattern be
  # compiled once instead of once per match. It means a match that
  # starts with almost nothing left can still run for a whole limit, so
  # an operation can overshoot by at most one limit -- bounded, which is
  # the point, and far cheaper than recompiling.
  #
  # An application that has set a stricter global Regexp.timeout keeps
  # it: baking in a larger value would leave it less protected than it
  # asked to be. A timeout set on one individual pattern is a different
  # matter, and is not preserved -- Budget#compile rebuilds the pattern
  # from its source and flags, neither of which carries one, so this
  # value takes its place. Only trusted code can supply such a pattern:
  # a condition decoded from JSON or BSON arrives as a string or a
  # BSON::Regexp::Raw, with no timeout of its own.
  @timeout = [ limit, ::Regexp.timeout ].compact.min if PER_REGEXP_TIMEOUT
end

Instance Attribute Details

#limitFloat (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns The limit this budget started with.

Returns:

  • (Float)

    The limit this budget started with.



56
57
58
# File 'lib/mongoid/matcher/regexp_budget.rb', line 56

def limit
  @limit
end

#remainingFloat (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns The seconds left before the budget is spent.

Returns:

  • (Float)

    The seconds left before the budget is spent.



59
60
61
# File 'lib/mongoid/matcher/regexp_budget.rb', line 59

def remaining
  @remaining
end

Instance Method Details

#charge(elapsed) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Draws the elapsed time down from the budget.

Parameters:

  • elapsed (Float)

    The seconds to charge.



88
89
90
# File 'lib/mongoid/matcher/regexp_budget.rb', line 88

def charge(elapsed)
  @remaining -= elapsed
end

#compile(condition) ⇒ Regexp

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns the condition as a Regexp which, where the Ruby in use supports it, gives up once its timeout is spent.

The condition is taken uncompiled so that the cache can answer before any compiling happens. A BSON::Regexp::Raw memoizes its own compile, but FieldExpression builds a fresh one for every $regex it evaluates, so that memo is worth nothing across documents and the source would otherwise be compiled once per document.

Parameters:

  • condition (Regexp | BSON::Regexp::Raw)

    The condition.

Returns:

  • (Regexp)

    The compiled pattern.



109
110
111
# File 'lib/mongoid/matcher/regexp_budget.rb', line 109

def compile(condition)
  @cache[cache_key(condition)] ||= bake(RegexpBudget.coerce(condition))
end

#exhausted?true | false

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns Whether the budget is spent.

Returns:

  • (true | false)

    Whether the budget is spent.



93
94
95
# File 'lib/mongoid/matcher/regexp_budget.rb', line 93

def exhausted?
  @remaining <= 0
end