jruby-memcache-client 1.6.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.
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ .DS_Store
2
+ nbproject/private
data/MIT-LICENSE ADDED
@@ -0,0 +1,24 @@
1
+ Copyright (c) 2008 Abhi Yerra <abhi@traytwo.com>
2
+ Copyright (c) 2009 Ikai Lan <ikai.lan@gmail.com>
3
+ Copyright (c) 2009 Tiago Bastos <comechao@gmail.com>
4
+ Copyright (c) 2009 Frederic Jean <frederic.jean@sun.com>
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining
7
+ a copy of this software and associated documentation files (the
8
+ "Software"), to deal in the Software without restriction, including
9
+ without limitation the rights to use, copy, modify, merge, publish,
10
+ distribute, sublicense, and/or sell copies of the Software, and to
11
+ permit persons to whom the Software is furnished to do so, subject to
12
+ the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be
15
+ included in all copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+
data/README ADDED
@@ -0,0 +1,69 @@
1
+ This projects provides memcached based stores for JRuby. It is a gem based on Ikai Lan's jruby-memcache-client project hosted at http://github.com/ikai/jruby-memcache-client/tree
2
+
3
+ This project is a JRuby wrapper of the Java MemCache library by Greg Whalin
4
+
5
+ http://www.whalin.com/memcached/
6
+
7
+ In production, the standard Ruby MemCache client can cause a thread to hang. In the Glassfish application server, by default there are 5 Grizzly connectors that handle incoming requests. A site that uses MemCache heavily can quickly cause all Grizzly connectors to block and take down a site. I'm hoping that this work I am doing here will help others adopt JRuby as a production platform for their Ruby on Rails applications.
8
+
9
+ The Ruby MemCache library was never written with threaded applications in mind. All threads use the same socket, and multithreaded mode basically wraps the IO with a Mutex. The Java library provides several features that are not available in the Ruby MemCache library:
10
+
11
+ - connection pooling
12
+ - socket timeouts. In forks of the Ruby MemCache library this is achieved either with a Mongrel timeout or use of the Ruby Timeout class, which, at least at the writing of this README, will work unpredictably when being used as a failsafe against hanging IO.
13
+
14
+ As of right now this code only provides a very minimal amount of functionality, but it is enough to use with the Rails cache and cache_fu.
15
+
16
+ Installation
17
+ ------------
18
+ This is a ruby gem that can be installed.
19
+
20
+ gem sources -a http://gems.github.com
21
+ gem install ikai-jruby-memcache-client --remote
22
+
23
+ Replacing Rail's MemCache Client
24
+ --------------------------------
25
+
26
+ Rails ships with a bundled copy of the MemCache client. This client will prevent you from using this gem instead. Adding the following code into your environment.rb file:
27
+
28
+ if RUBY_PLATFORM =~ /java/i
29
+ # Based on instructions from http://www.mikeperham.com/2009/03/03/using-memcache-client-16x-in-rails-23/
30
+ # Brain surgery to use our own version of memcache-client without
31
+ # having to modify activesupport directly.
32
+ # Unload any previous instance of the class
33
+ if Object.const_defined? :MemCache
34
+ Object.instance_eval { remove_const :MemCache }
35
+ end
36
+ # Pull in the exact version we want
37
+ gem 'ikai-jruby-memcache-client', '1.5.0'
38
+
39
+ # Ensure that the memcache-client path is at the front of the loadpath
40
+ $LOAD_PATH.each do |path|
41
+ if path =~ /ikai-jruby-memcache-client/
42
+ $LOAD_PATH.delete(path)
43
+ $LOAD_PATH.unshift(path)
44
+ end
45
+ end
46
+ # If Ruby thinks it's already loaded memcache.rb, force
47
+ # a reload otherwise just require.
48
+ if $".find { |file| file =~ /\Amemcache.rb\Z/ }
49
+ load 'memcache.rb'
50
+ else
51
+ require 'memcache'
52
+ end
53
+ end
54
+
55
+ This will remove the original MemCache client and load our version of the MemCache class instead.
56
+
57
+ Configuration
58
+ -------------
59
+ The JRuby MemCache client uses the same configuration options as the regular MemCache client. Here is how to build the configuration in your environment.rb file:
60
+
61
+ memcache_options = {
62
+ :namespace => 'fortaleza:production_live:',
63
+ }
64
+ memcached_servers = [ ENV['MEMCACHED_LOCATION'] || '0.0.0.0:11211']
65
+
66
+ # Constant used by libs
67
+ CACHE = MemCache.new memcached_servers, memcache_options if RUBY_PLATFORM =~ /java/
68
+
69
+ Note that this may vary based on your particular configuration method and environment.
data/Rakefile ADDED
@@ -0,0 +1,28 @@
1
+ begin
2
+ require 'jeweler'
3
+ Jeweler::Tasks.new do |gemspec|
4
+ gemspec.name = "jruby-memcache-client"
5
+ gemspec.summary = "A drop in replacement for Ruby's memcache-client."
6
+ gemspec.email = "abhi@traytwo.com"
7
+ gemspec.homepage = "http://github.com/abhiyerra/jruby-memcache-client"
8
+ gemspec.description = "A drop in replacement for Ruby's memcache-client."
9
+ gemspec.authors = ["Abhi Yerra", "Ikai Lan", "Frederic Jean", "Lennon Day-Reynolds"]
10
+ end
11
+ rescue LoadError
12
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
13
+ end
14
+
15
+ if RUBY_PLATFORM =~ /java/i
16
+ begin
17
+ require 'spec/rake/spectask'
18
+
19
+ task :default => :spec
20
+
21
+ desc "Run the specs for the jruby-memcache-client gem"
22
+ Spec::Rake::SpecTask.new
23
+ rescue LoadError
24
+ puts "You must have rspec installed in order to run the tests."
25
+ end
26
+ else
27
+ puts "You must run rake under JRuby."
28
+ end
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :minor: 6
3
+ :major: 1
4
+ :patch: 0
@@ -0,0 +1,45 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{jruby-memcache-client}
5
+ s.version = "1.6.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Abhi Yerra", "Ikai Lan", "Frederic Jean", "Lennon Day-Reynolds"]
9
+ s.date = %q{2009-05-20}
10
+ s.description = %q{A drop in replacement for Ruby's memcache-client.}
11
+ s.email = %q{abhi@traytwo.com}
12
+ s.extra_rdoc_files = [
13
+ "README"
14
+ ]
15
+ s.files = [
16
+ ".gitignore",
17
+ "MIT-LICENSE",
18
+ "README",
19
+ "Rakefile",
20
+ "VERSION.yml",
21
+ "jruby-memcache-client.gemspec",
22
+ "lib/java/java_memcached-release_2.0.1.jar",
23
+ "lib/memcache.rb",
24
+ "spec/jruby_memcache_spec.rb"
25
+ ]
26
+ s.has_rdoc = true
27
+ s.homepage = %q{http://github.com/ikai/jruby-memcache-client}
28
+ s.rdoc_options = ["--charset=UTF-8"]
29
+ s.require_paths = ["lib"]
30
+ s.rubygems_version = %q{1.3.1}
31
+ s.summary = %q{A drop in replacement for Ruby's memcache-client.}
32
+ s.test_files = [
33
+ "spec/jruby_memcache_spec.rb"
34
+ ]
35
+
36
+ if s.respond_to? :specification_version then
37
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
38
+ s.specification_version = 2
39
+
40
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
41
+ else
42
+ end
43
+ else
44
+ end
45
+ end
data/lib/memcache.rb ADDED
@@ -0,0 +1,306 @@
1
+ require 'java'
2
+
3
+ require File.dirname(__FILE__) + '/java/java_memcached-release_2.0.1.jar'
4
+
5
+ class MemCache
6
+ include_class 'com.danga.MemCached.MemCachedClient'
7
+ include_class 'com.danga.MemCached.SockIOPool'
8
+
9
+ VERSION = '1.6.0'
10
+
11
+ ##
12
+ # Default options for the cache object.
13
+
14
+ DEFAULT_OPTIONS = {
15
+ :namespace => nil,
16
+ :readonly => false,
17
+ :multithread => true,
18
+ :pool_initial_size => 5,
19
+ :pool_min_size => 5,
20
+ :pool_max_size => 250,
21
+ :pool_max_idle => (1000 * 60 * 60 * 6),
22
+ :pool_maintenance_thread_sleep => 30,
23
+ :pool_use_nagle => false,
24
+ :pool_socket_timeout => 3000,
25
+ :pool_socket_connect_timeout => 3000,
26
+ :pool_name => 'default'
27
+ }
28
+
29
+ ## CHARSET for Marshalling
30
+ MARSHALLING_CHARSET = 'UTF-8'
31
+
32
+ ##
33
+ # Default memcached port.
34
+
35
+ DEFAULT_PORT = 11211
36
+
37
+ ##
38
+ # Default memcached server weight.
39
+
40
+ DEFAULT_WEIGHT = 1
41
+
42
+ attr_accessor :request_timeout
43
+
44
+ ##
45
+ # The namespace for this instance
46
+
47
+ attr_reader :namespace
48
+
49
+ ##
50
+ # The multithread setting for this instance
51
+
52
+ attr_reader :multithread
53
+
54
+ ##
55
+ # The configured socket pool name for this client.
56
+ attr_reader :pool_name
57
+
58
+ ##
59
+ # Configures the client
60
+ def initialize(*args)
61
+ @servers = []
62
+ opts = {}
63
+
64
+ case args.length
65
+ when 0 then # NOP
66
+ when 1 then
67
+ arg = args.shift
68
+ case arg
69
+ when Hash then opts = arg
70
+ when Array then @servers = arg
71
+ when String then @servers = [arg]
72
+ else raise ArgumentError, 'first argument must be Array, Hash or String'
73
+ end
74
+ when 2 then
75
+ @servers, opts = args
76
+ @servers = [@servers].flatten
77
+ else
78
+ raise ArgumentError, "wrong number of arguments (#{args.length} for 2)"
79
+ end
80
+
81
+ opts = DEFAULT_OPTIONS.merge opts
82
+
83
+ @namespace = opts[:namespace] || opts["namespace"]
84
+ @pool_name = opts[:pool_name] || opts["pool_name"]
85
+ @readonly = opts[:readonly] || opts["readonly"]
86
+
87
+ @client = MemCachedClient.new(@pool_name)
88
+
89
+ @client.primitiveAsString = true
90
+ @client.sanitizeKeys = false
91
+
92
+ weights = Array.new(@servers.size, DEFAULT_WEIGHT)
93
+
94
+ @pool = SockIOPool.getInstance(@pool_name)
95
+ unless @pool.initialized?
96
+ # // set the servers and the weights
97
+ @pool.servers = @servers.to_java(:string)
98
+ @pool.weights = weights.to_java(:Integer)
99
+
100
+ # // set some basic pool settings
101
+ # // 5 initial, 5 min, and 250 max conns
102
+ # // and set the max idle time for a conn
103
+ # // to 6 hours
104
+ @pool.initConn = opts[:pool_initial_size]
105
+ @pool.minConn = opts[:pool_min_size]
106
+ @pool.maxConn = opts[:pool_max_size]
107
+ @pool.maxIdle = opts[:pool_max_idle]
108
+
109
+ # // set the sleep for the maint thread
110
+ # // it will wake up every x seconds and
111
+ # // maintain the pool size
112
+ @pool.maintSleep = opts[:pool_maintenance_thread_sleep]
113
+ #
114
+ # // set some TCP settings
115
+ # // disable nagle
116
+ # // set the read timeout to 3 secs
117
+ # // and don't set a connect timeout
118
+ @pool.nagle = opts[:pool_use_nagle]
119
+ @pool.socketTO = opts[:pool_socket_timeout]
120
+ @pool.socketConnectTO = opts[:pool_socket_connect_timeout]
121
+ @pool.aliveCheck = true
122
+ @pool.initialize__method
123
+ end
124
+ end
125
+
126
+ def reset
127
+ @pool.shut_down
128
+ @pool.initialize__method
129
+ end
130
+
131
+ ##
132
+ # Returns the servers that the client has been configured to
133
+ # use. Injects an alive? method into the string so it works with the
134
+ # updated Rails MemCacheStore session store class.
135
+ def servers
136
+ @pool.servers.to_a.collect do |s|
137
+ s.instance_eval(<<-EOIE)
138
+ def alive?
139
+ #{!!stats[s]}
140
+ end
141
+ EOIE
142
+ s
143
+ end rescue []
144
+ end
145
+
146
+ ##
147
+ # Determines whether any of the connections to the servers is
148
+ # alive. We are alive if it is the case.
149
+ def alive?
150
+ servers.to_a.any? { |s| s.alive? }
151
+ end
152
+
153
+ alias :active? :alive?
154
+
155
+ ##
156
+ # Retrieves a value associated with the key from the
157
+ # cache. Retrieves the raw value if the raw parameter is set.
158
+ def get(key, raw = false)
159
+ value = @client.get(make_cache_key(key))
160
+ return nil if value.nil?
161
+ unless raw
162
+ marshal_bytes = java.lang.String.new(value).getBytes(MARSHALLING_CHARSET)
163
+ value = Marshal.load(String.from_java_bytes(marshal_bytes))
164
+ end
165
+ value
166
+ end
167
+
168
+ alias :[] :get
169
+
170
+ ##
171
+ # Retrieves the values associated with the keys parameter.
172
+ def get_multi(keys, raw = false)
173
+ keys = keys.map {|k| make_cache_key(k)}
174
+ keys = keys.to_java :String
175
+ values = {}
176
+ values_j = @client.getMulti(keys)
177
+ values_j.to_a.each {|kv|
178
+ k,v = kv
179
+ next if v.nil?
180
+ unless raw
181
+ marshal_bytes = java.lang.String.new(v).getBytes(MARSHALLING_CHARSET)
182
+ v = Marshal.load(String.from_java_bytes(marshal_bytes))
183
+ end
184
+ values[k] = v
185
+ }
186
+ values
187
+ end
188
+
189
+ ##
190
+ # Associates a value with a key in the cache. MemCached will expire
191
+ # the value if an expiration is provided. The raw parameter allows
192
+ # us to store a value without marshalling it first.
193
+ def set(key, value, expiry = 0, raw = false)
194
+ raise MemCacheError, "Update of readonly cache" if @readonly
195
+ value = marshal_value(value) unless raw
196
+ key = make_cache_key(key)
197
+ if expiry == 0
198
+ @client.set key, value
199
+ else
200
+ @client.set key, value, expiration(expiry)
201
+ end
202
+ end
203
+
204
+ alias :[]= :set
205
+
206
+ ##
207
+ # Add a new value to the cache following the same conventions that
208
+ # are used in the set method.
209
+ def add(key, value, expiry = 0, raw = false)
210
+ raise MemCacheError, "Update of readonly cache" if @readonly
211
+ value = marshal_value(value) unless raw
212
+ if expiry == 0
213
+ @client.add make_cache_key(key), value
214
+ else
215
+ @client.add make_cache_key(key), value, expiration(expiry)
216
+ end
217
+ end
218
+
219
+ ##
220
+ # Removes the value associated with the key from the cache. This
221
+ # will ignore values that are not already present in the cache,
222
+ # which makes this safe to use without first checking for the
223
+ # existance of the key in the cache first.
224
+ def delete(key, expires = 0)
225
+ raise MemCacheError, "Update of readonly cache" if @readonly
226
+ @client.delete(make_cache_key(key))
227
+ end
228
+
229
+ ##
230
+ # Replaces the value associated with a key in the cache if it
231
+ # already is stored. It will not add the value to the cache if it
232
+ # isn't already present.
233
+ def replace(key, value, expiry = 0, raw = false)
234
+ raise MemCacheError, "Update of readonly cache" if @readonly
235
+ value = marshal_value(value) unless raw
236
+ if expiry == 0
237
+ @client.replace make_cache_key(key), value
238
+ else
239
+ @client.replace make_cache_key(key), value
240
+ end
241
+ end
242
+
243
+ ##
244
+ # Increments the value associated with the key by a certain amount.
245
+ def incr(key, amount = 1)
246
+ raise MemCacheError, "Update of readonly cache" if @readonly
247
+ value = get(key) || 0
248
+ value += amount
249
+ set key, value
250
+ value
251
+ end
252
+
253
+ ##
254
+ # Decrements the value associated with the key by a certain amount.
255
+ def decr(key, amount = 1)
256
+ raise MemCacheError, "Update of readonly cache" if @readonly
257
+ value = get(key) || 0
258
+ value -= amount
259
+ set key, value
260
+ value
261
+ end
262
+
263
+ ##
264
+ # Clears the cache.
265
+ def flush_all
266
+ @client.flush_all
267
+ end
268
+
269
+ ##
270
+ # Reports statistics on the cache.
271
+ def stats
272
+ stats_hash = {}
273
+ @client.stats.each do |server, stats|
274
+ stats_hash[server] = Hash.new
275
+ stats.each do |key, value|
276
+ unless key == 'version'
277
+ value = value.to_f
278
+ value = value.to_i if value == value.ceil
279
+ end
280
+ stats_hash[server][key] = value
281
+ end
282
+ end
283
+ stats_hash
284
+ end
285
+
286
+ class MemCacheError < RuntimeError; end
287
+
288
+ protected
289
+ def make_cache_key(key)
290
+ if namespace.nil? then
291
+ key
292
+ else
293
+ "#{@namespace}:#{key}"
294
+ end
295
+ end
296
+
297
+ def expiration(expiry)
298
+ java.util.Date.new((Time.now.to_i + expiry) * 1000)
299
+ end
300
+
301
+ def marshal_value(value)
302
+ marshal_bytes = Marshal.dump(value).to_java_bytes
303
+ java.lang.String.new(marshal_bytes, MARSHALLING_CHARSET)
304
+ end
305
+ end
306
+
@@ -0,0 +1,243 @@
1
+ require 'java'
2
+ require File.dirname(__FILE__) + '/../lib/memcache'
3
+
4
+ describe MemCache do
5
+ before(:all) do
6
+ @server = "127.0.0.1:11211"
7
+ @client = MemCache.new @server
8
+ @client.flush_all
9
+ end
10
+
11
+ after(:each) do
12
+ @client.flush_all
13
+ end
14
+
15
+ it "should return nil for a non-existent key" do
16
+ @client.get('non-existent-key').should be_nil
17
+ end
18
+
19
+ describe "setting servers" do
20
+ it "should work if the instance is created with a single String argument" do
21
+ @client = MemCache.new @server
22
+ @client.servers.should == [@server]
23
+ end
24
+
25
+ it "should work if the instance is created with an Array" do
26
+ @client = MemCache.new [ @server ]
27
+ @client.servers.should == [ @server ]
28
+ end
29
+
30
+ it "should work if the instance is created with a Hash" do
31
+ @client = MemCache.new [ @server ], :namespace => 'test'
32
+ @client.servers.should == [ @server ]
33
+ end
34
+
35
+ it "should work with an explicit pool name" do
36
+ @client = MemCache.new([@server], :pool_name => 'new_pool')
37
+ @client.pool_name.should == 'new_pool'
38
+ end
39
+ end
40
+
41
+ describe "namespacing" do
42
+ before(:each) do
43
+ @ns = 'namespace'
44
+ @nsclient = MemCache.new [ @server ] , :namespace => @ns
45
+ @nsclient.flush_all
46
+ @nsclient.set "test", 333, 0
47
+ end
48
+
49
+ it "should set and get values transparently" do
50
+ @nsclient.get("test").to_i.should == 333
51
+ end
52
+
53
+ it "should set values to the given namespace" do
54
+ @client.get("#{@ns}:test").to_i.should == 333
55
+ end
56
+
57
+ it "should not set a value without the given namespace" do
58
+ @client.get("test").to_i.should_not == 333
59
+ end
60
+
61
+ it "should delete values in the given namespace" do
62
+ @nsclient.delete "test"
63
+ @nsclient.get("test").should be_nil
64
+ end
65
+
66
+ it "should increment in the given namespace" do
67
+ @nsclient.incr("test").to_i.should == 334
68
+ end
69
+
70
+ it "should decrement values in the given namespace" do
71
+ @nsclient.decr("test").should == 332
72
+ end
73
+ end
74
+
75
+ describe "after setting a value to MemCache" do
76
+ before(:each) do
77
+ @client.set 'key', 'value'
78
+ end
79
+
80
+ it "should be able to retrieve the value" do
81
+ @client.get('key').should == 'value'
82
+ end
83
+
84
+ it "should not be able to retrieve the value after deleting" do
85
+ @client.delete('key')
86
+ @client.get('key').should be_nil
87
+ end
88
+
89
+ it "should not be able to retrieve the value after flushing everything" do
90
+ @client.flush_all
91
+ @client.get("key").should be_nil
92
+ end
93
+
94
+ it "should work exactly the same if the []= operator were used" do
95
+ @client['key'] = 'val'
96
+ @client.get('key').should == 'val'
97
+ end
98
+ end
99
+
100
+ describe "replacing values from the cache." do
101
+ before :each do
102
+ @client['key'] = 'value'
103
+ end
104
+
105
+ it "should be able to replace the stored value." do
106
+ @client.replace('key', 'new value').should be_true
107
+ @client['key'].should == 'new value'
108
+ end
109
+
110
+ it "should not replace values that are not in the cache." do
111
+ @client.replace('notthere', 'value').should be_false
112
+ end
113
+ end
114
+
115
+ describe "using the Hash notation" do
116
+ before :each do
117
+ @client['key'] = 'value'
118
+ end
119
+
120
+ it "should be able to retrieve the value using []" do
121
+ @client['key'].should == 'value'
122
+ end
123
+
124
+ it "should be able to retrieve the value using get" do
125
+ @client.get('key').should == 'value'
126
+ end
127
+ end
128
+
129
+ describe "#stats" do
130
+ it "should return a hash" do
131
+ @client.stats.should be_instance_of(Hash)
132
+ end
133
+
134
+ # it "should return 0 for curr_items" do
135
+ # @client.stats[@server]['curr_items'].should == 0
136
+ # end
137
+
138
+ it "should return a float for rusage_system and rusage_user" do
139
+ @client.stats[@server]['rusage_system'].should be_instance_of(Float)
140
+ @client.stats[@server]['rusage_user'].should be_instance_of(Float)
141
+ end
142
+
143
+ it "should return a String for version" do
144
+ @client.stats[@server]['version'].should be_instance_of(String)
145
+ end
146
+
147
+ end
148
+
149
+ describe "#incr" do
150
+
151
+ it "should increment a value by 1 without a second parameter" do
152
+ @client.set 'incr', 100, 0
153
+ @client.incr 'incr'
154
+ @client.get('incr').to_i.should == 101
155
+ end
156
+
157
+ it "should increment a value by a given second parameter" do
158
+ @client.set 'incr', 100, 0
159
+ @client.incr 'incr', 20
160
+ @client.get('incr').to_i.should == 120
161
+ end
162
+ end
163
+
164
+ describe "#decr" do
165
+
166
+ it "should decrement a value by 1 without a second parameter" do
167
+ @client.set 'decr', 100, 0
168
+ @client.decr 'decr'
169
+ @client.get('decr').to_i.should == 99
170
+ end
171
+
172
+ it "should decrement a value by a given second parameter" do
173
+ @client.set 'decr', 100, 0
174
+ @client.decr 'decr', 20
175
+ @client.get('decr').to_i.should == 80
176
+ end
177
+ end
178
+
179
+ describe "with Ruby Objects" do
180
+ it "should be able to transparently set and get equivalent Ruby objects" do
181
+ obj = { :test => :hi }
182
+ @client.set('obj', obj)
183
+ @client.get('obj').should == obj
184
+ end
185
+ end
186
+
187
+ describe "using set with an expiration" do
188
+ it "should make a value unretrievable if the expiry is set to a negative value" do
189
+ @client.set('key', 'val', -1)
190
+ @client.get('key').should be_nil
191
+ end
192
+
193
+ it "should make a value retrievable for only the amount of time if a value is given" do
194
+ @client.set('key', 'val', 2)
195
+ @client.get('key').should == 'val'
196
+ sleep(3)
197
+ @client.get('key').should be_nil
198
+ end
199
+ end
200
+
201
+ describe "#get_multi" do
202
+ it "should get 2 keys" do
203
+ @client.set('key', 'val')
204
+ @client.set('key2', 'val2')
205
+ @client.get_multi(%w/key key2/).should == {'key' => 'val', 'key2' => 'val2'}
206
+ end
207
+
208
+ it "should ignore nil values" do
209
+ @client.set('key', 'val')
210
+ @client.set('key2', 'val2')
211
+ @client.get_multi(%w/key key2 key3/).should == {'key' => 'val', 'key2' => 'val2'}
212
+ end
213
+
214
+ it "should not marshall if requested" do
215
+ @client.set('key', 'val', 0, true)
216
+ @client.set('key2', 'val2', 0, true)
217
+ @client.get_multi(%w/key key2/, true).should == {'key' => 'val', 'key2' => 'val2'}
218
+ end
219
+ end
220
+
221
+ describe "aliveness of the MemCache server." do
222
+ before :each do
223
+ @servers = ["localhost:11211", "localhost:11212", {:pool_name => "test"}]
224
+ @client = MemCache.new @servers
225
+ @client.flush_all
226
+ end
227
+
228
+ it "should report the client as being alive." do
229
+ @client.should be_alive
230
+ end
231
+
232
+ it "should report localhost:11211 as being alive." do
233
+ servers = @client.servers
234
+ servers.first.should be_alive
235
+ end
236
+
237
+ it "should report localhost:11212 as not being alive." do
238
+ servers = @client.servers
239
+ servers.find {|s| s.to_s == "localhost:11212"}.should be_nil
240
+ end
241
+ end
242
+ end
243
+
metadata ADDED
@@ -0,0 +1,66 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jruby-memcache-client
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.6.0
5
+ platform: ruby
6
+ authors:
7
+ - Abhi Yerra
8
+ - Ikai Lan
9
+ - Frederic Jean
10
+ - Lennon Day-Reynolds
11
+ autorequire:
12
+ bindir: bin
13
+ cert_chain: []
14
+
15
+ date: 2009-05-20 00:00:00 -06:00
16
+ default_executable:
17
+ dependencies: []
18
+
19
+ description: A drop in replacement for Ruby's memcache-client.
20
+ email: abhi@traytwo.com
21
+ executables: []
22
+
23
+ extensions: []
24
+
25
+ extra_rdoc_files:
26
+ - README
27
+ files:
28
+ - .gitignore
29
+ - MIT-LICENSE
30
+ - README
31
+ - Rakefile
32
+ - VERSION.yml
33
+ - jruby-memcache-client.gemspec
34
+ - lib/java/java_memcached-release_2.0.1.jar
35
+ - lib/memcache.rb
36
+ - spec/jruby_memcache_spec.rb
37
+ has_rdoc: true
38
+ homepage: http://github.com/ikai/jruby-memcache-client
39
+ licenses: []
40
+
41
+ post_install_message:
42
+ rdoc_options:
43
+ - --charset=UTF-8
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: "0"
51
+ version:
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ version:
58
+ requirements: []
59
+
60
+ rubyforge_project:
61
+ rubygems_version: 1.3.4
62
+ signing_key:
63
+ specification_version: 2
64
+ summary: A drop in replacement for Ruby's memcache-client.
65
+ test_files:
66
+ - spec/jruby_memcache_spec.rb