kredis 1.0.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of kredis might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6977b6ccbe9dba3574b4f0fe0c107fde3e1ff8a4e8a52f46076fe8df3acab2db
4
- data.tar.gz: b3b9fb9c0e82a898168c6a9442cba36938bc4f7b9046dca16be052d28074c3ef
3
+ metadata.gz: ef7140930b42a8d19b49568c233c1b0c9b1e799f5d8d6948e96442a2bc74e7c1
4
+ data.tar.gz: 205fc23eb761dba14f10ffd52506ad748b0a19c2799d75a059841d17fbe9080e
5
5
  SHA512:
6
- metadata.gz: aa0715d6e188a7261f2f4c27f13a1b4dc919c5bf339c29435836693c3ae8df19f63ae54ff0d0ca28712f984a238df124bdc06ab268b85c88fd28179ae1534560
7
- data.tar.gz: 9bb31956f1c666e64fc50c12a35b1a9ebefad8ec7f139b67c73033e745c48b8f271736b533c91eb6a4c84a892f541edb634688663219bd1285a1c3aafb996efd
6
+ metadata.gz: e95afce53e43f5ee10f527f41854a058ccd98c34d0d52394d99addcd0e774409c5aa1bf26d06e291fc12a3f5e7e50fffdffc686ed26e2926fe36709a08da90be
7
+ data.tar.gz: c03d6654a1cdb7680bad60efd2287b82f4ac720362d3c65935629beeeb466c54ff08341e5016173dca19ac1bb67cf48de52c296ddfd3a17fbb6d230090c6b38a
data/README.md CHANGED
@@ -105,24 +105,26 @@ cycle.next # => GET mycycle + SET mycycle 0
105
105
  :one == cycle.value # => GET mycycle
106
106
 
107
107
  enum = Kredis.enum "myenum", values: %w[ one two three ], default: "one"
108
- "one" == enum.value # => GET myenum
108
+ "one" == enum.value # => GET myenum
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
- "one" == enum.value # => GET myenum
117
+ "one" == enum.value # => GET myenum
116
118
 
117
119
  slots = Kredis.slots "myslots", available: 3
118
120
  true == slots.available? # => GET myslots
119
121
  slots.reserve # => INCR myslots
120
122
  true == slots.available? # => GET myslots
121
- slots.reserve # => INCR myslots
123
+ slots.reserve # => INCR myslots
122
124
  true == slots.available? # => GET myslots
123
125
  slots.reserve # => INCR myslots
124
126
  false == slots.available? # => GET myslots
125
- slots.reserve # => INCR myslots + DECR myslots
127
+ slots.reserve # => INCR myslots + DECR myslots
126
128
  false == slots.available? # => GET myslots
127
129
  slots.release # => DECR myslots
128
130
  true == slots.available? # => GET myslots
@@ -141,7 +143,7 @@ flag = Kredis.flag "myflag"
141
143
  false == flag.marked? # => EXISTS myflag
142
144
  flag.mark # => SET myflag 1
143
145
  true == flag.marked? # => EXISTS myflag
144
- flag.remove # => DEL myflag
146
+ flag.remove # => DEL myflag
145
147
  false == flag.marked? # => EXISTS myflag
146
148
 
147
149
  true == flag.mark(expires_in: 1.second, force: false) #=> SET myflag 1 EX 1 NX
@@ -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,28 +203,16 @@ 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. Add a default configuration under `config/redis/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
- A default configuration can look like this for `config/redis/shared.yml`:
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
- ```yaml
204
- production: &production
205
- host: <%= ENV.fetch("REDIS_SHARED_HOST", "127.0.0.1") %>
206
- port: <%= ENV.fetch("REDIS_SHARED_PORT", "6379") %>
207
- timeout: 1
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.
208
212
 
