diff options
author | Kamil Trzciński <ayufan@ayufan.eu> | 2017-12-18 16:08:51 +0300 |
---|---|---|
committer | Kamil Trzciński <ayufan@ayufan.eu> | 2017-12-18 16:08:51 +0300 |
commit | 924e00496c7d16887447b9384b66b555e5a9f911 (patch) | |
tree | ddf51b4cef3aa68eef7450a4c00eb28084f80eb9 /lib | |
parent | 38dd7263e15e84c08b62c97028e943c759384b94 (diff) | |
parent | 4b0465f20de1bf58326c7daf6876b63438f00d84 (diff) |
Merge branch 'sh-add-schedule-pipeline-run-now' into 'master'
Add button to run scheduled pipeline immediately
Closes #38741
See merge request gitlab-org/gitlab-ce!15700
Diffstat (limited to 'lib')
-rw-r--r-- | lib/gitlab/action_rate_limiter.rb | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/lib/gitlab/action_rate_limiter.rb b/lib/gitlab/action_rate_limiter.rb new file mode 100644 index 00000000000..4cd3bdefda3 --- /dev/null +++ b/lib/gitlab/action_rate_limiter.rb @@ -0,0 +1,47 @@ +module Gitlab + # This class implements a simple rate limiter that can be used to throttle + # certain actions. Unlike Rack Attack and Rack::Throttle, which operate at + # the middleware level, this can be used at the controller level. + class ActionRateLimiter + TIME_TO_EXPIRE = 60 # 1 min + + attr_accessor :action, :expiry_time + + def initialize(action:, expiry_time: TIME_TO_EXPIRE) + @action = action + @expiry_time = expiry_time + end + + # Increments the given cache key and increments the value by 1 with the + # given expiration time. Returns the incremented value. + # + # key - An array of ActiveRecord instances + def increment(key) + value = 0 + + Gitlab::Redis::Cache.with do |redis| + cache_key = action_key(key) + value = redis.incr(cache_key) + redis.expire(cache_key, expiry_time) if value == 1 + end + + value + end + + # Increments the given key and returns true if the action should + # be throttled. + # + # key - An array of ActiveRecord instances + # threshold_value - The maximum number of times this action should occur in the given time interval + def throttled?(key, threshold_value) + self.increment(key) > threshold_value + end + + private + + def action_key(key) + serialized = key.map { |obj| "#{obj.class.model_name.to_s.underscore}:#{obj.id}" }.join(":") + "action_rate_limiter:#{action}:#{serialized}" + end + end +end |