redis-objects 1.5.1 → 2.0.0.alpha

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: 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