kredis 1.6.0 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 15ed6996059d28937ffa4f43a35e53d1e8fbc1894a30446575d9c00c390cd838
4
- data.tar.gz: 296f80ea7719d69334d50240c9fce5969df4f8d976800013167c1fb0ebe6a0b3
3
+ metadata.gz: 4b979e9602301ecfbea9a89c99cc1b0f3763b26990c9264d7cb767aa258aaac5
4
+ data.tar.gz: cdd19bdd88263e1cbeae92cf40ad224cc7f84faa3965bd85f4e1f82487964ddd
5
5
  SHA512:
6
- metadata.gz: cae34ebe3f21fe7c0e9cc0da5fc14bdc0d15931436bf7f07c552c14090489806990779ffd219be054f050468c809e23bf79302365f59f2dfced4b6a054ad352c
7
- data.tar.gz: 96513897d1badc12f4fc6b2e51e017958f7e5eeaa5730d06bcb9d9a12d71ae09a4eb8ce2661e70a70647f4c4d7e5543a30451ab64d290b91de20d47602f30398
6
+ metadata.gz: 26e3ce8f1580e01c7177ba79caf93b2a3e77276a03e4de30968633e8de675341ab12a16d08f113fe67631bd60c334631d33c6e41bfa70301778e3bf26d64bb70
7
+ data.tar.gz: 86dd839a25c227d18e04492d6d3a58526be5687fd4dcf20ff94eb127522b51e98b6acbfda4dc0059a56ab22b4a6ff2b4d81b59884636aed03f7ab735fe5b3de7
data/README.md CHANGED
@@ -161,6 +161,20 @@ sleep 0.5.seconds
161
161
  true == flag.marked? #=> EXISTS myflag
162
162
  sleep 0.6.seconds
163
163
  false == flag.marked? #=> EXISTS myflag
