redis-objects 1.5.1 → 2.0.0.alpha

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5c7bc592d203647a8b7e9fd574a78eec1ec466e85fef95d30fac6d831f5d086a
4
- data.tar.gz: e89a8a50ddac32cc8b0fd5692697c21620ef97bac6f28c1841c0e50e9a833429
3
+ metadata.gz: 22b6b39234249ccd4c9485061bb918a211c539b3612d1a916a56eab0e13e031f
4
+ data.tar.gz: 9465be0b72fb8d160421eae75cf5cc5996a2aaa6b507bac6492f6a0b66fad788
5
5
  SHA512:
6
- metadata.gz: 7a91ab932b94a4a36ab4da40d173804b71c46b21c28e917acefb5f1720da1dd60fe3e4c0d06e124c172118789c31fa11f0f4b96b7b27da97cbd8f7a90f01dd6c
7
- data.tar.gz: d92e900d1fcec537a439e99ad7d311a83ad23c1e5c28ecc84e8922a0c7da56b4fdcfc9cadcb48aca382c4a6c8045dd24ecbeb81d681aa4fcad2c9d13b3cf9a8f
6
+ metadata.gz: ff4f516b5618e2a010c32ee0360dbfdbc172d400d3570cae3e5078aff845188171f3900849bdbb9c9c8cc869cc419d1995c9162b79e09a2a7d750d05b0591987
7
+ data.tar.gz: 75677a0da407ad97925c69ea51a55d51d4fc3b7a036768e4c5cb2457adbeefdeb924160d3ec8656949b4d2369785c8de4a272a4284ccc12f379eb89b3a7496b3
data/.gitignore CHANGED
@@ -9,3 +9,5 @@ spec/redis.pid
9
9
  dump.rdb
10
10
  Gemfile.lock
11
11
  redis-objects-*.gem
12
+ coverage/
13
+ .DS_Store
data/.travis.yml CHANGED
@@ -5,7 +5,12 @@ before_install:
5
5
  - gem install bundler
6
6
 
7
7
  rvm:
8
- - 2.3.3
9
- - 2.4.0
10
- - 2.5.1
11
- - 2.6.4
8
+ - 2.3.8
9
+ - 2.4.10
10
+ - 2.5.9
11
+ - 2.6.7
12
+ - 2.7.3
13
+ - 3.0.1
14
+
15
+ # For code coverage reports
16
+ script: bundle exec rake
data/CHANGELOG.rdoc CHANGED
@@ -1,5 +1,13 @@
1
1
  = Changelog for Redis::Objects
2
2
 
3
+ == 1.7.0 (29 Apr 2022)
4
+
5
+ * Bumped version to 1.7.0 to revert redis-rb version lock [Nate Wiger]
6
+
7
+ == 1.6.0 (29 Apr 2022)
8
+
9
+ * Upgrade version to 1.6.0 due to redis-rb changes to Redis.current [Nate Wiger]
10
+
3
11
  == 1.5.1 (10 Jul 2021)
4
12
 
5
13
  * Added double-splat for **options to account for Ruby 3.0 [Nate Wiger]
data/README.md CHANGED
@@ -1,9 +1,60 @@
1
1
  Redis::Objects - Map Redis types directly to Ruby objects
2
2
  =========================================================
3
3
 
