kredis 1.0.1 → 1.3.0.1

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: c1cd3c7afcd05236cdb9ed3980d0969077f594da2fe1ca0be383610be4a4b37c
4
- data.tar.gz: 912cd1ed2ff7d0b05df1fcacb07e0272ba098b86645a0607a80aa69e65107223
3
+ metadata.gz: 6042f4320cf89f8b0eae1ce4c8daa61ee6821775b7fdeab02777673a25b2cba1
4
+ data.tar.gz: 67121a89444ffd7f8e0a1636fc6651a2851bbc5b63514a23413136bca2abd22d
5
5
  SHA512:
6
- metadata.gz: 8d7fa6004370d1d75c8b2567397ab88d65351af3d42d381cfc602d3db2a12eb10cdf0e42d190c802dea9d02fee112130cd6786ef60a125581924d82630191ebc
7
- data.tar.gz: '07286763861b342cb8dd67c55f1df2e84d2496aa41a626bf23bd186ab7b8c698018cc7cb42bf65128cfb2a88eb22a9f73c84fa8a8a0516aaedb56d8c18624b19'
6
+ metadata.gz: 81888671af0fb781788d890640142da0f36bf03589d628ec2aaeca1d86608d9602282a9b9955e0c496cd47be01d4f4e3e42d47ac9d9414949ca635c2768177b8
7
+ data.tar.gz: eb7f0f1896bf2c27c4fa5630d43db65c8fcf183de9be5709146a3d06d183afdc33873f705a57dbbea5c58c2ca826758a82bd84ef81dfd320ca1d2a5c1c5eef1a
data/README.md CHANGED
@@ -109,8 +109,10 @@ enum = Kredis.enum "myenum", values: %w[ one two three ], default: "one"
109
109
  true == enum.one? # => GET myenum
110
110
  enum.value = "two" # => SET myenum "two"
111
111
  "two" == enum.value # => GET myenum
112
+ enum.three! # => SET myenum "three"
113
+ "three" == enum.value # => GET myenum
112
114
  enum.value = "four"
113
- "two" == enum.value # => GET myenum
115
+ "three" == enum.value # => GET myenum
114
116
  enum.reset # => DEL myenum
115
117
  "one" == enum.value # => GET myenum
116
118
 