209
- development: &development
210
- host: <%= ENV.fetch("REDIS_SHARED_HOST", "127.0.0.1") %>
211
- port: <%= ENV.fetch("REDIS_SHARED_PORT", "6379") %>
212
- timeout: 1
213
-
214
- test:
215
- <<: *development
216
- ```
213
+ ### Redis support
217
214
 
218
- Additional configurations can be added under `config/redis/*.yml` and referenced when a type is created, e.g. `Kredis.string("mystring", config: :strings)` would lookup `config/redis/strings.yml`. Under the hood `Kredis.configured_for` is called which'll pass the configuration on to `Redis.new`.
215
+ Kredis works with Redis server 4.0+, with the [Redis Ruby](https://github.com/redis/redis-rb) client version 4.2+.
219
216
 
220
217
  ### Setting SSL options on Redis Connections
221
218
 
@@ -246,7 +243,7 @@ The above code could be added to either `config/environments/production.rb` or a
246
243
 
247
244
  ### Configure how the redis client is created
248
245
 
249
- 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`:
250
247
 
251
248
  ```ruby
252
249
  config.kredis.connector = ->(config) { SomeRedisProxy.new(config) }
@@ -0,0 +1,6 @@
1
+ yaml_path = Rails.root.join("config/redis/shared.yml")
2
+ unless yaml_path.exist?
3
+ say "Adding `config/redis/shared.yml`"
4
+ empty_directory yaml_path.parent.to_s
5
+ copy_file "#{__dir__}/shared.yml", yaml_path
6
+ end
@@ -0,0 +1,15 @@
1
+ production: &production
2
+ url: <%= ENV.fetch("REDIS_URL", "redis://127.0.0.1:6379/0") %>
3
+ timeout: 1
4
+
5
+ development: &development
6
+ url: <%= ENV.fetch("REDIS_URL", "redis://127.0.0.1:6379/0") %>
7
+ timeout: 1
8
+
9
+ # You can also specify host, port, and db instead of url
10
+ # host: <%= ENV.fetch("REDIS_SHARED_HOST", "127.0.0.1") %>
11
+ # port: <%= ENV.fetch("REDIS_SHARED_PORT", "6379") %>
12
+ # db: <%= ENV.fetch("REDIS_SHARED_DB", "11") %>
13
+
14
+ test:
15
+ <<: *development
@@ -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,20 +10,20 @@ 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}"
@@ -31,8 +31,8 @@ class Kredis::Migration
31
31
  end
32
32
 
33
33
  def delete_all(key_pattern)
34
- each_key_batch_matching(key_pattern) do |keys|
35
- @redis.del *keys
34
+ each_key_batch_matching(key_pattern) do |keys, pipeline|
35
+ pipeline.del *keys
36
36
  end
37
37
  end
38
38
 
@@ -43,7 +43,7 @@ class Kredis::Migration
43
43
  cursor = "0"
44
44
  begin
45
45
  cursor, keys = @redis.scan(cursor, match: key_pattern, count: SCAN_BATCH_SIZE)
46
- @redis.pipelined { yield keys }
46
+ @redis.multi { |pipeline| yield keys, pipeline }
47
47
  end until cursor == "0"
48
48
  end
49
49
 
@@ -30,4 +30,9 @@ class Kredis::Railtie < ::Rails::Railtie
30
30
  include Kredis::Attributes
31
31
  end
32
32
  end
33
+
34
+ rake_tasks do
35
+ path = File.expand_path("..", __dir__)
36
+ Dir.glob("#{path}/tasks/**/*.rake").each { |f| load f }
37
+ end
33
38
  end
@@ -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
- Kredis::Types::Hash => %i[ update delete ],
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)
@@ -4,17 +4,17 @@ class Kredis::Types::Counter < Kredis::Types::Proxying
4
4
  attr_accessor :expires_in
5
5
 
6
6
  def increment(by: 1)
7
- multi do
8
- set 0, ex: expires_in, nx: true
9
- incrby by
10
- end
7
+ multi do |pipeline|
8
+ pipeline.set 0, ex: expires_in, nx: true
9
+ pipeline.incrby by
10
+ end[-1]
11
11
  end
12
12
 
13
13
  def decrement(by: 1)
14
- multi do
15
- set 0, ex: expires_in, nx: true
16
- decrby by
17
- end
14
+ multi do |pipeline|
15
+ pipeline.set 0, ex: expires_in, nx: true
16
+ pipeline.decrby by
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, :rpush, :exists?, :del
3
3
 
4
4
  attr_accessor :typed
5
5
 
@@ -8,16 +8,20 @@ class Kredis::Types::List < Kredis::Types::Proxying
8
8
  end
9
9
  alias to_a elements
10
10
 
11
- def remove(*elements)
12
- types_to_strings(elements, typed).each { |element| lrem 0, element }
11
+ def remove(*elements, pipeline: nil)
12
+ types_to_strings(elements, typed).each { |element| (pipeline || proxy).lrem 0, element }
13
13
  end
14
14
 
15
- def prepend(*elements)
16
- lpush types_to_strings(elements, typed) if elements.flatten.any?
15
+ def prepend(*elements, pipeline: nil)
16
+ (pipeline || proxy).lpush types_to_strings(elements, typed) if elements.flatten.any?
17
17
  end