164
+
165
+ limiter = Kredis.limiter "mylimit", limit: 3, expires_in: 5.seconds
166
+ 0 == limiter.value # => GET "limiter"
167
+ limiter.poke # => SET limiter 0 NX + INCRBY limiter 1
168
+ limiter.poke # => SET limiter 0 NX + INCRBY limiter 1
169
+ limiter.poke # => SET limiter 0 NX + INCRBY limiter 1
170
+ false == limiter.exceeded? # => GET "limiter"
171
+ limiter.poke # => SET limiter 0 NX + INCRBY limiter 1
172
+ true == limiter.exceeded? # => GET "limiter"
173
+ sleep 6
174
+ limiter.poke # => SET limiter 0 NX + INCRBY limiter 1
175
+ limiter.poke # => SET limiter 0 NX + INCRBY limiter 1
176
+ limiter.poke # => SET limiter 0 NX + INCRBY limiter 1
177
+ false == limiter.exceeded? # => GET "limiter"
164
178
  ```
165
179
 
166
180
  ### Models
@@ -245,6 +259,8 @@ Additional configurations can be added under `config/redis/*.yml` and referenced
245
259
 
246
260
  Kredis passes the configuration to `Redis.new` to establish the connection. See the [Redis documentation](https://github.com/redis/redis-rb) for other configuration options.
247
261
 
262
+ If you don't have `config/redis/shared.yml` (or use another named configuration), Kredis will default to look in env for `REDIS_URL`, then fallback to a default URL of `redis://127.0.0.1:6379/0`.
263
+
248
264
  ### Redis support
249
265
 
250
266
  Kredis works with Redis server 4.0+, with the [Redis Ruby](https://github.com/redis/redis-rb) client version 4.2+.
@@ -72,6 +72,10 @@ module Kredis::Attributes
72
72
  kredis_connection_with __method__, name, key, default: default, config: config, after_change: after_change, expires_in: expires_in
73
73
  end
74
74
 
75
+ def kredis_limiter(name, limit:, key: nil, config: :shared, after_change: nil, expires_in: nil)
76
+ kredis_connection_with __method__, name, key, limit: limit, config: config, after_change: after_change, expires_in: expires_in
77
+ end
78
+
75
79
  def kredis_hash(name, key: nil, default: nil, typed: :string, config: :shared, after_change: nil)
76
80
  kredis_connection_with __method__, name, key, default: default, typed: typed, config: config, after_change: after_change
77
81
  end
@@ -3,13 +3,22 @@
3
3
  require "redis"
4
4
 
5
5
  module Kredis::Connections
6
+ DEFAULT_REDIS_URL = "redis://127.0.0.1:6379/0"
7
+ DEFAULT_REDIS_TIMEOUT = 1
8
+
6
9
  mattr_accessor :connections, default: Hash.new
7
10
  mattr_accessor :configurator
8
11
  mattr_accessor :connector, default: ->(config) { Redis.new(config) }
9
12
 
10
13
  def configured_for(name)
11
14
  connections[name] ||= Kredis.instrument :meta, message: "Connected to #{name}" do
12
- connector.call configurator.config_for("redis/#{name}")
15
+ if configurator.root.join("config/redis/#{name}.yml").exist?
16
+ connector.call configurator.config_for("redis/#{name}")
17
+ elsif name == :shared
18
+ Redis.new url: ENV.fetch("REDIS_URL", DEFAULT_REDIS_URL), timeout: DEFAULT_REDIS_TIMEOUT
19
+ else
20
+ raise "No configuration found for #{name}"
21
+ end
13
22
  end
14
23
  end
15
24
 
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ # A limiter is a specialized form of a counter that can be checked whether it has been exceeded and is provided fail safe. This means it can be used to guard login screens from brute force attacks without denying access in case Redis is offline.
4
+ #
5
+ # It will usually be used as an expiring limiter. Note that the limiter expires in total after the `expires_in` time used upon the first poke.
6
+ #
7
+ # It offers no guarentee that you can't poke yourself above the limit. You're responsible for checking `#exceeded?` yourself first, and this may produce a race condition. So only use this when the exact number of pokes is not critical.
8
+ class Kredis::Types::Limiter < Kredis::Types::Counter
9
+ class LimitExceeded < StandardError; end
10
+
11
+ attr_accessor :limit
12
+
13
+ def poke
14
+ failsafe returning: true do
15
+ increment
16
+ end
17
+ end
18
+
19
+ def exceeded?
20
+ failsafe returning: false do
21
+ value >= limit
22
+ end
23
+ end
24
+ end
data/lib/kredis/types.rb CHANGED
@@ -85,6 +85,10 @@ module Kredis::Types
85
85
  type_from(Slots, config, key, after_change: after_change, available: available)
86
86
  end
87
87
 
88
+ def limiter(key, limit:, expires_in: nil, config: :shared, after_change: nil)
89
+ type_from(Limiter, config, key, after_change: after_change, expires_in: expires_in, limit: limit)
90
+ end
91
+
88
92
  private
89
93
  def type_from(type_klass, config, key, after_change: nil, **options)
90
94
  type_klass.new(configured_for(config), namespaced_key(key), **options).then do |type|
@@ -107,3 +111,4 @@ require "kredis/types/unique_list"
107
111
  require "kredis/types/set"
108
112
  require "kredis/types/ordered_set"
109
113
  require "kredis/types/slots"
114
+ require "kredis/types/limiter"
@@ -1,3 +1,3 @@
1
1
  module Kredis
2
- VERSION = "1.6.0"
2
+ VERSION = "1.7.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kredis
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.0
4
+ version: 1.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kasper Timm Hansen
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2023-10-19 00:00:00.000000000 Z
12
+ date: 2023-12-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -102,6 +102,7 @@ files:
102
102
  - lib/kredis/types/enum.rb
103
103
  - lib/kredis/types/flag.rb
104
104
  - lib/kredis/types/hash.rb
105
+ - lib/kredis/types/limiter.rb
105
106
  - lib/kredis/types/list.rb
106
107
  - lib/kredis/types/ordered_set.rb
107
108
  - lib/kredis/types/proxy.rb
@@ -132,7 +133,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
132
133
  - !ruby/object:Gem::Version
133
134
  version: '0'
134
135
  requirements: []
135
- rubygems_version: 3.4.20
136
+ rubygems_version: 3.4.14
136
137
  signing_key:
137
138
  specification_version: 4
138
139
  summary: Higher-level data structures built on Redis.