@@ -168,9 +170,16 @@ You can use all these structures in models:
168
170
  ```ruby
169
171
  class Person < ApplicationRecord
170
172
  kredis_list :names
171
- kredis_list :names_with_custom_key, key: ->(p) { "person:#{p.id}:names_customized" }
173
+ kredis_list :names_with_custom_key_via_lambda, key: ->(p) { "person:#{p.id}:names_customized" }
174
+ kredis_list :names_with_custom_key_via_method, key: :generate_names_key
172
175
  kredis_unique_list :skills, limit: 2
173
176
  kredis_enum :morning, values: %w[ bright blue black ], default: "bright"
177
+ kredis_counter :steps, expires_in: 1.hour
178
+
179
+ private
180
+ def generate_names_key
181
+ "key-generated-from-private-method"
182
+ end
174
183
  end
175
184
 
176
185
  person = Person.find(5)
@@ -194,14 +203,17 @@ end
194
203
 
195
204
  ## Installation
196
205
 
197
- 1. Add the `kredis` gem to your Gemfile: `gem 'kredis'`
198
- 2. Run `./bin/bundle install`
199
- 3. Run `./bin/rails kredis:install` to add a default configuration at [`config/redis/shared.yml`](lib/install/shared.yml)
206
+ 1. Run `./bin/bundle add kredis`
207
+ 2. Run `./bin/rails kredis:install` to add a default configuration at [`config/redis/shared.yml`](lib/install/shared.yml)
200
208
 
201
209
  Additional configurations can be added under `config/redis/*.yml` and referenced when a type is created. For example, `Kredis.string("mystring", config: :strings)` would lookup `config/redis/strings.yml`.
202
210
 
203
211
  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.
204
212
 
213
+ ### Redis support
214
+
215
+ Kredis works with Redis server 4.0+, with the [Redis Ruby](https://github.com/redis/redis-rb) client version 4.2+.
216
+
205
217
  ### Setting SSL options on Redis Connections
206
218
 
207
219
  If you need to connect to Redis with SSL, the recommended approach is to set your Redis instance manually by adding an entry to the `Kredis::Connections.connections` hash. Below an example showing how to connect to Redis using Client Authentication:
@@ -231,7 +243,7 @@ The above code could be added to either `config/environments/production.rb` or a
231
243
 
232
244
  ### Configure how the redis client is created
233
245
 
234
- You can configure how the redis client is created by setting `config.connector` in your `application.rb`:
246
+ You can configure how the redis client is created by setting `config.kredis.connector` in your `application.rb`:
235
247
 
236
248
  ```ruby
237
249
  config.kredis.connector = ->(config) { SomeRedisProxy.new(config) }
@@ -62,14 +62,18 @@ module Kredis::Attributes
62
62
  kredis_connection_with __method__, name, key, available: available, config: config, after_change: after_change
63
63
  end
64
64
 
65
- def kredis_counter(name, key: nil, config: :shared, after_change: nil)
66
- kredis_connection_with __method__, name, key, config: config, after_change: after_change
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
67
67
  end
68
68
 
69
69
  def kredis_hash(name, key: nil, typed: :string, config: :shared, after_change: nil)
70
70
  kredis_connection_with __method__, name, key, typed: typed, config: config, after_change: after_change
71
71
  end
72
72
 
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
75
+ end
76
+
73
77
  private
74
78
  def kredis_connection_with(method, name, key, **options)
75
79
  ivar_symbol = :"@#{name}_#{method}"
@@ -93,6 +97,7 @@ module Kredis::Attributes
93
97
  case key
94
98
  when String then key
95
99
  when Proc then key.call(self)
100
+ when Symbol then send(key)
96
101
  end
97
102
  end
98
103
 
@@ -10,29 +10,35 @@ class Kredis::Migration
10
10
  end
11
11
 
12
12
  def migrate_all(key_pattern)
13
- each_key_batch_matching(key_pattern) do |keys|
13
+ each_key_batch_matching(key_pattern) do |keys, pipeline|
14
14
  keys.each do |key|
15
15
  ids = key.scan(/\d+/).map(&:to_i)
16
- migrate from: key, to: yield(key, *ids)
16
+ migrate from: key, to: yield(key, *ids), pipeline: pipeline
17
17
  end
18
18
  end
19
19
  end
20
20
 
21
- def migrate(from:, to:)
21
+ def migrate(from:, to:, pipeline: nil)
22
22
  namespaced_to = Kredis.namespaced_key(to)
23
23
 
24
24
  if to.present? && from != namespaced_to
25
25
  log_migration "Migrating key #{from} to #{namespaced_to}" do
26
- @redis.evalsha @copy_sha, keys: [ from, namespaced_to ]
26
+ (pipeline || @redis).evalsha @copy_sha, keys: [ from, namespaced_to ]
27
27
  end
28
28
  else
29
29
  log_migration "Skipping blank/unaltered migration key #{from} → #{to}"
30
30
  end
31
31
  end
32
32
 
33
- def delete_all(key_pattern)
34
- each_key_batch_matching(key_pattern) do |keys|
35
- @redis.del *keys
33
+ def delete_all(*key_patterns)
34
+ log_migration "DELETE ALL #{key_patterns.inspect}" do
35
+ if key_patterns.length > 1
36
+ @redis.del *key_patterns
37
+ else
38
+ each_key_batch_matching(key_patterns.first) do |keys, pipeline|
39
+ pipeline.del *keys
40
+ end
41
+ end
36
42
  end
37
43
  end
38
44
 
@@ -43,7 +49,7 @@ class Kredis::Migration
43
49
  cursor = "0"
44
50
  begin
45
51
  cursor, keys = @redis.scan(cursor, match: key_pattern, count: SCAN_BATCH_SIZE)
46
- @redis.pipelined { yield keys }
52
+ @redis.multi { |pipeline| yield keys, pipeline }
47
53
  end until cursor == "0"
48
54
  end
49
55
 
@@ -8,7 +8,7 @@ module Kredis
8
8
  end
9
9
 
10
10
  def cast_value(value)
11
- JSON.load(value)
11
+ JSON.parse(value)
12
12
  end
13
13
 
14
14
  def serialize(value)
@@ -4,14 +4,15 @@ class Kredis::Types::CallbacksProxy
4
4
 
5
5
  AFTER_CHANGE_OPERATIONS = {
6
6
  Kredis::Types::Counter => %i[ increment decrement reset ],
7
- Kredis::Types::Cycle => %i[ next ],
7
+ Kredis::Types::Cycle => %i[ next reset ],
8
8
  Kredis::Types::Enum => %i[ value= reset ],
9
9
  Kredis::Types::Flag => %i[ mark remove ],
10
10
  Kredis::Types::Hash => %i[ update delete []= remove ],
11
11
  Kredis::Types::List => %i[ remove prepend append << ],
12
12
  Kredis::Types::Scalar => %i[ value= clear ],
13
13
  Kredis::Types::Set => %i[ add << remove replace take clear ],
14
- Kredis::Types::Slots => %i[ reserve release reset ]
14
+ Kredis::Types::Slots => %i[ reserve release reset ],
15
+ Kredis::Types::UniqueList => %i[ remove prepend append << ]
15
16
  }
16
17
 
17
18
  def initialize(type, callback)
@@ -7,14 +7,14 @@ class Kredis::Types::Counter < Kredis::Types::Proxying
7
7
  multi do
8
8
  set 0, ex: expires_in, nx: true
9
9
  incrby by
10
- end
10
+ end[-1]
11
11
  end
12
12
 
13
13
  def decrement(by: 1)
14
14
  multi do
15
15
  set 0, ex: expires_in, nx: true
16
16
  decrby by
17
- end
17
+ end[-1]
18
18
  end
19
19
 
20
20
  def value
@@ -28,6 +28,7 @@ class Kredis::Types::Enum < Kredis::Types::Proxying
28
28
  def define_predicates_for_values
29
29
  values.each do |defined_value|
30
30
  define_singleton_method("#{defined_value}?") { value == defined_value }
31
+ define_singleton_method("#{defined_value}!") { self.value = defined_value }
31
32
  end
32
33
  end
33
34
  end
@@ -28,6 +28,7 @@ class Kredis::Types::Hash < Kredis::Types::Proxying
28
28
  def remove
29
29
  del
30
30
  end
31
+ alias clear remove
31
32
 
32
33
  def entries
33
34
  (hgetall || {}).transform_values { |val| string_to_type(val, typed) }.with_indifferent_access
@@ -1,5 +1,5 @@
1
1
  class Kredis::Types::List < Kredis::Types::Proxying
2
- proxying :lrange, :lrem, :lpush, :rpush, :exists?
2
+ proxying :lrange, :lrem, :lpush, :ltrim, :rpush, :exists?, :del
3
3
 
4
4
  attr_accessor :typed
5
5
 
@@ -20,4 +20,8 @@ class Kredis::Types::List < Kredis::Types::Proxying
20
20
  rpush types_to_strings(elements, typed) if elements.flatten.any?
21
21
  end
22
22
  alias << append
23
+
24
+ def clear
25
+ del
26
+ end
23
27
  end
@@ -2,15 +2,22 @@ class Kredis::Types::Proxy
2
2
  require_relative "proxy/failsafe"
3
3
  include Failsafe
4
4
 
5
- attr_accessor :redis, :key
5
+ attr_accessor :key
6
+
7
+ thread_mattr_accessor :pipeline
6
8
 
7
9
  def initialize(redis, key, **options)
8
10
  @redis, @key = redis, key
9
11
  options.each { |key, value| send("#{key}=", value) }
10
12
  end
11
13
 
12
- def multi(...)
13
- redis.multi(...)
14
+ def multi(*args, **kwargs, &block)
15
+ redis.multi(*args, **kwargs) do |pipeline|
16
+ self.pipeline = pipeline
17
+ block.call
18
+ ensure
19
+ self.pipeline = nil
20
+ end
14
21
  end
15
22
 
16
23
  def method_missing(method, *args, **kwargs)
@@ -22,6 +29,10 @@ class Kredis::Types::Proxy
22
29
  end
23
30
 
24
31
  private
32
+ def redis
33
+ pipeline || @redis
34
+ end
35
+
25
36
  def log_message(method, *args, **kwargs)
26
37
  args = args.flatten.reject(&:blank?).presence
27
38
  kwargs = kwargs.reject { |_k, v| v.blank? }.presence
@@ -1,14 +1,14 @@
1
1
  require "active_support/core_ext/module/delegation"
2
2
 
3
3
  class Kredis::Types::Proxying
4
- attr_accessor :proxy, :redis, :key
4
+ attr_accessor :proxy, :key
5
5
 
6
6
  def self.proxying(*commands)
7
7
  delegate *commands, to: :proxy
8
8
  end
9
9
 
10
10
  def initialize(redis, key, **options)
11
- @redis, @key = redis, key
11
+ @key = key
12
12
  @proxy = Kredis::Types::Proxy.new(redis, key)
13
13
  options.each { |key, value| send("#{key}=", value) }
14
14
  end
@@ -19,10 +19,10 @@ class Kredis::Types::Slots < Kredis::Types::Proxying
19
19
  release
20
20
  end
21
21
  else
22
- if incr <= available
22
+ if available?
23
+ incr
23
24
  true
24
25
  else
25
- release
26
26
  false
27
27
  end
28
28
  end
@@ -30,16 +30,25 @@ class Kredis::Types::Slots < Kredis::Types::Proxying
30
30
  end
31
31
 
32
32
  def release
33
- decr
33
+ if taken > 0
34
+ decr
35
+ true
36
+ else
37
+ false
38
+ end
34
39
  end
35
40
 
36
41
  def available?
37
42
  failsafe returning: false do
38
- get.to_i < available
43
+ taken < available
39
44
  end
40
45
  end
41
46
 
42
47
  def reset
43
48
  del
44
49
  end
50
+
51
+ def taken
52
+ get.to_i
53
+ end
45
54
  end
@@ -5,19 +5,25 @@ class Kredis::Types::UniqueList < Kredis::Types::List
5
5
  attr_accessor :typed, :limit
6
6
 
7
7
  def prepend(elements)
8
+ elements = Array(elements).uniq
9
+ return if elements.empty?
10
+
8
11
  multi do
9
12
  remove elements
10
13
  super
11
14
  ltrim 0, (limit - 1) if limit
12
- end if Array(elements).flatten.any?
15
+ end
13
16
  end
14
17
 
15
18
  def append(elements)
19
+ elements = Array(elements).uniq
20
+ return if elements.empty?
21
+
16
22
  multi do
17
23
  remove elements
18
24
  super
19
25
  ltrim -limit, -1 if limit
20
- end if Array(elements).flatten.any?
26
+ end
21
27
  end
22
28
  alias << append
23
29
  end
@@ -1,3 +1,3 @@
1
1
  module Kredis
2
- VERSION = "1.0.1"
2
+ VERSION = "1.3.0.1"
3
3
  end
data/lib/kredis.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require "active_support"
2
2
  require "active_support/core_ext/module/attribute_accessors"
3
+ require "active_support/core_ext/module/attribute_accessors_per_thread"
3
4
 
4
5
  require "kredis/version"
5
6
 
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.0.1
4
+ version: 1.3.0.1
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: 2021-12-02 00:00:00.000000000 Z
12
+ date: 2023-03-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -29,16 +29,22 @@ dependencies:
29
29
  name: redis
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
- - - "~>"
32
+ - - ">="
33
33
  - !ruby/object:Gem::Version
34
34
  version: '4.2'
35
+ - - "<"
36
+ - !ruby/object:Gem::Version
37
+ version: '6'
35
38
  type: :runtime
36
39
  prerelease: false
37
40
  version_requirements: !ruby/object:Gem::Requirement
38
41
  requirements:
39
- - - "~>"
42
+ - - ">="
40
43
  - !ruby/object:Gem::Version
41
44
  version: '4.2'
45
+ - - "<"
46
+ - !ruby/object:Gem::Version
47
+ version: '6'
42
48
  - !ruby/object:Gem::Dependency
43
49
  name: rails
44
50
  requirement: !ruby/object:Gem::Requirement
@@ -109,7 +115,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
109
115
  - !ruby/object:Gem::Version
110
116
  version: '0'
111
117
  requirements: []
112
- rubygems_version: 3.2.30
118
+ rubygems_version: 3.4.2
113
119
  signing_key:
114
120
  specification_version: 4
115
121
  summary: Higher-level data structures built on Redis.