redis-objects 1.0.1 → 1.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 735c34367c9ed2f4bdd4d64e96c22068bb2956b4
4
- data.tar.gz: 4e0cac119a34d58e46a2d65c3dfab74bda1394fd
3
+ metadata.gz: dc70bd55cafac46d93b6dc5dcd24d2e116c00d1e
4
+ data.tar.gz: d98febd210c47c61f8511f023e09edf86d848f25
5
5
  SHA512:
6
- metadata.gz: c1f48c5fa92ea83c2dcf0df1368d69d60564c69fdffaa82855ef9b898cfa446afa377bdc7a1590bbc82f0ff4282cdce274a615d99810624b7bbb132ca3636326
7
- data.tar.gz: 84ffd1f1185315c8d128c23b598b88b8fca03ede54e794afd8fc42ad2642312d5a086af735f2282e30f734fc83f3c04f011b22be8df2597575ca91bf079ddd29
6
+ metadata.gz: d854a41164664e2e4dafdf3c25e05ad6281ba305cb4c28fcccbff6777b4f2bcc9f773b96e0c7423552957395ab21aa7c0bef5175d70fe4aae7677c04c457c7d4
7
+ data.tar.gz: 090c58f4cbe376b4a37b0bd9c1b70894f036c8bc5b94a62c58e1047c0a175f8418659b260ca26daa3a3c21f6e2c9642694f1176f8c8bc390a6914eccd05e90bb
data/CHANGELOG.rdoc CHANGED
@@ -1,5 +1,23 @@
1
1
  = Changelog for Redis::Objects
2
2
 
3
+ == 1.1.0 (21 Jan 2015)
4
+
5
+ * Support connection_pool useage via a proxy object [Jared Jenkins]
6
+
7
+ * Fix typo on :counter usage [Kevin Bongart]
8
+
9
+ * Use parent redis_id_field if present [Arnaud Lavrard]
10
+
11
+ * Fetch the objects options through a redis_options method [Arnaud Lavrard]
12
+
13
+ == 1.0.1 (14 Oct 2014)
14
+
15
+ * Array handling for unmarshal [dreyks]
16
+
17
+ * Test against Ruby 2.1 / 2.2 on Travis CI [tricknotes]
18
+
19
+ * Redis::Set#randmember method accept count as optional parameter [xeviknal]
20
+
3
21
  == 1.0.0 (25 Jul 2014)
4
22
 
5
23
  * Fix expiration filter to handle atomic blocks, remove method aliasing [nateware]
data/README.md CHANGED
@@ -36,10 +36,17 @@ Add it to your Gemfile as:
36
36
  gem 'redis-objects'
37
37
  ~~~
38
38
 