4
- [![Build Status](https://travis-ci.org/nateware/redis-objects.png)](https://travis-ci.org/nateware/redis-objects)
4
+ [![Build Status](https://app.travis-ci.com/nateware/redis-objects.svg?branch=master)](https://travis-ci.com/github/nateware/redis-objects)
5
+ [![Code Coverage](https://codecov.io/gh/nateware/redis-objects/branch/master/graph/badge.svg)](https://codecov.io/gh/nateware/redis-objects)
5
6
  [![Donate](https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=MJF7JU5M7F8VL)
6
7
 
8
+ Important 2.0 changes
9
+ ---------------------
10
+ Redis::Objects 2.0 introduces several important backwards incompatible changes.
11
+ Currently 2.0 can be installed with `gem install redis-objects --pre` or by listing it
12
+ explicitly in your Gemfile:
13
+ ~~~ruby
14
+ # Gemfile
15
+ gem 'redis-objects', '>= 2.0.0.alpha'
16
+ ~~~
17
+ You're encouraged to try it out in test code (not production) to ensure it works for you.
18
+ Official release is expected later in 2022.
19
+
20
+ Key Naming Changes
21
+ ==================
22
+ The internal key naming scheme has changed for `Nested::Class::Namespaces` to fix a longstanding bug.
23
+ **This means your existing data in Redis will not be accessible until you call `migrate_redis_legacy_keys`.**
24
+
25
+ To fix this (only needed once), create a script like this:
26
+
27
+ ~~~ruby
28
+ class YouClassNameHere < ActiveRecord::Base
29
+ include Redis::Objects
30
+ # ... your relevant definitions here ...
31
+ end
32
+
33
+ YourClassName.migrate_redis_legacy_keys
34
+ ~~~
35
+
36
+ Then, you need to find a time when you can temporarily pause writes to your redis server
37
+ so that you can run that script. It uses `redis.scan` internally so it should be able to
38
+ handle a high number of keys. For large data sets, it could take a while.
39
+
40
+ For more details on the issue and fix refer to [#213](https://github.com/nateware/redis-objects/issues/231).
41
+
42
+ Rename of `lock` Method
43
+ =======================
44
+ The `lock` method that collided with `ActiveRecord::Base` has been renamed `redis_lock`.
45
+ This means your classes need to be updated to call `redis_lock` instead:
46
+
47
+ ~~~ruby
48
+ class YouClassNameHere < ActiveRecord::Base
49
+ include Redis::Objects
50
+ redis_lock :mylock # formerly just "lock"
51
+ end
52
+ ~~~
53
+
54
+ For more details on the issue and fix refer to [#213](https://github.com/nateware/redis-objects/issues/231).
55
+
56
+ Overview
57
+ --------
7
58
  This is **not** an ORM. People that are wrapping ORM’s around Redis are missing the point.
8
59
 
9
60
  The killer feature of Redis is that it allows you to perform _atomic_ operations
@@ -118,7 +169,7 @@ Here's an example that integrates several data types with an ActiveRecord model:
118
169
  class Team < ActiveRecord::Base
119
170
  include Redis::Objects
120
171
 
121
- lock :trade_players, :expiration => 15 # sec
172
+ redis_lock :trade_players, :expiration => 15 # sec
122
173
  value :at_bat
123
174
  counter :hits
124
175
  counter :runs
@@ -523,7 +574,7 @@ Locks work similarly. On completion or exception the lock is released:
523
574
 
524
575
  ~~~ruby
525
576
  class Team < ActiveRecord::Base
526
- lock :reorder # declare a lock
577
+ redis_lock :reorder # declare a lock
527
578
  end
528
579
 
529
580
  @team.reorder_lock.lock do
@@ -547,7 +598,7 @@ lock time.
547
598
 
548
599
  ~~~ruby
549
600
  class Team < ActiveRecord::Base
550
- lock :reorder, :expiration => 15.minutes
601
+ redis_lock :reorder, :expiration => 15.minutes
551
602
  end
552
603
  ~~~
553
604
 
@@ -595,5 +646,5 @@ end
595
646
 
596
647
  Author
597
648
  =======
598
- Copyright (c) 2009-2019 [Nate Wiger](http://nateware.com). All Rights Reserved.
649
+ Copyright (c) 2009-2022 [Nate Wiger](http://nateware.com). All Rights Reserved.
599
650
  Released under the [Artistic License](http://www.opensource.org/licenses/artistic-license-2.0.php).
@@ -123,24 +123,20 @@ class Redis
123
123
  hsh
124
124
  end
125
125
 
126
- # Get values in bulk, takes an array of keys as arguments.
126
+ # Get values in bulk, takes an array of fields as arguments.
127
127
  # Values are returned in a collection in the same order than their keys in *keys Redis: HMGET
128
- def bulk_values(*keys)
129
- get_keys = *keys.flatten
130
- return [] if get_keys.empty?
131
- res = redis.hmget(key, get_keys)
132
- get_keys.inject([]){|collection, k| collection << unmarshal(res.shift, options[:marshal_keys][k])}
128
+ def bulk_values(*fields)
129
+ get_fields = *fields.flatten
130
+ return [] if get_fields.empty?
131
+ res = redis.hmget(key, get_fields)
132
+ get_fields.collect{|k| unmarshal(res.shift, options[:marshal_keys][k])}
133
133
  end
134
134
 
135
135
  # Increment value by integer at field. Redis: HINCRBY
136
136
  def incrby(field, by=1)
137
137
  allow_expiration do
138
138
  ret = redis.hincrby(key, field, by)
139
- unless ret.is_a? Array
140
- ret.to_i
141
- else
142
- nil
143
- end
139
+ ret.to_i
144
140
  end
145
141
  end
146
142
  alias_method :incr, :incrby
@@ -155,11 +151,7 @@ class Redis
155
151
  def incrbyfloat(field, by=1.0)
156
152
  allow_expiration do
157
153
  ret = redis.hincrbyfloat(key, field, by)
158
- unless ret.is_a? Array
159
- ret.to_f
160
- else
161
- nil
162
- end
154
+ ret.to_f
163
155
  end
164
156
  end
165
157
 
@@ -2,6 +2,10 @@ class Redis
2
2
  module Helpers
3
3
  # These are core commands that all types share (rename, etc)
4
4
  module CoreCommands
5
+ def exists
6
+ redis.exists key
7
+ end
8
+
5
9
  def exists?
6
10
  redis.exists? key
7
11
  end
@@ -14,7 +14,7 @@ class Redis
14
14
  module ClassMethods
15
15
  # Define a new lock. It will function like a model attribute,
16
16
  # so it can be used alongside ActiveRecord/DataMapper, etc.
17
- def lock(name, options={})
17
+ def redis_lock(name, options={})
18
18
  options[:timeout] ||= 5 # seconds
19
19
  lock_name = "#{name}_lock"
20
20
  redis_objects[lock_name.to_sym] = options.merge(:type => :lock)
@@ -1,5 +1,5 @@
1
1
  class Redis
2
2
  module Objects
3
- VERSION = "1.5.1"
3
+ VERSION = "2.0.0.alpha"
4
4
  end
5
5
  end
data/lib/redis/objects.rb CHANGED
@@ -101,16 +101,93 @@ class Redis
101
101
  @redis_objects ||= {}
102
102
  end
103
103
 
104
- # Set the Redis redis_prefix to use. Defaults to model_name
105
- def redis_prefix=(redis_prefix) @redis_prefix = redis_prefix end
104
+ # Toggles whether to use the legacy redis key naming scheme, which causes
105
+ # naming conflicts in certain cases.
106
+ attr_accessor :redis_legacy_naming
107
+ attr_accessor :redis_silence_warnings
108
+
109
+ # Set the Redis redis_prefix to use. Defaults to class_name.
110
+ def redis_prefix=(redis_prefix)
111
+ @silence_warnings_as_redis_prefix_was_set_manually = true
112
+ @redis_prefix = redis_prefix
113
+ end
114
+
106
115
  def redis_prefix(klass = self) #:nodoc:
107
- @redis_prefix ||= klass.name.to_s.
108
- sub(%r{(.*::)}, '').
109
- gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
110
- gsub(/([a-z\d])([A-Z])/,'\1_\2').
116
+ @redis_prefix ||=
117
+ if redis_legacy_naming
118
+ redis_legacy_prefix(klass)
119
+ else
120
+ redis_legacy_naming_warning_message(klass)
121
+ redis_modern_prefix(klass)
122
+ end
123
+
124
+ @redis_prefix
125
+ end
126
+
127
+ def redis_modern_prefix(klass = self) #:nodoc:
128
+ klass.name.to_s.
129
+ gsub(/::/, '__'). # Nested::Class => Nested__Class
130
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2'). # ClassName => Class_Name
131
+ gsub(/([a-z\d])([A-Z])/,'\1_\2'). # className => class_Name
132
+ downcase
133
+ end
134
+
135
+ def redis_legacy_prefix(klass = self) #:nodoc:
136
+ klass.name.to_s.
137
+ sub(%r{(.*::)}, ''). # Nested::Class => Class (problematic)
138
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2'). # ClassName => Class_Name
139
+ gsub(/([a-z\d])([A-Z])/,'\1_\2'). # className => class_Name
111
140
  downcase
112
141
  end
113
142
 
143
+ # Temporary warning to help with migrating key names
144
+ def redis_legacy_naming_warning_message(klass)
145
+ # warn @silence_warnings_as_redis_prefix_was_set_manually.inspect
146
+ unless redis_legacy_naming || redis_silence_warnings || @silence_warnings_as_redis_prefix_was_set_manually
147
+ modern = redis_modern_prefix(klass)
148
+ legacy = redis_legacy_prefix(klass)
149
+ if modern != legacy
150
+ warn <<EOW
151
+ WARNING: In redis-objects 2.0.0, key naming will change to fix longstanding bugs.
152
+ Your class #{klass.name.to_s} will be affected by this change!
153
+ Current key prefix: #{legacy.inspect}
154
+ Future key prefix: #{modern.inspect}
155
+ Read more at https://github.com/nateware/redis-objects/issues/231
156
+ EOW
157
+ end
158
+ end
159
+ end
160
+
161
+ def migrate_redis_legacy_keys
162
+ cursor = 0
163
+ legacy = redis_legacy_prefix
164
+ total_keys = 0
165
+ if legacy == redis_prefix
166
+ raise "Failed to migrate keys for #{self.name.to_s} as legacy and new redis_prefix are the same (#{redis_prefix})"
167
+ end
168
+ warn "Migrating keys from #{legacy} prefix to #{redis_prefix}"
169
+
170
+ loop do
171
+ cursor, keys = redis.scan(cursor, :match => "#{legacy}:*")
172
+ total_keys += keys.length
173
+ keys.each do |key|
174
+ # Split key name apart on ':'
175
+ base_class, id, name = key.split(':')
176
+
177
+ # Figure out the new name
178
+ new_key = redis_field_key(name, id=id, context=self)
179
+
180
+ # Rename the key
181
+ warn "Rename '#{key}', '#{new_key}'"
182
+ ok = redis.rename(key, new_key)
183
+ warn "Warning: Rename '#{key}', '#{new_key}' failed: #{ok}" if ok != 'OK'
184
+ end
185
+ break if cursor == "0"
186
+ end
187
+
188
+ warn "Migrated #{total_keys} total number of redis keys"
189
+ end
190
+
114
191
  def redis_options(name)
115
192
  klass = first_ancestor_with(name)
116
193
  return klass.redis_objects[name.to_sym] || {}
@@ -19,7 +19,7 @@ Gem::Specification.new do |spec|
19
19
  spec.require_paths = ["lib"]
20
20
 
21
21
  # Only fix this one version or else tests break
22
- spec.add_dependency "redis", "~> 4.2"
22
+ spec.add_dependency "redis"
23
23
 
24
24
  # Ignore gemspec warnings on these. Trying to fix them to versions breaks TravisCI
25
25
  spec.add_development_dependency "bundler"
@@ -29,6 +29,10 @@ Gem::Specification.new do |spec|
29
29
 
30
30
  # Compatibility testing
31
31
  spec.add_development_dependency "redis-namespace"
32
+ spec.add_development_dependency "activesupport"
32
33
  spec.add_development_dependency "activerecord"
33
34
  spec.add_development_dependency "sqlite3"
35
+
36
+ # Code coverage
37
+ spec.add_development_dependency "simplecov-cobertura"
34
38
  end
@@ -4,7 +4,7 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
4
4
  # tests whether autoload functionality works correctly; had issues previously
5
5
 
6
6
  require 'redis/objects'
7
- # $redis used automatically
7
+ Redis::Objects.redis = REDIS_HANDLE
8
8
 
9
9
  describe 'Redis::Objects' do
10
10
  it "should autoload everything" do