18
18
 
19
- def append(*elements)
20
- rpush types_to_strings(elements, typed) if elements.flatten.any?
19
+ def append(*elements, pipeline: nil)
20
+ (pipeline || proxy).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
@@ -9,8 +9,13 @@ class Kredis::Types::Proxy
9
9
  options.each { |key, value| send("#{key}=", value) }
10
10
  end
11
11
 
12
- def multi(...)
13
- redis.multi(...)
12
+ def multi(&block)
13
+ # NOTE: to be removed when Redis 4 compatibility gets dropped
14
+ return redis.multi unless block
15
+
16
+ redis.multi do |pipeline|
17
+ block.call(Kredis::Types::Proxy.new(pipeline, key))
18
+ end
14
19
  end
15
20
 
16
21
  def method_missing(method, *args, **kwargs)
@@ -8,19 +8,19 @@ class Kredis::Types::Set < Kredis::Types::Proxying
8
8
  end
9
9
  alias to_a members
10
10
 
11
- def add(*members)
12
- sadd types_to_strings(members, typed) if members.flatten.any?
11
+ def add(*members, pipeline: nil)
12
+ (pipeline || proxy).sadd types_to_strings(members, typed) if members.flatten.any?
13
13
  end
14
14
  alias << add
15
15
 
16
- def remove(*members)
17
- srem types_to_strings(members, typed) if members.flatten.any?
16
+ def remove(*members, pipeline: nil)
17
+ (pipeline || proxy).srem types_to_strings(members, typed) if members.flatten.any?
18
18
  end
19
19
 
20
20
  def replace(*members)
21
- multi do
22
- del
23
- add members
21
+ multi do |pipeline|
22
+ pipeline.del
23
+ add members, pipeline: pipeline
24
24
  end
25
25
  end
26
26
 
@@ -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
- multi do
9
- remove elements
10
- super
11
- ltrim 0, (limit - 1) if limit
12
- end if Array(elements).flatten.any?
8
+ elements = Array(elements).uniq
9
+ return if elements.empty?
10
+
11
+ multi do |pipeline|
12
+ remove elements, pipeline: pipeline
13
+ super(elements, pipeline: pipeline)
14
+ pipeline.ltrim 0, (limit - 1) if limit
15
+ end
13
16
  end
14
17
 
15
18
  def append(elements)
16
- multi do
17
- remove elements
18
- super
19
- ltrim (limit - 1), -1 if limit
20
- end if Array(elements).flatten.any?
19
+ elements = Array(elements).uniq
20
+ return if elements.empty?
21
+
22
+ multi do |pipeline|
23
+ remove elements, pipeline: pipeline
24
+ super(elements, pipeline: pipeline)
25
+ pipeline.ltrim -limit, -1 if limit
26
+ end
21
27
  end
22
28
  alias << append
23
29
  end
@@ -1,3 +1,3 @@
1
1
  module Kredis
2
- VERSION = "1.0.0"
2
+ VERSION = "1.2.0"
3
3
  end
@@ -0,0 +1,6 @@
1
+ namespace :kredis do
2
+ desc "Install kredis"
3
+ task :install do
4
+ system "#{RbConfig.ruby} ./bin/rails app:template LOCATION=#{File.expand_path("../../install/install.rb", __dir__)}"
5
+ end
6
+ 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.0.0
4
+ version: 1.2.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: 2021-11-22 00:00:00.000000000 Z
12
+ date: 2022-04-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -61,6 +61,8 @@ extra_rdoc_files: []
61
61
  files:
62
62
  - MIT-LICENSE
63
63
  - README.md
64
+ - lib/install/install.rb
65
+ - lib/install/shared.yml
64
66
  - lib/kredis.rb
65
67
  - lib/kredis/attributes.rb
66
68
  - lib/kredis/connections.rb
@@ -87,6 +89,7 @@ files:
87
89
  - lib/kredis/types/slots.rb
88
90
  - lib/kredis/types/unique_list.rb
89
91
  - lib/kredis/version.rb
92
+ - lib/tasks/kredis/install.rake
90
93
  homepage: https://github.com/rails/kredis
91
94
  licenses:
92
95
  - MIT
@@ -106,7 +109,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
106
109
  - !ruby/object:Gem::Version
107
110
  version: '0'
108
111
  requirements: []
109
- rubygems_version: 3.2.22
112
+ rubygems_version: 3.2.32
110
113
  signing_key:
111
114
  specification_version: 4
112
115
  summary: Higher-level data structures built on Redis.