kredis 1.4.0 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +76 -18
- data/lib/install/install.rb +2 -0
- data/lib/kredis/attributes.rb +42 -27
- data/lib/kredis/connections.rb +4 -4
- data/lib/kredis/default_values.rb +36 -0
- data/lib/kredis/log_subscriber.rb +2 -0
- data/lib/kredis/migration.rb +4 -2
- data/lib/kredis/namespace.rb +2 -0
- data/lib/kredis/railtie.rb +2 -0
- data/lib/kredis/type/boolean.rb +11 -0
- data/lib/kredis/type_casting.rb +5 -2
- data/lib/kredis/types/callbacks_proxy.rb +2 -0
- data/lib/kredis/types/counter.rb +11 -2
- data/lib/kredis/types/cycle.rb +2 -0
- data/lib/kredis/types/enum.rb +21 -4
- data/lib/kredis/types/flag.rb +9 -0
- data/lib/kredis/types/hash.rb +10 -1
- data/lib/kredis/types/list.rb +9 -0
- data/lib/kredis/types/ordered_set.rb +87 -0
- data/lib/kredis/types/proxy/failsafe.rb +2 -0
- data/lib/kredis/types/proxy.rb +12 -0
- data/lib/kredis/types/proxying.rb +10 -1
- data/lib/kredis/types/scalar.rb +10 -1
- data/lib/kredis/types/set.rb +9 -0
- data/lib/kredis/types/slots.rb +2 -0
- data/lib/kredis/types/unique_list.rb +3 -1
- data/lib/kredis/types.rb +19 -12
- data/lib/kredis/version.rb +1 -1
- data/lib/kredis.rb +3 -0
- data/lib/tasks/kredis/install.rake +2 -0
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 15ed6996059d28937ffa4f43a35e53d1e8fbc1894a30446575d9c00c390cd838
|
4
|
+
data.tar.gz: 296f80ea7719d69334d50240c9fce5969df4f8d976800013167c1fb0ebe6a0b3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cae34ebe3f21fe7c0e9cc0da5fc14bdc0d15931436bf7f07c552c14090489806990779ffd219be054f050468c809e23bf79302365f59f2dfced4b6a054ad352c
|
7
|
+
data.tar.gz: 96513897d1badc12f4fc6b2e51e017958f7e5eeaa5730d06bcb9d9a12d71ae09a4eb8ce2661e70a70647f4c4d7e5543a30451ab64d290b91de20d47602f30398
|
data/README.md
CHANGED
@@ -21,11 +21,11 @@ integer.value = 5 # => SET myinteger "5"
|
|
21
21
|
5 == integer.value # => GET myinteger
|
22
22
|
|
23
23
|
decimal = Kredis.decimal "mydecimal" # accuracy!
|
24
|
-
decimal.value = "%.47f" % (1.0/10) # => SET mydecimal "0.10000000000000000555111512312578270211815834045"
|
24
|
+
decimal.value = "%.47f" % (1.0 / 10) # => SET mydecimal "0.10000000000000000555111512312578270211815834045"
|
25
25
|
BigDecimal("0.10000000000000000555111512312578270211815834045e0") == decimal.value # => GET mydecimal
|
26
26
|
|
27
27
|
float = Kredis.float "myfloat" # speed!
|
28
|
-
float.value = 1.0/10 # => SET myfloat "0.1"
|
28
|
+
float.value = 1.0 / 10 # => SET myfloat "0.1"
|
29
29
|
0.1 == float.value # => GET myfloat
|
30
30
|
|
31
31
|
boolean = Kredis.boolean "myboolean"
|
@@ -49,10 +49,10 @@ list = Kredis.list "mylist"
|
|
49
49
|
list << "hello world!" # => RPUSH mylist "hello world!"
|
50
50
|
[ "hello world!" ] == list.elements # => LRANGE mylist 0, -1
|
51
51
|
|
52
|
-
integer_list = Kredis.list "myintegerlist", typed: :integer
|
53
|
-
integer_list.append([
|
54
|
-
integer_list <<
|
55
|
-
[ 1, 2, 3, 4 ] == integer_list.elements
|
52
|
+
integer_list = Kredis.list "myintegerlist", typed: :integer, default: [ 1, 2, 3 ] # => EXISTS? myintegerlist, RPUSH myintegerlist "1" "2" "3"
|
53
|
+
integer_list.append([ 4, 5, 6 ]) # => RPUSH myintegerlist "4" "5" "6"
|
54
|
+
integer_list << 7 # => RPUSH myintegerlist "7"
|
55
|
+
[ 1, 2, 3, 4, 5, 6, 7 ] == integer_list.elements # => LRANGE myintegerlist 0 -1
|
56
56
|
|
57
57
|
unique_list = Kredis.unique_list "myuniquelist"
|
58
58
|
unique_list.append(%w[ 2 3 4 ]) # => LREM myuniquelist 0, "2" + LREM myuniquelist 0, "3" + LREM myuniquelist 0, "4" + RPUSH myuniquelist "2", "3", "4"
|
@@ -62,6 +62,14 @@ unique_list << "5" # => LREM myuniquelist 0, "5" + R
|
|
62
62
|
unique_list.remove(3) # => LREM myuniquelist 0, "3"
|
63
63
|
[ "4", "2", "1", "5" ] == unique_list.elements # => LRANGE myuniquelist 0, -1
|
64
64
|
|
65
|
+
ordered_set = Kredis.ordered_set "myorderedset"
|
66
|
+
ordered_set.append(%w[ 2 3 4 ]) # => ZADD myorderedset 1646131025.4953232 2 1646131025.495326 3 1646131025.4953272 4
|
67
|
+
ordered_set.prepend(%w[ 1 2 3 4 ]) # => ZADD myorderedset -1646131025.4957051 1 -1646131025.495707 2 -1646131025.4957082 3 -1646131025.4957092 4
|
68
|
+
ordered_set.append([])
|
69
|
+
ordered_set << "5" # => ZADD myorderedset 1646131025.4960442 5
|
70
|
+
ordered_set.remove(3) # => ZREM myorderedset 3
|
71
|
+
[ "4", "2", "1", "5" ] == ordered_set.elements # => ZRANGE myorderedset 0 -1
|
72
|
+
|
65
73
|
set = Kredis.set "myset", typed: :datetime
|
66
74
|
set.add(DateTime.tomorrow, DateTime.yesterday) # => SADD myset "2021-02-03 00:00:00 +0100" "2021-02-01 00:00:00 +0100"
|
67
75
|
set << DateTime.tomorrow # => SADD myset "2021-02-03 00:00:00 +0100"
|
@@ -155,15 +163,7 @@ sleep 0.6.seconds
|
|
155
163
|
false == flag.marked? #=> EXISTS myflag
|
156
164
|
```
|
157
165
|
|
158
|
-
|
159
|
-
|
160
|
-
```ruby
|
161
|
-
one_string = Kredis.string "mystring"
|
162
|
-
two_string = Kredis.string "mystring", config: :secondary
|
163
|
-
|
164
|
-
one_string.value = "just on shared"
|
165
|
-
two_string.value != one_string.value
|
166
|
-
```
|
166
|
+
### Models
|
167
167
|
|
168
168
|
You can use all these structures in models:
|
169
169
|
|
@@ -189,6 +189,29 @@ person.morning.value = "blue" # => SET people:5:morning
|
|
189
189
|
true == person.morning.blue? # => GET people:5:morning
|
190
190
|
```
|
191
191
|
|
192
|
+
### Default values
|
193
|
+
|
194
|
+
You can set a default value for all types. For example:
|
195
|
+
|
196
|
+
```ruby
|
197
|
+
list = Kredis.list "favorite_colors", default: [ "red", "green", "blue" ]
|
198
|
+
|
199
|
+
# or, in a model
|
200
|
+
class Person < ApplicationRecord
|
201
|
+
kredis_string :name, default: "Unknown"
|
202
|
+
kredis_list :favorite_colors, default: [ "red", "green", "blue" ]
|
203
|
+
end
|
204
|
+
```
|
205
|
+
|
206
|
+
There's a performance overhead to consider though. When you first read or write an attribute in a model, Kredis will
|
207
|
+
check if the underlying Redis key exists, while watching for concurrent changes, and if it does not,
|
208
|
+
write the specified default value.
|
209
|
+
|
210
|
+
This means that using default values in a typical Rails app additional Redis calls (WATCH, EXISTS, UNWATCH) will be
|
211
|
+
executed for each Kredis attribute with a default value read or written during a request.
|
212
|
+
|
213
|
+
### Callbacks
|
214
|
+
|
192
215
|
You can also define `after_change` callbacks that trigger on mutations:
|
193
216
|
|
194
217
|
```ruby
|
@@ -201,6 +224,18 @@ class Person < ApplicationRecord
|
|
201
224
|
end
|
202
225
|
```
|
203
226
|
|
227
|
+
### Multiple Redis servers
|
228
|
+
|
229
|
+
And using structures on a different than the default `shared` redis instance, relying on `config/redis/secondary.yml`:
|
230
|
+
|
231
|
+
```ruby
|
232
|
+
one_string = Kredis.string "mystring"
|
233
|
+
two_string = Kredis.string "mystring", config: :secondary
|
234
|
+
|
235
|
+
one_string.value = "just on shared"
|
236
|
+
two_string.value != one_string.value
|
237
|
+
```
|
238
|
+
|
204
239
|
## Installation
|
205
240
|
|
206
241
|
1. Run `./bin/bundle add kredis`
|
@@ -220,14 +255,14 @@ If you need to connect to Redis with SSL, the recommended approach is to set you
|
|
220
255
|
|
221
256
|
```ruby
|
222
257
|
Kredis::Connections.connections[:shared] = Redis.new(
|
223
|
-
url: ENV[
|
258
|
+
url: ENV["REDIS_URL"],
|
224
259
|
ssl_params: {
|
225
260
|
cert_store: OpenSSL::X509::Store.new.tap { |store|
|
226
|
-
store.add_file(Rails.root.join(
|
261
|
+
store.add_file(Rails.root.join("config", "ca_cert.pem").to_s)
|
227
262
|
},
|
228
263
|
|
229
264
|
cert: OpenSSL::X509::Certificate.new(File.read(
|
230
|
-
Rails.root.join(
|
265
|
+
Rails.root.join("config", "client.crt")
|
231
266
|
)),
|
232
267
|
|
233
268
|
key: OpenSSL::PKey::RSA.new(
|
@@ -251,6 +286,29 @@ config.kredis.connector = ->(config) { SomeRedisProxy.new(config) }
|
|
251
286
|
|
252
287
|
By default Kredis will use `Redis.new(config)`.
|
253
288
|
|
289
|
+
## Development
|
290
|
+
|
291
|
+
A development console is available by running `bin/console`.
|
292
|
+
|
293
|
+
From there, you can experiment with Kredis. e.g.
|
294
|
+
|
295
|
+
```erb
|
296
|
+
>> str = Kredis.string "mystring"
|
297
|
+
Kredis (0.1ms) Connected to shared
|
298
|
+
=>
|
299
|
+
#<Kredis::Types::Scalar:0x0000000134c7d938
|
300
|
+
...
|
301
|
+
>> str.value = "hello, world"
|
302
|
+
Kredis Proxy (2.4ms) SET mystring ["hello, world"]
|
303
|
+
=> "hello, world"
|
304
|
+
>> str.value
|
305
|
+
```
|
306
|
+
|
307
|
+
Run tests with `bin/test`.
|
308
|
+
|
309
|
+
[`debug`](https://github.com/ruby/debug) can be used in the development console and in the test suite by inserting a
|
310
|
+
breakpoint, e.g. `debugger`.
|
311
|
+
|
254
312
|
## License
|
255
313
|
|
256
314
|
Kredis is released under the [MIT License](https://opensource.org/licenses/MIT).
|
data/lib/install/install.rb
CHANGED
data/lib/kredis/attributes.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Kredis::Attributes
|
2
4
|
extend ActiveSupport::Concern
|
3
5
|
|
@@ -6,52 +8,56 @@ module Kredis::Attributes
|
|
6
8
|
kredis_connection_with __method__, name, key, config: config, after_change: after_change
|
7
9
|
end
|
8
10
|
|
9
|
-
def kredis_string(name, key: nil, config: :shared, after_change: nil, expires_in: nil)
|
10
|
-
kredis_connection_with __method__, name, key, config: config, after_change: after_change, expires_in: expires_in
|
11
|
+
def kredis_string(name, key: nil, default: nil, config: :shared, after_change: nil, expires_in: nil)
|
12
|
+
kredis_connection_with __method__, name, key, default: default, config: config, after_change: after_change, expires_in: expires_in
|
11
13
|
end
|
12
14
|
|
13
|
-
def kredis_integer(name, key: nil, config: :shared, after_change: nil, expires_in: nil)
|
14
|
-
kredis_connection_with __method__, name, key, config: config, after_change: after_change, expires_in: expires_in
|
15
|
+
def kredis_integer(name, key: nil, default: nil, config: :shared, after_change: nil, expires_in: nil)
|
16
|
+
kredis_connection_with __method__, name, key, default: default, config: config, after_change: after_change, expires_in: expires_in
|
15
17
|
end
|
16
18
|
|
17
|
-
def kredis_decimal(name, key: nil, config: :shared, after_change: nil, expires_in: nil)
|
18
|
-
kredis_connection_with __method__, name, key, config: config, after_change: after_change, expires_in: expires_in
|
19
|
+
def kredis_decimal(name, key: nil, default: nil, config: :shared, after_change: nil, expires_in: nil)
|
20
|
+
kredis_connection_with __method__, name, key, default: default, config: config, after_change: after_change, expires_in: expires_in
|
19
21
|
end
|
20
22
|
|
21
|
-
def kredis_datetime(name, key: nil, config: :shared, after_change: nil, expires_in: nil)
|
22
|
-
kredis_connection_with __method__, name, key, config: config, after_change: after_change, expires_in: expires_in
|
23
|
+
def kredis_datetime(name, key: nil, default: nil, config: :shared, after_change: nil, expires_in: nil)
|
24
|
+
kredis_connection_with __method__, name, key, default: default, config: config, after_change: after_change, expires_in: expires_in
|
23
25
|
end
|
24
26
|
|
25
|
-
def kredis_flag(name, key: nil, config: :shared, after_change: nil, expires_in: nil)
|
26
|
-
kredis_connection_with __method__, name, key, config: config, after_change: after_change, expires_in: expires_in
|
27
|
+
def kredis_flag(name, key: nil, default: nil, config: :shared, after_change: nil, expires_in: nil)
|
28
|
+
kredis_connection_with __method__, name, key, default: default, config: config, after_change: after_change, expires_in: expires_in
|
27
29
|
|
28
30
|
define_method("#{name}?") do
|
29
31
|
send(name).marked?
|
30
32
|
end
|
31
33
|
end
|
32
34
|
|
33
|
-
def kredis_float(name, key: nil, config: :shared, after_change: nil, expires_in: nil)
|
34
|
-
kredis_connection_with __method__, name, key, config: config, after_change: after_change, expires_in: expires_in
|
35
|
+
def kredis_float(name, key: nil, default: nil, config: :shared, after_change: nil, expires_in: nil)
|
36
|
+
kredis_connection_with __method__, name, key, default: default, config: config, after_change: after_change, expires_in: expires_in
|
35
37
|
end
|
36
38
|
|
37
39
|
def kredis_enum(name, key: nil, values:, default:, config: :shared, after_change: nil)
|
38
40
|
kredis_connection_with __method__, name, key, values: values, default: default, config: config, after_change: after_change
|
39
41
|
end
|
40
42
|
|
41
|
-
def kredis_json(name, key: nil, config: :shared, after_change: nil, expires_in: nil)
|
42
|
-
kredis_connection_with __method__, name, key, config: config, after_change: after_change, expires_in: expires_in
|
43
|
+
def kredis_json(name, key: nil, default: nil, config: :shared, after_change: nil, expires_in: nil)
|
44
|
+
kredis_connection_with __method__, name, key, default: default, config: config, after_change: after_change, expires_in: expires_in
|
45
|
+
end
|
46
|
+
|
47
|
+
def kredis_list(name, key: nil, default: nil, typed: :string, config: :shared, after_change: nil)
|
48
|
+
kredis_connection_with __method__, name, key, default: default, typed: typed, config: config, after_change: after_change
|
43
49
|
end
|
44
50
|
|
45
|
-
def
|
46
|
-
kredis_connection_with __method__, name, key, typed: typed, config: config, after_change: after_change
|
51
|
+
def kredis_unique_list(name, limit: nil, key: nil, default: nil, typed: :string, config: :shared, after_change: nil)
|
52
|
+
kredis_connection_with __method__, name, key, default: default, limit: limit, typed: typed, config: config, after_change: after_change
|
47
53
|
end
|
48
54
|
|
49
|
-
def
|
50
|
-
kredis_connection_with __method__, name, key,
|
55
|
+
def kredis_set(name, key: nil, default: nil, typed: :string, config: :shared, after_change: nil)
|
56
|
+
kredis_connection_with __method__, name, key, default: default, typed: typed, config: config, after_change: after_change
|
51
57
|
end
|
52
58
|
|
53
|
-
def
|
54
|
-
kredis_connection_with __method__, name, key, typed: typed, config: config, after_change: after_change
|
59
|
+
def kredis_ordered_set(name, limit: nil, default: nil, key: nil, typed: :string, config: :shared, after_change: nil)
|
60
|
+
kredis_connection_with __method__, name, key, default: default, limit: limit, typed: typed, config: config, after_change: after_change
|
55
61
|
end
|
56
62
|
|
57
63
|
def kredis_slot(name, key: nil, config: :shared, after_change: nil)
|
@@ -62,16 +68,16 @@ module Kredis::Attributes
|
|
62
68
|
kredis_connection_with __method__, name, key, available: available, config: config, after_change: after_change
|
63
69
|
end
|
64
70
|
|
65
|
-
def kredis_counter(name, key: nil, config: :shared, after_change: nil, expires_in: nil)
|
66
|
-
kredis_connection_with __method__, name, key, config: config, after_change: after_change, expires_in: expires_in
|
71
|
+
def kredis_counter(name, key: nil, default: nil, config: :shared, after_change: nil, expires_in: nil)
|
72
|
+
kredis_connection_with __method__, name, key, default: default, config: config, after_change: after_change, expires_in: expires_in
|
67
73
|
end
|
68
74
|
|
69
|
-
def kredis_hash(name, key: nil, typed: :string, config: :shared, after_change: nil)
|
70
|
-
kredis_connection_with __method__, name, key, typed: typed, config: config, after_change: after_change
|
75
|
+
def kredis_hash(name, key: nil, default: nil, typed: :string, config: :shared, after_change: nil)
|
76
|
+
kredis_connection_with __method__, name, key, default: default, typed: typed, config: config, after_change: after_change
|
71
77
|
end
|
72
78
|
|
73
|
-
def kredis_boolean(name, key: nil, config: :shared, after_change: nil, expires_in: nil)
|
74
|
-
kredis_connection_with __method__, name, key, config: config, after_change: after_change, expires_in: expires_in
|
79
|
+
def kredis_boolean(name, key: nil, default: nil, config: :shared, after_change: nil, expires_in: nil)
|
80
|
+
kredis_connection_with __method__, name, key, default: default, config: config, after_change: after_change, expires_in: expires_in
|
75
81
|
end
|
76
82
|
|
77
83
|
private
|
@@ -84,6 +90,7 @@ module Kredis::Attributes
|
|
84
90
|
if instance_variable_defined?(ivar_symbol)
|
85
91
|
instance_variable_get(ivar_symbol)
|
86
92
|
else
|
93
|
+
options[:default] = kredis_default_evaluated(options[:default]) if options[:default]
|
87
94
|
new_type = Kredis.send(type, kredis_key_evaluated(key) || kredis_key_for_attribute(name), **options)
|
88
95
|
instance_variable_set ivar_symbol,
|
89
96
|
after_change ? enrich_after_change_with_record_access(new_type, after_change) : new_type
|
@@ -102,7 +109,7 @@ module Kredis::Attributes
|
|
102
109
|
end
|
103
110
|
|
104
111
|
def kredis_key_for_attribute(name)
|
105
|
-
"#{self.class.name.tableize.
|
112
|
+
"#{self.class.name.tableize.tr("/", ":")}:#{extract_kredis_id}:#{name}"
|
106
113
|
end
|
107
114
|
|
108
115
|
def extract_kredis_id
|
@@ -115,4 +122,12 @@ module Kredis::Attributes
|
|
115
122
|
when Symbol then Kredis::Types::CallbacksProxy.new(type, ->(_) { send(original_after_change) })
|
116
123
|
end
|
117
124
|
end
|
125
|
+
|
126
|
+
def kredis_default_evaluated(default)
|
127
|
+
case default
|
128
|
+
when Proc then Proc.new { default.call(self) }
|
129
|
+
when Symbol then send(default)
|
130
|
+
else default
|
131
|
+
end
|
132
|
+
end
|
118
133
|
end
|
data/lib/kredis/connections.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "redis"
|
2
4
|
|
3
5
|
module Kredis::Connections
|
@@ -6,10 +8,8 @@ module Kredis::Connections
|
|
6
8
|
mattr_accessor :connector, default: ->(config) { Redis.new(config) }
|
7
9
|
|
8
10
|
def configured_for(name)
|
9
|
-
connections[name] ||=
|
10
|
-
|
11
|
-
connector.call configurator.config_for("redis/#{name}")
|
12
|
-
end
|
11
|
+
connections[name] ||= Kredis.instrument :meta, message: "Connected to #{name}" do
|
12
|
+
connector.call configurator.config_for("redis/#{name}")
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kredis::DefaultValues
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
prepended do
|
7
|
+
attr_writer :default
|
8
|
+
|
9
|
+
proxying :watch, :unwatch, :exists?
|
10
|
+
|
11
|
+
def default
|
12
|
+
case @default
|
13
|
+
when Proc then @default.call
|
14
|
+
when Symbol then send(@default)
|
15
|
+
else @default
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
def set_default
|
21
|
+
raise NotImplementedError, "Kredis type #{self.class} needs to define #set_default"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def initialize(...)
|
26
|
+
super
|
27
|
+
|
28
|
+
if default
|
29
|
+
watch do
|
30
|
+
set_default unless exists?
|
31
|
+
|
32
|
+
unwatch
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/kredis/migration.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/core_ext/module/delegation"
|
2
4
|
|
3
5
|
class Kredis::Migration
|
@@ -33,10 +35,10 @@ class Kredis::Migration
|
|
33
35
|
def delete_all(*key_patterns)
|
34
36
|
log_migration "DELETE ALL #{key_patterns.inspect}" do
|
35
37
|
if key_patterns.length > 1
|
36
|
-
@redis.del
|
38
|
+
@redis.del(*key_patterns)
|
37
39
|
else
|
38
40
|
each_key_batch_matching(key_patterns.first) do |keys, pipeline|
|
39
|
-
pipeline.del
|
41
|
+
pipeline.del(*keys)
|
40
42
|
end
|
41
43
|
end
|
42
44
|
end
|
data/lib/kredis/namespace.rb
CHANGED
data/lib/kredis/railtie.rb
CHANGED
data/lib/kredis/type_casting.rb
CHANGED
@@ -1,7 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "json"
|
2
4
|
require "active_model/type"
|
3
|
-
require "kredis/type/
|
5
|
+
require "kredis/type/boolean"
|
4
6
|
require "kredis/type/datetime"
|
7
|
+
require "kredis/type/json"
|
5
8
|
|
6
9
|
module Kredis::TypeCasting
|
7
10
|
class InvalidType < StandardError; end
|
@@ -11,7 +14,7 @@ module Kredis::TypeCasting
|
|
11
14
|
integer: ActiveModel::Type::Integer.new,
|
12
15
|
decimal: ActiveModel::Type::Decimal.new,
|
13
16
|
float: ActiveModel::Type::Float.new,
|
14
|
-
boolean:
|
17
|
+
boolean: Kredis::Type::Boolean.new,
|
15
18
|
datetime: Kredis::Type::DateTime.new,
|
16
19
|
json: Kredis::Type::Json.new
|
17
20
|
}
|
data/lib/kredis/types/counter.rb
CHANGED
@@ -1,18 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Kredis::Types::Counter < Kredis::Types::Proxying
|
4
|
+
prepend Kredis::DefaultValues
|
5
|
+
|
2
6
|
proxying :multi, :set, :incrby, :decrby, :get, :del, :exists?
|
3
7
|
|
4
8
|
attr_accessor :expires_in
|
5
9
|
|
6
10
|
def increment(by: 1)
|
7
11
|
multi do
|
8
|
-
set 0, ex: expires_in, nx: true
|
12
|
+
set 0, ex: expires_in, nx: true if expires_in
|
9
13
|
incrby by
|
10
14
|
end[-1]
|
11
15
|
end
|
12
16
|
|
13
17
|
def decrement(by: 1)
|
14
18
|
multi do
|
15
|
-
set 0, ex: expires_in, nx: true
|
19
|
+
set 0, ex: expires_in, nx: true if expires_in
|
16
20
|
decrby by
|
17
21
|
end[-1]
|
18
22
|
end
|
@@ -24,4 +28,9 @@ class Kredis::Types::Counter < Kredis::Types::Proxying
|
|
24
28
|
def reset
|
25
29
|
del
|
26
30
|
end
|
31
|
+
|
32
|
+
private
|
33
|
+
def set_default
|
34
|
+
increment by: default
|
35
|
+
end
|
27
36
|
end
|
data/lib/kredis/types/cycle.rb
CHANGED
data/lib/kredis/types/enum.rb
CHANGED
@@ -1,9 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/core_ext/object/inclusion"
|
2
4
|
|
3
5
|
class Kredis::Types::Enum < Kredis::Types::Proxying
|
4
|
-
|
6
|
+
prepend Kredis::DefaultValues
|
7
|
+
|
8
|
+
InvalidDefault = Class.new(StandardError)
|
5
9
|
|
6
|
-
|
10
|
+
proxying :set, :get, :del, :exists?, :multi
|
11
|
+
|
12
|
+
attr_accessor :values
|
7
13
|
|
8
14
|
def initialize(...)
|
9
15
|
super
|
@@ -17,11 +23,14 @@ class Kredis::Types::Enum < Kredis::Types::Proxying
|
|
17
23
|
end
|
18
24
|
|
19
25
|
def value
|
20
|
-
get
|
26
|
+
get
|
21
27
|
end
|
22
28
|
|
23
29
|
def reset
|
24
|
-
|
30
|
+
multi do
|
31
|
+
del
|
32
|
+
set_default
|
33
|
+
end
|
25
34
|
end
|
26
35
|
|
27
36
|
private
|
@@ -31,4 +40,12 @@ class Kredis::Types::Enum < Kredis::Types::Proxying
|
|
31
40
|
define_singleton_method("#{defined_value}!") { self.value = defined_value }
|
32
41
|
end
|
33
42
|
end
|
43
|
+
|
44
|
+
def set_default
|
45
|
+
if default.in?(values) || default.nil?
|
46
|
+
set default
|
47
|
+
else
|
48
|
+
raise InvalidDefault, "Default value #{default.inspect} for #{key} is not a valid option (Valid values: #{values.join(", ")})"
|
49
|
+
end
|
50
|
+
end
|
34
51
|
end
|
data/lib/kredis/types/flag.rb
CHANGED
@@ -1,4 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Kredis::Types::Flag < Kredis::Types::Proxying
|
4
|
+
prepend Kredis::DefaultValues
|
5
|
+
|
2
6
|
proxying :set, :exists?, :del
|
3
7
|
|
4
8
|
attr_accessor :expires_in
|
@@ -14,4 +18,9 @@ class Kredis::Types::Flag < Kredis::Types::Proxying
|
|
14
18
|
def remove
|
15
19
|
del
|
16
20
|
end
|
21
|
+
|
22
|
+
private
|
23
|
+
def set_default
|
24
|
+
mark if default
|
25
|
+
end
|
17
26
|
end
|
data/lib/kredis/types/hash.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/core_ext/hash"
|
2
4
|
|
3
5
|
class Kredis::Types::Hash < Kredis::Types::Proxying
|
6
|
+
prepend Kredis::DefaultValues
|
7
|
+
|
4
8
|
proxying :hget, :hset, :hmget, :hdel, :hgetall, :hkeys, :hvals, :del, :exists?
|
5
9
|
|
6
10
|
attr_accessor :typed
|
@@ -14,7 +18,7 @@ class Kredis::Types::Hash < Kredis::Types::Proxying
|
|
14
18
|
end
|
15
19
|
|
16
20
|
def update(**entries)
|
17
|
-
hset entries.transform_values{ |val| type_to_string(val, typed) } if entries.flatten.any?
|
21
|
+
hset entries.transform_values { |val| type_to_string(val, typed) } if entries.flatten.any?
|
18
22
|
end
|
19
23
|
|
20
24
|
def values_at(*keys)
|
@@ -42,4 +46,9 @@ class Kredis::Types::Hash < Kredis::Types::Proxying
|
|
42
46
|
def values
|
43
47
|
strings_to_types(hvals || [], typed)
|
44
48
|
end
|
49
|
+
|
50
|
+
private
|
51
|
+
def set_default
|
52
|
+
update(**default)
|
53
|
+
end
|
45
54
|
end
|
data/lib/kredis/types/list.rb
CHANGED
@@ -1,4 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Kredis::Types::List < Kredis::Types::Proxying
|
4
|
+
prepend Kredis::DefaultValues
|
5
|
+
|
2
6
|
proxying :lrange, :lrem, :lpush, :ltrim, :rpush, :exists?, :del
|
3
7
|
|
4
8
|
attr_accessor :typed
|
@@ -28,4 +32,9 @@ class Kredis::Types::List < Kredis::Types::Proxying
|
|
28
32
|
def last(n = nil)
|
29
33
|
n ? lrange(-n, -1) : lrange(-1, -1).first
|
30
34
|
end
|
35
|
+
|
36
|
+
private
|
37
|
+
def set_default
|
38
|
+
append default
|
39
|
+
end
|
31
40
|
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Kredis::Types::OrderedSet < Kredis::Types::Proxying
|
4
|
+
prepend Kredis::DefaultValues
|
5
|
+
|
6
|
+
proxying :multi, :zrange, :zrem, :zadd, :zremrangebyrank, :zcard, :exists?, :del, :zscore
|
7
|
+
|
8
|
+
attr_accessor :typed
|
9
|
+
attr_reader :limit
|
10
|
+
|
11
|
+
def elements
|
12
|
+
strings_to_types(zrange(0, -1) || [], typed)
|
13
|
+
end
|
14
|
+
alias to_a elements
|
15
|
+
|
16
|
+
def remove(*elements)
|
17
|
+
zrem(types_to_strings(elements, typed))
|
18
|
+
end
|
19
|
+
|
20
|
+
def include?(element)
|
21
|
+
!!zscore(type_to_string(element, typed))
|
22
|
+
end
|
23
|
+
|
24
|
+
def prepend(elements)
|
25
|
+
insert(elements, prepending: true)
|
26
|
+
end
|
27
|
+
|
28
|
+
def append(elements)
|
29
|
+
insert(elements)
|
30
|
+
end
|
31
|
+
alias << append
|
32
|
+
|
33
|
+
def limit=(limit)
|
34
|
+
raise "Limit must be greater than 0" if limit && limit <= 0
|
35
|
+
|
36
|
+
@limit = limit
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
def insert(elements, prepending: false)
|
41
|
+
elements = Array(elements)
|
42
|
+
return if elements.empty?
|
43
|
+
|
44
|
+
elements_with_scores = types_to_strings(elements, typed).map.with_index do |element, index|
|
45
|
+
incremental_score = index * 0.000001
|
46
|
+
|
47
|
+
score = if prepending
|
48
|
+
-base_score - incremental_score
|
49
|
+
else
|
50
|
+
base_score + incremental_score
|
51
|
+
end
|
52
|
+
|
53
|
+
[ score, element ]
|
54
|
+
end
|
55
|
+
|
56
|
+
multi do
|
57
|
+
zadd(elements_with_scores)
|
58
|
+
trim(from_beginning: prepending)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def base_score
|
63
|
+
process_start_time + process_uptime
|
64
|
+
end
|
65
|
+
|
66
|
+
def process_start_time
|
67
|
+
@process_start_time ||= unproxied_redis.time.join(".").to_f - process_uptime
|
68
|
+
end
|
69
|
+
|
70
|
+
def process_uptime
|
71
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
72
|
+
end
|
73
|
+
|
74
|
+
def trim(from_beginning:)
|
75
|
+
return unless limit
|
76
|
+
|
77
|
+
if from_beginning
|
78
|
+
zremrangebyrank(limit, -1)
|
79
|
+
else
|
80
|
+
zremrangebyrank(0, -(limit + 1))
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def set_default
|
85
|
+
append default
|
86
|
+
end
|
87
|
+
end
|
data/lib/kredis/types/proxy.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Kredis::Types::Proxy
|
2
4
|
require_relative "proxy/failsafe"
|
3
5
|
include Failsafe
|
@@ -20,6 +22,16 @@ class Kredis::Types::Proxy
|
|
20
22
|
end
|
21
23
|
end
|
22
24
|
|
25
|
+
def watch(&block)
|
26
|
+
redis.watch(key) do
|
27
|
+
block.call
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def unwatch
|
32
|
+
redis.unwatch
|
33
|
+
end
|
34
|
+
|
23
35
|
def method_missing(method, *args, **kwargs)
|
24
36
|
Kredis.instrument :proxy, **log_message(method, *args, **kwargs) do
|
25
37
|
failsafe do
|
@@ -1,13 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/core_ext/module/delegation"
|
2
4
|
|
3
5
|
class Kredis::Types::Proxying
|
4
6
|
attr_accessor :proxy, :key
|
5
7
|
|
6
8
|
def self.proxying(*commands)
|
7
|
-
delegate
|
9
|
+
delegate(*commands, to: :proxy)
|
8
10
|
end
|
9
11
|
|
10
12
|
def initialize(redis, key, **options)
|
13
|
+
@redis = redis
|
11
14
|
@key = key
|
12
15
|
@proxy = Kredis::Types::Proxy.new(redis, key)
|
13
16
|
options.each { |key, value| send("#{key}=", value) }
|
@@ -17,6 +20,12 @@ class Kredis::Types::Proxying
|
|
17
20
|
proxy.suppress_failsafe_with(returning: returning, &block)
|
18
21
|
end
|
19
22
|
|
23
|
+
def unproxied_redis
|
24
|
+
# Generally, this should not be used. It's only here for the rare case where we need to
|
25
|
+
# call Redis commands that don't reference a key and don't want to be pipelined.
|
26
|
+
@redis
|
27
|
+
end
|
28
|
+
|
20
29
|
private
|
21
30
|
delegate :type_to_string, :string_to_type, :types_to_strings, :strings_to_types, to: :Kredis
|
22
31
|
end
|
data/lib/kredis/types/scalar.rb
CHANGED
@@ -1,7 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Kredis::Types::Scalar < Kredis::Types::Proxying
|
4
|
+
prepend Kredis::DefaultValues
|
5
|
+
|
2
6
|
proxying :set, :get, :exists?, :del, :expire, :expireat
|
3
7
|
|
4
|
-
attr_accessor :typed, :
|
8
|
+
attr_accessor :typed, :expires_in
|
5
9
|
|
6
10
|
def value=(value)
|
7
11
|
set type_to_string(value, typed), ex: expires_in
|
@@ -36,4 +40,9 @@ class Kredis::Types::Scalar < Kredis::Types::Proxying
|
|
36
40
|
def expire_at(datetime)
|
37
41
|
expireat datetime.to_i
|
38
42
|
end
|
43
|
+
|
44
|
+
private
|
45
|
+
def set_default
|
46
|
+
self.value = default
|
47
|
+
end
|
39
48
|
end
|
data/lib/kredis/types/set.rb
CHANGED
@@ -1,4 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Kredis::Types::Set < Kredis::Types::Proxying
|
4
|
+
prepend Kredis::DefaultValues
|
5
|
+
|
2
6
|
proxying :smembers, :sadd, :srem, :multi, :del, :sismember, :scard, :spop, :exists?, :srandmember
|
3
7
|
|
4
8
|
attr_accessor :typed
|
@@ -47,4 +51,9 @@ class Kredis::Types::Set < Kredis::Types::Proxying
|
|
47
51
|
strings_to_types(srandmember(count), typed)
|
48
52
|
end
|
49
53
|
end
|
54
|
+
|
55
|
+
private
|
56
|
+
def set_default
|
57
|
+
add default
|
58
|
+
end
|
50
59
|
end
|
data/lib/kredis/types/slots.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# You'd normally call this a set, but Redis already has another data type for that
|
2
4
|
class Kredis::Types::UniqueList < Kredis::Types::List
|
3
5
|
proxying :multi, :ltrim, :exists?
|
@@ -22,7 +24,7 @@ class Kredis::Types::UniqueList < Kredis::Types::List
|
|
22
24
|
multi do
|
23
25
|
remove elements
|
24
26
|
super
|
25
|
-
ltrim
|
27
|
+
ltrim(-limit, -1) if limit
|
26
28
|
end
|
27
29
|
end
|
28
30
|
alias << append
|
data/lib/kredis/types.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Kredis::Types
|
2
4
|
autoload :CallbacksProxy, "kredis/types/callbacks_proxy"
|
3
5
|
|
@@ -39,36 +41,40 @@ module Kredis::Types
|
|
39
41
|
end
|
40
42
|
|
41
43
|
|
42
|
-
def counter(key, expires_in: nil, config: :shared, after_change: nil)
|
43
|
-
type_from(Counter, config, key, after_change: after_change, expires_in: expires_in)
|
44
|
+
def counter(key, expires_in: nil, default: nil, config: :shared, after_change: nil)
|
45
|
+
type_from(Counter, config, key, after_change: after_change, default: default, expires_in: expires_in)
|
44
46
|
end
|
45
47
|
|
46
48
|
def cycle(key, values:, expires_in: nil, config: :shared, after_change: nil)
|
47
49
|
type_from(Cycle, config, key, after_change: after_change, values: values, expires_in: expires_in)
|
48
50
|
end
|
49
51
|
|
50
|
-
def flag(key, config: :shared, after_change: nil, expires_in: nil)
|
51
|
-
type_from(Flag, config, key, after_change: after_change, expires_in: expires_in)
|
52
|
+
def flag(key, default: nil, config: :shared, after_change: nil, expires_in: nil)
|
53
|
+
type_from(Flag, config, key, after_change: after_change, default: default, expires_in: expires_in)
|
52
54
|
end
|
53
55
|
|
54
56
|
def enum(key, values:, default:, config: :shared, after_change: nil)
|
55
57
|
type_from(Enum, config, key, after_change: after_change, values: values, default: default)
|
56
58
|
end
|
57
59
|
|
58
|
-
def hash(key, typed: :string, config: :shared, after_change: nil)
|
59
|
-
type_from(Hash, config, key, after_change: after_change, typed: typed)
|
60
|
+
def hash(key, typed: :string, default: nil, config: :shared, after_change: nil)
|
61
|
+
type_from(Hash, config, key, after_change: after_change, default: default, typed: typed)
|
62
|
+
end
|
63
|
+
|
64
|
+
def list(key, default: nil, typed: :string, config: :shared, after_change: nil)
|
65
|
+
type_from(List, config, key, after_change: after_change, default: default, typed: typed)
|
60
66
|
end
|
61
67
|
|
62
|
-
def
|
63
|
-
type_from(
|
68
|
+
def unique_list(key, default: nil, typed: :string, limit: nil, config: :shared, after_change: nil)
|
69
|
+
type_from(UniqueList, config, key, after_change: after_change, default: default, typed: typed, limit: limit)
|
64
70
|
end
|
65
71
|
|
66
|
-
def
|
67
|
-
type_from(
|
72
|
+
def set(key, default: nil, typed: :string, config: :shared, after_change: nil)
|
73
|
+
type_from(Set, config, key, after_change: after_change, default: default, typed: typed)
|
68
74
|
end
|
69
75
|
|
70
|
-
def
|
71
|
-
type_from(
|
76
|
+
def ordered_set(key, default: nil, typed: :string, limit: nil, config: :shared, after_change: nil)
|
77
|
+
type_from(OrderedSet, config, key, after_change: after_change, default: default, typed: typed, limit: limit)
|
72
78
|
end
|
73
79
|
|
74
80
|
def slot(key, config: :shared, after_change: nil)
|
@@ -99,4 +105,5 @@ require "kredis/types/hash"
|
|
99
105
|
require "kredis/types/list"
|
100
106
|
require "kredis/types/unique_list"
|
101
107
|
require "kredis/types/set"
|
108
|
+
require "kredis/types/ordered_set"
|
102
109
|
require "kredis/types/slots"
|
data/lib/kredis/version.rb
CHANGED
data/lib/kredis.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support"
|
2
4
|
require "active_support/core_ext/module/attribute_accessors"
|
3
5
|
require "active_support/core_ext/module/attribute_accessors_per_thread"
|
@@ -8,6 +10,7 @@ require "kredis/connections"
|
|
8
10
|
require "kredis/log_subscriber"
|
9
11
|
require "kredis/namespace"
|
10
12
|
require "kredis/type_casting"
|
13
|
+
require "kredis/default_values"
|
11
14
|
require "kredis/types"
|
12
15
|
require "kredis/attributes"
|
13
16
|
|
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.
|
4
|
+
version: 1.6.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-
|
12
|
+
date: 2023-10-19 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -86,10 +86,12 @@ files:
|
|
86
86
|
- lib/kredis.rb
|
87
87
|
- lib/kredis/attributes.rb
|
88
88
|
- lib/kredis/connections.rb
|
89
|
+
- lib/kredis/default_values.rb
|
89
90
|
- lib/kredis/log_subscriber.rb
|
90
91
|
- lib/kredis/migration.rb
|
91
92
|
- lib/kredis/namespace.rb
|
92
93
|
- lib/kredis/railtie.rb
|
94
|
+
- lib/kredis/type/boolean.rb
|
93
95
|
- lib/kredis/type/datetime.rb
|
94
96
|
- lib/kredis/type/json.rb
|
95
97
|
- lib/kredis/type_casting.rb
|
@@ -101,6 +103,7 @@ files:
|
|
101
103
|
- lib/kredis/types/flag.rb
|
102
104
|
- lib/kredis/types/hash.rb
|
103
105
|
- lib/kredis/types/list.rb
|
106
|
+
- lib/kredis/types/ordered_set.rb
|
104
107
|
- lib/kredis/types/proxy.rb
|
105
108
|
- lib/kredis/types/proxy/failsafe.rb
|
106
109
|
- lib/kredis/types/proxying.rb
|
@@ -129,7 +132,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
129
132
|
- !ruby/object:Gem::Version
|
130
133
|
version: '0'
|
131
134
|
requirements: []
|
132
|
-
rubygems_version: 3.4.
|
135
|
+
rubygems_version: 3.4.20
|
133
136
|
signing_key:
|
134
137
|
specification_version: 4
|
135
138
|
summary: Higher-level data structures built on Redis.
|