excess_flow 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,120 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2019 ConvertKit, LLC
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'connection_pool'
18
+ require 'redis'
19
+
20
+ require 'excess_flow/constants'
21
+ require 'excess_flow/configuration'
22
+ require 'excess_flow/redis_connection'
23
+
24
+ require 'excess_flow/global_mutex'
25
+ require 'excess_flow/failed_execution'
26
+
27
+ require 'excess_flow/throttle_configuration'
28
+ require 'excess_flow/throttled_executor'
29
+ require 'excess_flow/configuration_error'
30
+
31
+ require 'excess_flow/strategy'
32
+ require 'excess_flow/fixed_window_strategy'
33
+ require 'excess_flow/sliding_window_strategy'
34
+ require 'excess_flow/rate_limited_execution_result'
35
+
36
+ # = ExcessFlow
37
+ #
38
+ # Precise rate limiter with Redis as a backend. For more information on
39
+ # general usage consider consulting README.md file.
40
+ #
41
+ # While interacting with the rate limiter from within your application
42
+ # avoid re-using anything after :: notation as it is part of internal API
43
+ # and is subject to an un-announced breaking change.
44
+ #
45
+ # ExcessFlow provides 5 methods as part of it's public API:
46
+ # * configuration
47
+ # * configure
48
+ # * redis
49
+ # * redis_connection_pool
50
+ # * throttle
51
+ module ExcessFlow
52
+ module_function
53
+
54
+ # Provides access to cache's configuration.
55
+ #
56
+ # @return [Configuration] the object holding configuration values
57
+ def configuration
58
+ @configuration ||= Configuration.new
59
+ end
60
+
61
+ # API to configure cache dynamically during runtime.
62
+ #
63
+ # @yield [configuration] Takes in a block of code of code that is setting
64
+ # or changing configuration values
65
+ #
66
+ # @example Configure during runtime changing redis URL
67
+ # ExcessFlow.configure { |c| c.redis_url = 'foobar' }
68
+ #
69
+ # @return [void]
70
+ def configure
71
+ yield(configuration)
72
+ nil
73
+ end
74
+
75
+ # API to communicate with Redis database backing cache up.
76
+ #
77
+ # @yield [redis]
78
+ #
79
+ # @example Store a value in Redis at given key
80
+ # Store.redis { |r| r.set('meaning_of_life', 42) }
81
+ #
82
+ # @return Returns a result of interaction with Redis
83
+ def redis
84
+ redis_connection_pool.with do |connection|
85
+ yield connection
86
+ end
87
+ end
88
+
89
+ # Accessor to connection pool. Defined on top level so it can be memoized
90
+ # on the topmost level
91
+ #
92
+ # @return [ConnectionPool] ConnectionPool object from connection_pool gem
93
+ def redis_connection_pool
94
+ @redis_connection_pool ||= ExcessFlow::RedisConnection.connection_pool
95
+ end
96
+
97
+ # Executes passed in block of code rate limited using specified strategy
98
+ # and arguments. Different call types can be differentiated and configured
99
+ # using arguments.
100
+ #
101
+ # @param key [String] key to identify your request to limit. Requests that are
102
+ # identified by same key share limits
103
+ # @param limit [Integer] number of requests that can be made in the specified
104
+ # time window
105
+ # @param ttl [Integer] size of window in seconds; how long it will take until
106
+ # the limits are reset
107
+ # @param strategy [Symbol] (optional) specifies which strategy to use to rate
108
+ # limit requests. Optional. Defaults to :fixed_window. Supported strategies
109
+ # are :fixed_window and :sliding_window.
110
+ #
111
+ # @return [ExcessFlow::RateLimitedExecutionResult] Execution result object that
112
+ # will hold result of your execution if it was under the limit. Accessible by
113
+ # calling `result` method. This object has two methods as part of it's public
114
+ # API: `result` (returns either result of execution or ExcessFlow::FailedExecution
115
+ # if limits were breached) and `success?` (returns `true` if request was within
116
+ # limits and else returns `false`).
117
+ def throttle(args, &block)
118
+ ExcessFlow::ThrottledExecutor.select_strategy_and_execute(args, &block)
119
+ end
120
+ end
metadata ADDED
@@ -0,0 +1,115 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: excess_flow
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - ConvertKit, LLC
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-10-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: connection_pool
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: redis
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: Hihg precision simple redis based rate limiter.
56
+ email:
57
+ - engineering@convertkit.com
58
+ executables:
59
+ - console
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - ".circleci/config.yml"
64
+ - ".gitignore"
65
+ - ".rspec"
66
+ - ".rubocop.yml"
67
+ - ".travis.yml"
68
+ - CHANGELOG.md
69
+ - CODE_OF_CONDUCT.md
70
+ - Gemfile
71
+ - Gemfile.lock
72
+ - LICENSE.txt
73
+ - README.md
74
+ - Rakefile
75
+ - bin/console
76
+ - bin/setup
77
+ - excess_flow.gemspec
78
+ - lib/excess_flow.rb
79
+ - lib/excess_flow/configuration.rb
80
+ - lib/excess_flow/configuration_error.rb
81
+ - lib/excess_flow/constants.rb
82
+ - lib/excess_flow/failed_execution.rb
83
+ - lib/excess_flow/fixed_window_strategy.rb
84
+ - lib/excess_flow/global_mutex.rb
85
+ - lib/excess_flow/rate_limited_execution_result.rb
86
+ - lib/excess_flow/redis_connection.rb
87
+ - lib/excess_flow/sliding_window_strategy.rb
88
+ - lib/excess_flow/strategy.rb
89
+ - lib/excess_flow/throttle_configuration.rb
90
+ - lib/excess_flow/throttled_executor.rb
91
+ homepage:
92
+ licenses:
93
+ - Apache License Version 2.0
94
+ metadata:
95
+ source_code_uri: https://github.com/ConvertKit/excess_flow
96
+ post_install_message:
97
+ rdoc_options: []
98
+ require_paths:
99
+ - lib
100
+ required_ruby_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ required_rubygems_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ requirements: []
111
+ rubygems_version: 3.0.3
112
+ signing_key:
113
+ specification_version: 4
114
+ summary: Redis based rate limiter
115
+ test_files: []