+1
−0
lib/labkit/rate_limit/matcher.rb
0 → 100644
+85
−0
Loading
Implements Spec 10 (gitlab-com/gl-infra/production-engineering#28855): extends Labkit::RateLimit::Rule#match so callers can match on regex patterns alongside the existing equality semantics. Unblocks Spec 9 (Stage 2b RackAttack migration, gitlab-com/gl-infra/production-engineering#28852). Match-value shape: - any plain value -> :equality matcher (semantics unchanged) - { regex: "<source>" } single-key Hash -> :regex matcher (canonical, YAML-compatible) - bare Regexp instance -> :regex matcher (Ruby-side convenience, normalized internally) Internals: a private Labkit::RateLimit::Matcher value object encapsulates (type, value); Matcher.from is the single normalization entry point and Matcher#match? the single matching entry point. Rule.new normalizes every match value through Matcher.from at construction; Evaluator#rule_matches? calls matcher.match?(identifier[key]). Out of scope (per @reprazent review): - Glob matchers — { glob: "..." } is explicitly rejected at Rule.new with ArgumentError. Glob support is deferred to gitlab-com/gl-infra/production-engineering#28853 (config evolution). - Ruby-only typed-object constructors (e.g. Matcher.regex(...)) — push callers toward the YAML-compatible Hash form. Behaviour notes: - Non-String identifier value vs. regex matcher: quiet skip (rule does not match, evaluation continues; no exception, no log). - Regex compilation happens once at Rule.new; counter-key derivation still uses the identifier value, never the pattern source. - Regex source strings are capped at 200 characters at Rule.new. Specs cover Scenarios A–I from the spec acceptance criteria, including Ruby<->YAML cross-format parity (Scenario I) and the explicit-rejection guarantee for { glob: ... } and other unsupported shapes (Scenario H). Co-Authored-By:Claude Opus 4.7 (1M context) <noreply@anthropic.com>