39
- Redis::Objects needs a handle created by `Redis.new`. The recommended approach
40
- is to set `Redis.current` to point to your server, which Redis::Objects will
41
- pick up automatically.
39
+ Redis::Objects needs a handle created by `Redis.new` or a [ConnectionPool](https://github.com/mperham/connection_pool):
42
40
 
41
+ The recommended approach is to use a `ConnectionPool` since this guarantees that most timeouts in the `redis` client
42
+ do not pollute your existing connection. However, you need to make sure that both `:timeout` and `:size` are set appropriately
43
+ in a multithreaded environment.
44
+ ~~~ruby
45
+ require 'connection_pool'
46
+ Redis::Objects.redis = ConnectionPool.new(size: 5, timeout: 5) { Redis.new(:host => '127.0.0.1', :port => 6379) }
47
+ ~~~
48
+
49
+ Redis::Objects can also default to `Redis.current` if `Redis::Objects.redis` is not set.
43
50
  ~~~ruby
44
51
  Redis.current = Redis.new(:host => '127.0.0.1', :port => 6379)
45
52
  ~~~
@@ -64,6 +71,7 @@ class Post
64
71
  include Redis::Objects
65
72
  end
66
73
 
74
+ # you can also use a ConnectionPool here as well
67
75
  User.redis = Redis.new(:host => '1.2.3.4')
68
76
  Post.redis = Redis.new(:host => '5.6.7.8')
69
77
  ~~~
@@ -97,7 +105,7 @@ user.id # 1
97
105
  user.my_posts.increment
98
106
  user.my_posts.increment
99
107
  user.my_posts.increment
100
- puts user.my_posts # 3
108
+ puts user.my_posts.value # 3
101
109
  user.my_posts.reset
102
110
  puts user.my_posts.value # 0
103
111
  user.my_posts.reset 5
data/Rakefile CHANGED
@@ -4,6 +4,10 @@ desc "run all the specs"
4
4
  task :test do
5
5
  sh "bacon spec/*_spec.rb"
6
6
  end
7
-
8
7
  task :default => :test
9
8
 
9
+ desc "show changelog"
10
+ task :changelog do
11
+ latest = `git tag |tail -1`.chomp
12
+ system "git log --pretty=format:'* %s %b [%an]' #{latest}..HEAD"
13
+ end
@@ -4,7 +4,7 @@ class Redis
4
4
  def initialize(key, *args)
5
5
  @key = key.is_a?(Array) ? key.flatten.join(':') : key
6
6
  @options = args.last.is_a?(Hash) ? args.pop : {}
7
- @myredis = args.first
7
+ @myredis = Objects::ConnectionPoolProxy.proxy_if_needed(args.first)
8
8
  end
9
9
 
10
10
  # Dynamically query the handle to enable resetting midstream
data/lib/redis/objects.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # Redis::Objects - Lightweight object layer around redis-rb
2
2
  # See README.rdoc for usage and approach.
3
3
  require 'redis'
4
+ require 'redis/objects/connection_pool_proxy'
4
5
 
5
6
  class Redis
6
7
  autoload :Counter, 'redis/counter'
@@ -60,7 +61,7 @@ class Redis
60
61
 
61
62
  class << self
62
63
  def redis=(conn)
63
- @redis = conn
64
+ @redis = Objects::ConnectionPoolProxy.proxy_if_needed(conn)
64
65
  end
65
66
  def redis
66
67
  @redis || $redis || Redis.current ||
@@ -88,7 +89,10 @@ class Redis
88
89
  # Class methods that appear in your class when you include Redis::Objects.
89
90
  module ClassMethods
90
91
  # Enable per-class connections (eg, User and Post can use diff redis-server)
91
- attr_writer :redis
92
+ def redis=(conn)
93
+ @redis = Objects::ConnectionPoolProxy.proxy_if_needed(conn)
94
+ end
95
+
92
96
  def redis
93
97
  @redis || Objects.redis
94
98
  end
@@ -109,9 +113,19 @@ class Redis
109
113
  downcase
110
114
  end
111
115
 
116
+ def redis_options(name)
117
+ klass = first_ancestor_with(name)
118
+ return klass.redis_objects[name.to_sym] || {}
119
+ end
120
+
112
121
  def redis_field_redis(name) #:nodoc:
113
122
  klass = first_ancestor_with(name)
114
- return klass.redis_objects[name.to_sym][:redis] || self.redis
123
+ override_redis = klass.redis_objects[name.to_sym][:redis]
124
+ if override_redis
125
+ Objects::ConnectionPoolProxy.proxy_if_needed(override_redis)
126
+ else
127
+ self.redis
128
+ end
115
129
  end
116
130
 
117
131
  def redis_field_key(name, id=nil, context=self) #:nodoc:
@@ -143,7 +157,13 @@ class Redis
143
157
  end
144
158
 
145
159
  def redis_id_field(id=nil)
146
- @redis_id_field = id || @redis_id_field || :id
160
+ @redis_id_field = id || @redis_id_field
161
+
162
+ if superclass && superclass.respond_to?(:redis_id_field)
163
+ @redis_id_field ||= superclass.redis_id_field
164
+ end
165
+
166
+ @redis_id_field ||= :id
147
167
  end
148
168
  end
149
169
 
@@ -153,6 +173,10 @@ class Redis
153
173
  def redis() self.class.redis end
154
174
  def redis_objects() self.class.redis_objects end
155
175
 
176
+ def redis_options(name) #:nodoc:
177
+ return self.class.redis_options(name)
178
+ end
179
+
156
180
  def redis_field_redis(name) #:nodoc:
157
181
  return self.class.redis_field_redis(name)
158
182
  end
@@ -0,0 +1,30 @@
1
+ class Redis
2
+ module Objects
3
+ class ConnectionPoolProxy
4
+ def initialize(pool)
5
+ raise ArgumentError "Should only proxy ConnectionPool!" unless self.class.should_proxy?(pool)
6
+ @pool = pool
7
+ end
8
+
9
+ def method_missing(name, *args, &block)
10
+ @pool.with { |x| x.send(name, *args, &block) }
11
+ end
12
+
13
+ def respond_to_missing?(name, include_all = false)
14
+ @pool.with { |x| x.respond_to?(name, include_all) }
15
+ end
16
+
17
+ def self.should_proxy?(conn)
18
+ defined?(::ConnectionPool) && conn.is_a?(::ConnectionPool)
19
+ end
20
+
21
+ def self.proxy_if_needed(conn)
22
+ if should_proxy?(conn)
23
+ ConnectionPoolProxy.new(conn)
24
+ else
25
+ conn
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -29,7 +29,7 @@ class Redis
29
29
  instance_variable_get("@#{name}") or
30
30
  instance_variable_set("@#{name}",
31
31
  Redis::Counter.new(
32
- redis_field_key(name), redis_field_redis(name), redis_objects[name.to_sym]
32
+ redis_field_key(name), redis_field_redis(name), redis_options(name)
33
33
  )
34
34
  )
35
35
  end
@@ -21,7 +21,7 @@ class Redis
21
21
  instance_variable_get("@#{name}") or
22
22
  instance_variable_set("@#{name}",
23
23
  Redis::HashKey.new(
24
- redis_field_key(name), redis_field_redis(name), redis_objects[name.to_sym]
24
+ redis_field_key(name), redis_field_redis(name), redis_options(name)
25
25
  )
26
26
  )
27
27
  end
@@ -21,7 +21,7 @@ class Redis
21
21
  instance_variable_get("@#{name}") or
22
22
  instance_variable_set("@#{name}",
23
23
  Redis::List.new(
24
- redis_field_key(name), redis_field_redis(name), redis_objects[name.to_sym]
24
+ redis_field_key(name), redis_field_redis(name), redis_options(name)
25
25
  )
26
26
  )
27
27
  end
@@ -21,7 +21,7 @@ class Redis
21
21
  instance_variable_get("@#{name}") or
22
22
  instance_variable_set("@#{name}",
23
23
  Redis::Set.new(
24
- redis_field_key(name), redis_field_redis(name), redis_objects[name.to_sym]
24
+ redis_field_key(name), redis_field_redis(name), redis_options(name)
25
25
  )
26
26
  )
27
27
  end
@@ -21,7 +21,7 @@ class Redis
21
21
  instance_variable_get("@#{name}") or
22
22
  instance_variable_set("@#{name}",
23
23
  Redis::SortedSet.new(
24
- redis_field_key(name), redis_field_redis(name), redis_objects[name.to_sym]
24
+ redis_field_key(name), redis_field_redis(name), redis_options(name)
25
25
  )
26
26
  )
27
27
  end
@@ -21,7 +21,7 @@ class Redis
21
21
  instance_variable_get("@#{name}") or
22
22
  instance_variable_set("@#{name}",
23
23
  Redis::Value.new(
24
- redis_field_key(name), redis_field_redis(name), redis_objects[name.to_sym]
24
+ redis_field_key(name), redis_field_redis(name), redis_options(name)
25
25
  )
26
26
  )
27
27
  end
@@ -1,5 +1,5 @@
1
1
  class Redis
2
2
  module Objects
3
- VERSION = "1.0.1"
3
+ VERSION = "1.1.0"
4
4
  end
5
5
  end
@@ -4,13 +4,13 @@
4
4
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
5
5
 
6
6
  require 'redis/objects'
7
+ require 'connection_pool'
7
8
 
8
9
  BAD_REDIS = "totally bad bogus redis handle"
9
10
 
10
11
  # Grab a global handle
11
12
  describe 'Connection tests' do
12
- it "should support overriding object handles" do
13
-
13
+ it "should support overriding object handles with a vanilla redis connection" do
14
14
  class CustomConnectionObject
15
15
  include Redis::Objects
16
16
 
@@ -41,7 +41,38 @@ describe 'Connection tests' do
41
41
  obj.default_redis_value.clear
42
42
  end
43
43
 
44
- it "should support local handles" do
44
+ it "should support overriding object handles with a connection_pool" do
45
+ class CustomConnectionObject
46
+ include Redis::Objects
47
+
48
+ def id
49
+ return 1
50
+ end
51
+
52
+ redis_handle = ConnectionPool.new { Redis.new(:host => REDIS_HOST, :port => REDIS_PORT, :db => 31) }
53
+ value :redis_value, :redis => redis_handle, :key => 'rval'
54
+ value :default_redis_value, :key => 'rval'
55
+ end
56
+
57
+ obj = CustomConnectionObject.new
58
+
59
+ obj.default_redis_value.value.should == nil
60
+ obj.redis_value.value.should == nil
61
+
62
+ obj.default_redis_value.value = 'foo'
63
+ obj.default_redis_value.value.should == 'foo'
64
+ obj.redis_value.value.should == nil
65
+
66
+ obj.default_redis_value.clear
67
+ obj.redis_value.value = 'foo'
68
+ obj.redis_value.value.should == 'foo'
69
+ obj.default_redis_value.value.should == nil
70
+
71
+ obj.redis_value.clear
72
+ obj.default_redis_value.clear
73
+ end
74
+
75
+ it "should support local handles with a vanilla redis connection" do
45
76
  Redis.current = nil # reset from other tests
46
77
  Redis::Objects.redis = nil
47
78
  @redis_handle = Redis.new(:host => REDIS_HOST, :port => REDIS_PORT)
@@ -86,6 +117,51 @@ describe 'Connection tests' do
86
117
  c.decr(1)
87
118
  end
88
119
 
120
+ it "should support local handles with a connection_pool" do
121
+ Redis.current = nil # reset from other tests
122
+ Redis::Objects.redis = nil
123
+ @redis_handle = ConnectionPool.new { Redis.new(:host => REDIS_HOST, :port => REDIS_PORT) }
124
+
125
+ # Redis.current is lazily auto-populated to touch 6379
126
+ # This why we choose the weird 9212 port to avoid
127
+ Redis.current.inspect.should == Redis.new.inspect
128
+ Redis::Objects.redis.inspect.should == Redis.new.inspect
129
+
130
+ v = Redis::Value.new('conn/value', @redis_handle)
131
+ v.clear
132
+ v.value = 'yay'
133
+ v.value.should == 'yay'
134
+
135
+ h = Redis::HashKey.new('conn/hash', @redis_handle)
136
+ h.clear
137
+ h['k'] = 'v'
138
+
139
+ l = Redis::List.new('conn/list', @redis_handle)
140
+ l.clear
141
+ l << 3
142
+ l << 4
143
+ l << 5
144
+
145
+ s = Redis::Set.new('conn/set', @redis_handle)
146
+ s.clear
147
+ s << 5
148
+ s << 5
149
+ s << 6
150
+ s << 7
151
+
152
+ z = Redis::SortedSet.new('conn/zset', @redis_handle)
153
+ z.clear
154
+ z['a'] = 8
155
+ z['b'] = 7
156
+ z['c'] = 9
157
+ z['d'] = 6
158
+
159
+ c = Redis::Counter.new('conn/counter', @redis_handle)
160
+ c.reset
161
+ c.incr(3)
162
+ c.decr(1)
163
+ end
164
+
89
165
  it "should support Redis.current" do
90
166
  Redis.current = Redis.new(:host => REDIS_HOST, :port => REDIS_PORT)
91
167
 
@@ -97,7 +173,41 @@ describe 'Connection tests' do
97
173
  Redis::Counter.new('conn/counter').should == 2
98
174
  end
99
175
 
100
- it "should support Redis::Objects.redis=" do
176
+ it "should support Redis::Objects.redis= with a connection_pool" do
177
+ @redis_handle = ConnectionPool.new { Redis.new(:host => REDIS_HOST, :port => REDIS_PORT) }
178
+
179
+ # Redis.current is lazily auto-populated to touch 6379
180
+ # This why we choose the weird 9212 port to avoid
181
+ Redis.current = BAD_REDIS
182
+ Redis::Objects.redis.should == BAD_REDIS
183
+
184
+ # This set of tests sucks, it fucks up the per-data-type handles
185
+ # because Redis.current is then set to a BS value, and the lazy
186
+ # init code in redis-rb will keep that value until we clear it.
187
+ # This ends up fucking any sequential tests.
188
+ raises_exception{ Redis::Value.new('conn/value').should.be.nil }
189
+ raises_exception{ Redis::HashKey.new('conn/hash').keys.should == [] }
190
+ raises_exception{ Redis::List.new('conn/list').sort.should == [] }
191
+ raises_exception{ Redis::Set.new('conn/set').sort.should == [] }
192
+ raises_exception{ Redis::SortedSet.new('conn/zset').should == [] }
193
+ raises_exception{ Redis::Counter.new('conn/counter').get.should == 0 }
194
+
195
+ Redis::Objects.redis = @redis_handle
196
+ Redis::Value.new('fart').redis.is_a?(Redis::Objects::ConnectionPoolProxy).should == true
197
+
198
+ # These should now get the correct handle
199
+ Redis::Value.new('conn/value').should == 'yay'
200
+ Redis::HashKey.new('conn/hash').keys.should == ['k']
201
+ Redis::List.new('conn/list').sort.should == ['3', '4', '5']
202
+ Redis::Set.new('conn/set').sort.should == ['5', '6', '7']
203
+ Redis::SortedSet.new('conn/zset').should == ['d', 'b', 'a', 'c']
204
+ Redis::Counter.new('conn/counter').should == 2
205
+
206
+ end
207
+
208
+ it "should support Redis::Objects.redis= with a vanilla redis connection" do
209
+ # reset redis
210
+ Redis::Objects.redis = nil
101
211
  @redis_handle = Redis.new(:host => REDIS_HOST, :port => REDIS_PORT)
102
212
 
103
213
  # Redis.current is lazily auto-populated to touch 6379
@@ -130,5 +240,4 @@ describe 'Connection tests' do
130
240
  # Fix for future tests
131
241
  Redis.current = @redis_handle
132
242
  end
133
-
134
243
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redis-objects
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nate Wiger
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-10-14 00:00:00.000000000 Z
11
+ date: 2015-01-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: connection_pool
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: redis-namespace
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -117,6 +131,7 @@ files:
117
131
  - lib/redis/list.rb
118
132
  - lib/redis/lock.rb
119
133
  - lib/redis/objects.rb
134
+ - lib/redis/objects/connection_pool_proxy.rb
120
135
  - lib/redis/objects/counters.rb
121
136
  - lib/redis/objects/hashes.rb
122
137
  - lib/redis/objects/lists.rb