Add labkit rate limit adapter for cohort 3 keys

What does this MR do and why?

Migrates Gitlab::ApplicationRateLimiter keys whose call graph contains .peek callers to Labkit::RateLimit::Limiter (cohort 3 of the staged migration tracked under epic gitlab-com/gl-infra&2021).

This is the first cohort that includes peek (read-without-increment) callers. Peek needed Limiter#peek upstream in labkit-ruby, which landed in v1.19.0; this MR bumps gitlab-labkit ~> 1.17.0 to ~> 1.19.0.

Adapter and dispatch changes

  • Adds Gitlab::ApplicationRateLimiter::LabkitAdapter.run_peek! companion to run!, calling limiter.peek (no INCR, no TTL extension).
  • Lifts the !peek guard in Gitlab::ApplicationRateLimiter._throttled? so peek dispatches now route through the adapter as well.
  • Refactors _throttled? for readability: extracts dispatch_to_labkit and legacy_throttled? private helpers so the orchestrator stays below the cyclomatic-complexity ceiling.

Cohort 3 registration

Key CE/EE Characteristics
glql CE [query_sha]
permanent_email_failure CE [email]
temporary_email_failure CE [email]
update_namespace_name CE [namespace]
hard_phone_verification_transactions_limit EE [scope]
soft_phone_verification_transactions_limit EE [scope]

All six tagged flag_scope: :cohort_3 in SupportedRateLimits.

web_hook_calls{,_low,_mid} is deliberately excluded: every caller passes a threshold: override that the adapter cannot honor, so it would always route to legacy via record_override. Registering it would never exercise the labkit path.

Mapping the 10 production peek call sites to keys

Key Peek call sites
glql app/services/analytics/glql/query_service.rb:115
permanent_email_failure app/models/notification_recipient.rb:116
temporary_email_failure app/models/notification_recipient.rb:117
update_namespace_name ee/app/models/ee/namespace.rb:1090
hard_phone_verification_transactions_limit ee/app/models/concerns/identity_verifiable.rb:180,202; ee/app/helpers/arkose_helper.rb:7
soft_phone_verification_transactions_limit ee/app/models/concerns/identity_verifiable.rb:207; ee/lib/identity_verification/user_risk_profile.rb:80
(excluded) web_hook_calls{,_low,_mid} lib/gitlab/web_hooks/rate_limiter.rb:36 (always passes threshold: override)

Feature flags

Two cohort-wide WIP ops flags, both default off:

  • rate_limiter_use_labkit_cohort_3 — enable shadow path
  • rate_limiter_use_labkit_cohort_3_enforce — switch authoritative decision to labkit

Operate as fully on or fully off; the adapter uses Feature.current_request as the actor, which resolves to a per-call UUID for non-request callers, making percentage rollouts non-deterministic.

References

How to set up and validate locally

  1. bundle install to pick up gitlab-labkit 1.19.0.

  2. Verify the gem bump and cohort 3 registration:

    bin/rails runner 'puts Gem.loaded_specs["gitlab-labkit"].version'
    # expected: 1.19.0
    
    bin/rails runner '
      puts Gitlab::ApplicationRateLimiter::LabkitAdapter::SupportedRateLimits.all
        .select { |_, spec| spec[:flag_scope] == :cohort_3 }
        .keys.sort
    '
    # expected (EE): glql, hard_phone_verification_transactions_limit,
    # permanent_email_failure, soft_phone_verification_transactions_limit,
    # temporary_email_failure, update_namespace_name
  3. Run the smoke-test driver from the smoke-test comment (save as /tmp/cohort3_smoke.rb):

    bin/rails runner /tmp/cohort3_smoke.rb

    Exercises shadow + enforce paths, override fallback, EE Symbol-scope serialization, and cleans up after itself. All seven cases were PASS against my GDK.

  4. Run the affected spec files:

    bundle exec rspec \
      spec/lib/gitlab/application_rate_limiter_spec.rb \
      spec/lib/gitlab/application_rate_limiter/labkit_adapter_spec.rb \
      ee/spec/lib/ee/gitlab/application_rate_limiter_spec.rb \
      ee/spec/lib/ee/gitlab/application_rate_limiter/labkit_adapter/supported_rate_limits_spec.rb

    Expected: 120 examples, 0 failures.

MR acceptance checklist

Evaluate this MR against the MR acceptance checklist.

  • Specs added for dispatch_to_labkit, run_peek!, peek dispatch in _throttled?, cohort 3 flag-basis resolution, and EE phone-verification cohort 3 registration.
  • All four affected spec files pass locally (120/120).
  • RuboCop clean on changed files.
  • bundle exec rake bundler:gemfile:sync run (Gemfile.next.lock kept in sync with Gemfile.lock).
  • Smoke-tested end-to-end against local GDK Redis (driver script in the cohort 3 issue).
  • Rollout plan with Grafana go/no-go queries posted on the cohort 3 issue.
  • introduced_by_url populated in both feature flag YAMLs (will fill in once this MR has a number).
  • rollout_issue_url populated in both feature flag YAMLs (pending rollout-steps issue).

Merge request reports

Loading