spymemcached.jruby 1.0.3-java → 1.0.4-java

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
  SHA1:
3
- metadata.gz: 5780ea53b6d60b038125beb9dd617f8add8cbbc7
4
- data.tar.gz: e55cd318622f535a5351ab76d02b666b2294dbab
3
+ metadata.gz: de172a58da9de394e290392fe8e3797e917d98ca
4
+ data.tar.gz: c73d9b51e084d5858d7191a4a5ab93f6bd6642bd
5
5
  SHA512:
6
- metadata.gz: a78224ec0b00eb60041e3e0ccfaf2a97b37b79c139e6f7e766fafe9d0133fa292edd77b4b5e5e17bacd1d6bf2d2f880a37439c491f584d4e236da4bc96ce15d1
7
- data.tar.gz: e022c6ef66b52a9da19958a9753dcda754d536050305a3c0e87e62095894e0f8c16e3bb103fcec378bbdfacb26af09e932644c1b0c7c75c6e90c27a64c9b3303
6
+ metadata.gz: e7533c8391fb29bf4cabdfcdfb97319d4b0924f164d87e8e67e1fdda173135fd03bbb24ab863eadb0670928a1dbf345f3f29f8e36b1c3e523c35f7215d4eebbe
7
+ data.tar.gz: f035eca85fbb17adc7e5d493a8f0d84880f9e38fa7270893a7beac3bd5e7adffb1798971fae850ae9c756aad446897cc5c68d76980abe8cbc0314ac22f58536a
data/README.md CHANGED
@@ -0,0 +1,43 @@
1
+ Spymemcached.jruby
2
+ ================
3
+
4
+ A JRuby extension wraps the latest spymemcached client.
5
+
6
+ Usage
7
+ ----------------
8
+
9
+
10
+ Start a local networked memcached server:
11
+
12
+ $ memcached -p 11211
13
+
14
+ Require the library and instantiate a Spymemcached object at a global level:
15
+
16
+ require 'spymemcached'
17
+ $cache = Spymemcached.new("localhost:11211")
18
+
19
+ Setup multiple servers with options
20
+
21
+ require 'spymemcached'
22
+ $cache = Spymemcached.new(['memcached1.host:11211', 'memcached2.host:11211', 'memcached3.host:11211'],
23
+ {:namespace => 'appName', :timeout => 0.1, :binary => true})
24
+
25
+ Valid +options+ are:
26
+
27
+ [:namespace] Prepends this value to all keys added or retrieved.
28
+ [:timeout] Time to use as the socket read timeout, seconds. Defaults to 0.5 sec.
29
+ [:binary] Talks binary protocol with Memcached server. Default to true.
30
+
31
+ Rails 3 & 4
32
+
33
+ TODO
34
+
35
+ Rails 2.3
36
+
37
+ ActionController::Base.cache_store = :mem_cache_store, Spymemcached.new(servers).rails23
38
+
39
+
40
+ Performance
41
+ ---------------
42
+
43
+ [Benchmark result](https://github.com/ThoughtWorksStudios/memcached-client-benchmark) compared with gem dalli and jruby-memcached
data/lib/spymemcached.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'spymemcached-2.11.4.jar'
2
2
  require 'spymemcached_adapter.jar'
3
3
  require 'spymemcached_adapter'
4
+ require 'digest/md5'
4
5
 
5
6
  #
6
7
  # Memcached client Spymemcached JRuby extension
@@ -9,6 +10,7 @@ class Spymemcached
9
10
  class Error < StandardError; end
10
11
  class TimeoutError < Error; end
11
12
 
13
+ ESCAPE_KEY_CHARS = /[\x00-\x20%\x7F-\xFF]/n
12
14
  # default options for client
13
15
  DEFAULT_OPTIONS = {
14
16
  :timeout => 0.5, # second
@@ -49,53 +51,54 @@ class Spymemcached
49
51
  end
50
52
 
51
53
  def get(key)
52
- @client.get(ns(key))
54
+ @client.get(encode(key))
53
55
  end
54
56
  alias :[] :get
55
57
 
56
58
  def get_multi(*keys)
57
- Hash[@client.get_multi(keys.map(&method(:ns))).map {|k, v| [unns(k), v]}]
59
+ key_map = Hash[keys.flatten.compact.map {|k| [encode(k), k]}]
60
+ Hash[@client.get_multi(key_map.keys).map {|k, v| [key_map[k], v]}]
58
61
  end
59
62
 
60
- def add(key, value, ttl=0, opts={})
61
- @client.add(ns(key), value, ttl)
63
+ def add(key, value, ttl=0)
64
+ @client.add(encode(key), value, ttl)
62
65
  end
63
66
 
64
- def set(key, value, ttl=0, opts={})
65
- @client.set(ns(key), value, ttl)
67
+ def set(key, value, ttl=0)
68
+ @client.set(encode(key), value, ttl)
66
69
  end
67
70
  alias :[]= :set
68
71
 
69
72
  def cas(key, ttl=0, &block)
70
- @client.cas(ns(key), ttl, &block)
73
+ @client.cas(encode(key), ttl, &block)
71
74
  end
72
75
 
73
76
  def replace(key, value, ttl=0)
74
- @client.replace(ns(key), value, ttl)
77
+ @client.replace(encode(key), value, ttl)
75
78
  end
76
79
 
77
80
  def delete(key)
78
- @client.delete(ns(key))
81
+ @client.delete(encode(key))
79
82
  end
80
83
 
81
84
  def incr(key, by=1)
82
- @client.incr(ns(key), by)
85
+ @client.incr(encode(key), by)
83
86
  end
84
87
 
85
88
  def decr(key, by=1)
86
- @client.decr(ns(key), by)
89
+ @client.decr(encode(key), by)
87
90
  end
88
91
 
89
92
  def append(key, value)
90
- @client.append(ns(key), value)
93
+ @client.append(encode(key), value)
91
94
  end
92
95
 
93
96
  def prepend(key, value)
94
- @client.prepend(ns(key), value)
97
+ @client.prepend(encode(key), value)
95
98
  end
96
99
 
97
100
  def touch(key, ttl=0)
98
- @client.touch(ns(key), ttl)
101
+ @client.touch(encode(key), ttl)
99
102
  end
100
103
 
101
104
  def stats
@@ -116,29 +119,31 @@ class Spymemcached
116
119
  @client.shutdown
117
120
  end
118
121
 
119
- # compatible api
122
+ # compatible api with Rails 2.3 MemcacheStore
123
+ # ActionController::Base.cache_store = :mem_cache_store, Spymemcached.new(servers).rails23
120
124
  def rails23
121
125
  require 'spymemcached/rails23'
122
126
  Rails23.new(self)
123
127
  end
124
128
 
125
129
  private
126
- def raw?(opts)
127
- opts.is_a?(Hash) ? opts[:raw] : opts
130
+ def encode(key)
131
+ escape_key(namespace ? "#{namespace.call}:#{key}" : key)
128
132
  end
129
133
 
130
- def ns(key)
131
- return key unless namespace
132
- "#{namespace.call}:#{key}"
134
+ def namespace
135
+ @namespace
133
136
  end
134
137
 
135
- def unns(k)
136
- return k unless namespace
137
- @ns_size ||= namespace.call.size + 1
138
- k[@ns_size..-1]
138
+ # Memcache keys are binaries. So we need to force their encoding to binary
139
+ # before applying the regular expression to ensure we are escaping all
140
+ # characters properly.
141
+ def escape_key(key)
142
+ key = key.to_s.dup
143
+ key = key.force_encoding(Encoding::ASCII_8BIT)
144
+ key = key.gsub(ESCAPE_KEY_CHARS){ |match| "%#{match.getbyte(0).to_s(16).upcase}" }
145
+ key = "#{key[0, 213]}:md5:#{Digest::MD5.hexdigest(key)}" if key.size > 250
146
+ key
139
147
  end
140
148
 
141
- def namespace
142
- @namespace
143
- end
144
149
  end
@@ -74,6 +74,7 @@ class SpymemcachedBinaryProtocolTest < Test::Unit::TestCase
74
74
  assert_equal(2, ret.size)
75
75
  assert_equal('v1', ret['k1'])
76
76
  assert_equal(Msg.new('v2'), ret['k2'])
77
+ assert_equal(ret, @client.get_multi(['k1', 'k2', 'k3']))
77
78
  end
78
79
 
79
80
  def test_cas
@@ -74,6 +74,7 @@ class SpymemcachedPlainProtocolTest < Test::Unit::TestCase
74
74
  assert_equal(2, ret.size)
75
75
  assert_equal('v1', ret['k1'])
76
76
  assert_equal(Msg.new('v2'), ret['k2'])
77
+ assert_equal(ret, @client.get_multi(['k1', 'k2', 'k3']))
77
78
  end
78
79
 
79
80
  def test_cas
@@ -1,3 +1,4 @@
1
+ # encoding: UTF-8
1
2
  require 'test_helper'
2
3
 
3
4
  class SpymemcachedTest < Test::Unit::TestCase
@@ -172,4 +173,12 @@ class SpymemcachedTest < Test::Unit::TestCase
172
173
  assert_match(/\:11211/, v.keys.first)
173
174
  assert_match(/\d\.\d+\.\d+/, v.values.first)
174
175
  end
176
+
177
+ def test_escape_key
178
+ k = 'k 开' * 250
179
+ @client.add(k, 'v1')
180
+ assert_equal('v1', @client.get(k))
181
+ @client.set(k, 'v2')
182
+ assert_equal({k => 'v2'}, @client.get_multi(k))
183
+ end
175
184
  end
data/test/test_helper.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'test/unit'
2
+ $LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
2
3
  require "spymemcached"
3
4
 
4
5
  class Msg < Struct.new(:name)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spymemcached.jruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.0.4
5
5
  platform: java
6
6
  authors:
7
7
  - Xiao Li
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-10-27 00:00:00.000000000 Z
11
+ date: 2014-10-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake