astro-remcached 0.2.2 → 0.3.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/VERSION.yml +2 -2
- data/lib/remcached.rb +78 -11
- data/lib/remcached/client.rb +0 -17
- data/lib/remcached/const.rb +4 -0
- data/lib/remcached/packet.rb +56 -8
- data/remcached.gemspec +9 -6
- data/spec/client_spec.rb +0 -116
- data/spec/memcached_spec.rb +201 -5
- metadata +3 -3
data/VERSION.yml
CHANGED
data/lib/remcached.rb
CHANGED
@@ -56,31 +56,98 @@ module Memcached
|
|
56
56
|
hashed
|
57
57
|
end
|
58
58
|
|
59
|
-
|
59
|
+
|
60
|
+
##
|
61
|
+
# Memcached operations
|
62
|
+
##
|
63
|
+
|
64
|
+
def operation(request_klass, contents, &callback)
|
60
65
|
client = client_for_key(contents[:key])
|
61
66
|
if client
|
62
|
-
client.
|
67
|
+
client.send_request request_klass.new(contents), &callback
|
63
68
|
elsif callback
|
64
69
|
callback.call :status => Errors::DISCONNECTED
|
65
70
|
end
|
66
71
|
end
|
67
72
|
|
68
|
-
|
69
|
-
##
|
70
|
-
# Memcached operations
|
71
|
-
##
|
72
|
-
|
73
73
|
def add(contents, &callback)
|
74
|
-
operation
|
74
|
+
operation Request::Add, contents, &callback
|
75
75
|
end
|
76
76
|
def get(contents, &callback)
|
77
|
-
operation
|
77
|
+
operation Request::Get, contents, &callback
|
78
78
|
end
|
79
79
|
def set(contents, &callback)
|
80
|
-
operation
|
80
|
+
operation Request::Set, contents, &callback
|
81
81
|
end
|
82
82
|
def delete(contents, &callback)
|
83
|
-
operation
|
83
|
+
operation Request::Delete, contents, &callback
|
84
|
+
end
|
85
|
+
|
86
|
+
|
87
|
+
##
|
88
|
+
# Multi operations
|
89
|
+
#
|
90
|
+
##
|
91
|
+
|
92
|
+
def multi_operation(request_klass, contents_list, &callback)
|
93
|
+
results = {}
|
94
|
+
|
95
|
+
# Assemble client connections per keys
|
96
|
+
client_contents = {}
|
97
|
+
contents_list.each do |contents|
|
98
|
+
client = client_for_key(contents[:key])
|
99
|
+
if client
|
100
|
+
client_contents[client] ||= []
|
101
|
+
client_contents[client] << contents
|
102
|
+
else
|
103
|
+
puts "no client for #{contents[:key].inspect}"
|
104
|
+
results[contents[:key]] = {:status => Memcached::Errors::DISCONNECTED}
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# send requests and wait for responses per client
|
109
|
+
clients_pending = client_contents.length
|
110
|
+
client_contents.each do |client,contents_list|
|
111
|
+
last_i = contents_list.length - 1
|
112
|
+
client_results = {}
|
113
|
+
|
114
|
+
contents_list.each_with_index do |contents,i|
|
115
|
+
if i < last_i
|
116
|
+
request = request_klass::Quiet.new(contents)
|
117
|
+
client.send_request(request) { |response|
|
118
|
+
results[contents[:key]] = response
|
119
|
+
}
|
120
|
+
else # last request for this client
|
121
|
+
request = request_klass.new(contents)
|
122
|
+
client.send_request(request) { |response|
|
123
|
+
results[contents[:key]] = response
|
124
|
+
clients_pending -= 1
|
125
|
+
if clients_pending < 1
|
126
|
+
callback.call results
|
127
|
+
end
|
128
|
+
}
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
self
|
84
134
|
end
|
135
|
+
|
136
|
+
def multi_add(contents_list, &callback)
|
137
|
+
multi_operation Request::Add, contents_list, &callback
|
138
|
+
end
|
139
|
+
|
140
|
+
def multi_get(contents_list, &callback)
|
141
|
+
multi_operation Request::Get, contents_list, &callback
|
142
|
+
end
|
143
|
+
|
144
|
+
def multi_set(contents_list, &callback)
|
145
|
+
multi_operation Request::Set, contents_list, &callback
|
146
|
+
end
|
147
|
+
|
148
|
+
def multi_delete(contents_list, &callback)
|
149
|
+
multi_operation Request::Delete, contents_list, &callback
|
150
|
+
end
|
151
|
+
|
85
152
|
end
|
86
153
|
end
|
data/lib/remcached/client.rb
CHANGED
@@ -129,23 +129,6 @@ module Memcached
|
|
129
129
|
end
|
130
130
|
end
|
131
131
|
|
132
|
-
|
133
|
-
def get(contents, &callback)
|
134
|
-
send_request Request::Get.new(contents), &callback
|
135
|
-
end
|
136
|
-
|
137
|
-
def add(contents, &callback)
|
138
|
-
send_request Request::Add.new(contents), &callback
|
139
|
-
end
|
140
|
-
|
141
|
-
def set(contents, &callback)
|
142
|
-
send_request Request::Set.new(contents), &callback
|
143
|
-
end
|
144
|
-
|
145
|
-
def delete(contents, &callback)
|
146
|
-
send_request Request::Delete.new(contents), &callback
|
147
|
-
end
|
148
|
-
|
149
132
|
# Callback will be called multiple times
|
150
133
|
def stats(contents={}, &callback)
|
151
134
|
send_request Request::Stats.new(contents) do |result|
|
data/lib/remcached/const.rb
CHANGED
data/lib/remcached/packet.rb
CHANGED
@@ -2,6 +2,8 @@ require 'remcached/pack_array'
|
|
2
2
|
|
3
3
|
module Memcached
|
4
4
|
class Packet
|
5
|
+
##
|
6
|
+
# Initialize with fields
|
5
7
|
def initialize(contents={})
|
6
8
|
@contents = contents
|
7
9
|
(self.class.fields +
|
@@ -10,15 +12,20 @@ module Memcached
|
|
10
12
|
end
|
11
13
|
end
|
12
14
|
|
15
|
+
##
|
16
|
+
# Get field
|
13
17
|
def [](field)
|
14
18
|
@contents[field]
|
15
19
|
end
|
16
20
|
|
21
|
+
##
|
22
|
+
# Set field
|
17
23
|
def []=(field, value)
|
18
24
|
@contents[field] = value
|
19
25
|
end
|
20
26
|
|
21
|
-
|
27
|
+
##
|
28
|
+
# Define a field for subclasses
|
22
29
|
def self.field(name, packed, default=nil)
|
23
30
|
instance_eval do
|
24
31
|
@fields ||= []
|
@@ -26,6 +33,8 @@ module Memcached
|
|
26
33
|
end
|
27
34
|
end
|
28
35
|
|
36
|
+
##
|
37
|
+
# Fields of parent and this class
|
29
38
|
def self.fields
|
30
39
|
parent_class = ancestors[1]
|
31
40
|
parent_fields = parent_class.respond_to?(:fields) ? parent_class.fields : []
|
@@ -33,6 +42,8 @@ module Memcached
|
|
33
42
|
parent_fields + class_fields
|
34
43
|
end
|
35
44
|
|
45
|
+
##
|
46
|
+
# Define an extra for subclasses
|
36
47
|
def self.extra(name, packed, default=nil)
|
37
48
|
instance_eval do
|
38
49
|
@extras ||= []
|
@@ -40,10 +51,17 @@ module Memcached
|
|
40
51
|
end
|
41
52
|
end
|
42
53
|
|
54
|
+
##
|
55
|
+
# Extras of this class
|
43
56
|
def self.extras
|
44
|
-
|
57
|
+
parent_class = ancestors[1]
|
58
|
+
parent_extras = parent_class.respond_to?(:extras) ? parent_class.extras : []
|
59
|
+
class_extras = instance_eval { @extras || [] }
|
60
|
+
parent_extras + class_extras
|
45
61
|
end
|
46
62
|
|
63
|
+
##
|
64
|
+
# Build a packet by parsing header fields
|
47
65
|
def self.parse_header(buf)
|
48
66
|
pack_fmt = fields.collect { |name,fmt,default| fmt }.join
|
49
67
|
values = PackArray.unpack(buf, pack_fmt)
|
@@ -56,7 +74,11 @@ module Memcached
|
|
56
74
|
new contents
|
57
75
|
end
|
58
76
|
|
59
|
-
|
77
|
+
##
|
78
|
+
# Parse body of packet when the +:total_body_length+ field is
|
79
|
+
# known by header. Pass it at least +total_body_length+ bytes.
|
80
|
+
#
|
81
|
+
# return:: [String] remaining bytes
|
60
82
|
def parse_body(buf)
|
61
83
|
buf, rest = buf[0..(self[:total_body_length] - 1)], buf[self[:total_body_length]..-1]
|
62
84
|
|
@@ -75,6 +97,8 @@ module Memcached
|
|
75
97
|
rest
|
76
98
|
end
|
77
99
|
|
100
|
+
##
|
101
|
+
# Serialize for wire
|
78
102
|
def to_s
|
79
103
|
extras_s = extras_to_s
|
80
104
|
key_s = self[:key].to_s
|
@@ -154,7 +178,13 @@ module Memcached
|
|
154
178
|
|
155
179
|
class Get < Request
|
156
180
|
def initialize(contents)
|
157
|
-
super(
|
181
|
+
super({:opcode=>Commands::GET}.merge(contents))
|
182
|
+
end
|
183
|
+
|
184
|
+
class Quiet < Get
|
185
|
+
def initialize(contents)
|
186
|
+
super({:opcode=>Commands::GETQ}.merge(contents))
|
187
|
+
end
|
158
188
|
end
|
159
189
|
end
|
160
190
|
|
@@ -163,7 +193,13 @@ module Memcached
|
|
163
193
|
extra :expiration, 'N', 0
|
164
194
|
|
165
195
|
def initialize(contents)
|
166
|
-
super(
|
196
|
+
super({:opcode=>Commands::ADD}.merge(contents))
|
197
|
+
end
|
198
|
+
|
199
|
+
class Quiet < Add
|
200
|
+
def initialize(contents)
|
201
|
+
super({:opcode=>Commands::ADDQ}.merge(contents))
|
202
|
+
end
|
167
203
|
end
|
168
204
|
end
|
169
205
|
|
@@ -172,19 +208,31 @@ module Memcached
|
|
172
208
|
extra :expiration, 'N', 0
|
173
209
|
|
174
210
|
def initialize(contents)
|
175
|
-
super(
|
211
|
+
super({:opcode=>Commands::SET}.merge(contents))
|
212
|
+
end
|
213
|
+
|
214
|
+
class Quiet < Set
|
215
|
+
def initialize(contents)
|
216
|
+
super({:opcode=>Commands::SETQ}.merge(contents))
|
217
|
+
end
|
176
218
|
end
|
177
219
|
end
|
178
220
|
|
179
221
|
class Delete < Request
|
180
222
|
def initialize(contents)
|
181
|
-
super(
|
223
|
+
super({:opcode=>Commands::DELETE}.merge(contents))
|
224
|
+
end
|
225
|
+
|
226
|
+
class Quiet < Delete
|
227
|
+
def initialize(contents)
|
228
|
+
super({:opcode=>Commands::DELETEQ}.merge(contents))
|
229
|
+
end
|
182
230
|
end
|
183
231
|
end
|
184
232
|
|
185
233
|
class Stats < Request
|
186
234
|
def initialize(contents)
|
187
|
-
super(
|
235
|
+
super({:opcode=>Commands::STAT}.merge(contents))
|
188
236
|
end
|
189
237
|
end
|
190
238
|
end
|
data/remcached.gemspec
CHANGED
@@ -1,12 +1,15 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
|
1
4
|
# -*- encoding: utf-8 -*-
|
2
5
|
|
3
6
|
Gem::Specification.new do |s|
|
4
7
|
s.name = %q{remcached}
|
5
|
-
s.version = "0.
|
8
|
+
s.version = "0.3.0"
|
6
9
|
|
7
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
11
|
s.authors = ["Stephan Maka"]
|
9
|
-
s.date = %q{2009-09-
|
12
|
+
s.date = %q{2009-09-17}
|
10
13
|
s.description = %q{Ruby EventMachine memcached client}
|
11
14
|
s.email = %q{astro@spaceboyz.net}
|
12
15
|
s.files = [
|
@@ -26,12 +29,12 @@ Gem::Specification.new do |s|
|
|
26
29
|
s.homepage = %q{http://github.com/astro/remcached/}
|
27
30
|
s.rdoc_options = ["--charset=UTF-8"]
|
28
31
|
s.require_paths = ["lib"]
|
29
|
-
s.rubygems_version = %q{1.3.
|
32
|
+
s.rubygems_version = %q{1.3.4}
|
30
33
|
s.summary = %q{Ruby EventMachine memcached client}
|
31
34
|
s.test_files = [
|
32
|
-
"spec/
|
33
|
-
"spec/
|
34
|
-
"spec/
|
35
|
+
"spec/packet_spec.rb",
|
36
|
+
"spec/client_spec.rb",
|
37
|
+
"spec/memcached_spec.rb"
|
35
38
|
]
|
36
39
|
|
37
40
|
if s.respond_to? :specification_version then
|
data/spec/client_spec.rb
CHANGED
@@ -14,122 +14,6 @@ describe Memcached::Client do
|
|
14
14
|
end
|
15
15
|
|
16
16
|
|
17
|
-
it "should add a value" do
|
18
|
-
run do
|
19
|
-
@cl.add(:key => 'Hello',
|
20
|
-
:value => 'World') do |result|
|
21
|
-
result.should be_kind_of(Memcached::Response)
|
22
|
-
result[:status].should == Memcached::Errors::NO_ERROR
|
23
|
-
result[:cas].should_not == 0
|
24
|
-
stop
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
it "should get a value" do
|
30
|
-
run do
|
31
|
-
@cl.get(:key => 'Hello') do |result|
|
32
|
-
result.should be_kind_of(Memcached::Response)
|
33
|
-
result[:status].should == Memcached::Errors::NO_ERROR
|
34
|
-
result[:value].should == 'World'
|
35
|
-
result[:cas].should_not == 0
|
36
|
-
@old_cas = result[:cas]
|
37
|
-
stop
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
it "should set a value" do
|
43
|
-
run do
|
44
|
-
@cl.set(:key => 'Hello',
|
45
|
-
:value => 'Planet') do |result|
|
46
|
-
result.should be_kind_of(Memcached::Response)
|
47
|
-
result[:status].should == Memcached::Errors::NO_ERROR
|
48
|
-
result[:cas].should_not == 0
|
49
|
-
result[:cas].should_not == @old_cas
|
50
|
-
stop
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
it "should get a value" do
|
56
|
-
run do
|
57
|
-
@cl.get(:key => 'Hello') do |result|
|
58
|
-
result.should be_kind_of(Memcached::Response)
|
59
|
-
result[:status].should == Memcached::Errors::NO_ERROR
|
60
|
-
result[:value].should == 'Planet'
|
61
|
-
result[:cas].should_not == @old_cas
|
62
|
-
stop
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
it "should delete a value" do
|
68
|
-
run do
|
69
|
-
@cl.delete(:key => 'Hello') do |result|
|
70
|
-
result.should be_kind_of(Memcached::Response)
|
71
|
-
result[:status].should == Memcached::Errors::NO_ERROR
|
72
|
-
stop
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
it "should not get a value" do
|
78
|
-
run do
|
79
|
-
@cl.get(:key => 'Hello') do |result|
|
80
|
-
result.should be_kind_of(Memcached::Response)
|
81
|
-
result[:status].should == Memcached::Errors::KEY_NOT_FOUND
|
82
|
-
stop
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
$n = 100
|
88
|
-
context "when incrementing a counter #{$n} times" do
|
89
|
-
it "should initialize the counter" do
|
90
|
-
run do
|
91
|
-
@cl.set(:key => 'counter',
|
92
|
-
:value => '0') do |result|
|
93
|
-
stop
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
it "should count #{$n} times" do
|
99
|
-
$counted = 0
|
100
|
-
def count
|
101
|
-
@cl.get(:key => 'counter') do |result|
|
102
|
-
result[:status].should == Memcached::Errors::NO_ERROR
|
103
|
-
value = result[:value].to_i
|
104
|
-
@cl.set(:key => 'counter',
|
105
|
-
:value => (value + 1).to_s,
|
106
|
-
:cas => result[:cas]) do |result|
|
107
|
-
if result[:status] == Memcached::Errors::KEY_EXISTS
|
108
|
-
count # again
|
109
|
-
else
|
110
|
-
result[:status].should == Memcached::Errors::NO_ERROR
|
111
|
-
$counted += 1
|
112
|
-
stop if $counted >= $n
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
116
|
-
end
|
117
|
-
run do
|
118
|
-
$n.times { count }
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
it "should have counted up to #{$n}" do
|
123
|
-
run do
|
124
|
-
@cl.get(:key => 'counter') do |result|
|
125
|
-
result[:status].should == Memcached::Errors::NO_ERROR
|
126
|
-
result[:value].to_i.should == $n
|
127
|
-
stop
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
17
|
context "when getting stats" do
|
134
18
|
before :all do
|
135
19
|
@stats = {}
|
data/spec/memcached_spec.rb
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
$: << File.dirname(__FILE__) + '/../lib'
|
2
2
|
require 'remcached'
|
3
3
|
|
4
|
-
describe Memcached
|
4
|
+
describe Memcached do
|
5
5
|
def run(&block)
|
6
6
|
EM.run do
|
7
7
|
Memcached.servers = %w(127.0.0.2 localhost:11212 localhost localhost)
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
if
|
12
|
-
|
9
|
+
@timer = EM::PeriodicTimer.new(0.01) do
|
10
|
+
# at least localhost & localhost
|
11
|
+
if Memcached.usable_clients.length >= 2
|
12
|
+
@timer.cancel
|
13
13
|
block.call
|
14
14
|
end
|
15
15
|
end
|
@@ -21,6 +21,125 @@ describe Memcached::Client do
|
|
21
21
|
EM.stop
|
22
22
|
end
|
23
23
|
|
24
|
+
|
25
|
+
context "when doing a simple operation" do
|
26
|
+
it "should add a value" do
|
27
|
+
run do
|
28
|
+
Memcached.add(:key => 'Hello',
|
29
|
+
:value => 'World') do |result|
|
30
|
+
result.should be_kind_of(Memcached::Response)
|
31
|
+
result[:status].should == Memcached::Errors::NO_ERROR
|
32
|
+
result[:cas].should_not == 0
|
33
|
+
stop
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should get a value" do
|
39
|
+
run do
|
40
|
+
Memcached.get(:key => 'Hello') do |result|
|
41
|
+
result.should be_kind_of(Memcached::Response)
|
42
|
+
result[:status].should == Memcached::Errors::NO_ERROR
|
43
|
+
result[:value].should == 'World'
|
44
|
+
result[:cas].should_not == 0
|
45
|
+
@old_cas = result[:cas]
|
46
|
+
stop
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should set a value" do
|
52
|
+
run do
|
53
|
+
Memcached.set(:key => 'Hello',
|
54
|
+
:value => 'Planet') do |result|
|
55
|
+
result.should be_kind_of(Memcached::Response)
|
56
|
+
result[:status].should == Memcached::Errors::NO_ERROR
|
57
|
+
result[:cas].should_not == 0
|
58
|
+
result[:cas].should_not == @old_cas
|
59
|
+
stop
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should get a value" do
|
65
|
+
run do
|
66
|
+
Memcached.get(:key => 'Hello') do |result|
|
67
|
+
result.should be_kind_of(Memcached::Response)
|
68
|
+
result[:status].should == Memcached::Errors::NO_ERROR
|
69
|
+
result[:value].should == 'Planet'
|
70
|
+
result[:cas].should_not == @old_cas
|
71
|
+
stop
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should delete a value" do
|
77
|
+
run do
|
78
|
+
Memcached.delete(:key => 'Hello') do |result|
|
79
|
+
result.should be_kind_of(Memcached::Response)
|
80
|
+
result[:status].should == Memcached::Errors::NO_ERROR
|
81
|
+
stop
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should not get a value" do
|
87
|
+
run do
|
88
|
+
Memcached.get(:key => 'Hello') do |result|
|
89
|
+
result.should be_kind_of(Memcached::Response)
|
90
|
+
result[:status].should == Memcached::Errors::KEY_NOT_FOUND
|
91
|
+
stop
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
$n = 100
|
97
|
+
context "when incrementing a counter #{$n} times" do
|
98
|
+
it "should initialize the counter" do
|
99
|
+
run do
|
100
|
+
Memcached.set(:key => 'counter',
|
101
|
+
:value => '0') do |result|
|
102
|
+
stop
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should count #{$n} times" do
|
108
|
+
@counted = 0
|
109
|
+
def count
|
110
|
+
Memcached.get(:key => 'counter') do |result|
|
111
|
+
result[:status].should == Memcached::Errors::NO_ERROR
|
112
|
+
value = result[:value].to_i
|
113
|
+
Memcached.set(:key => 'counter',
|
114
|
+
:value => (value + 1).to_s,
|
115
|
+
:cas => result[:cas]) do |result|
|
116
|
+
if result[:status] == Memcached::Errors::KEY_EXISTS
|
117
|
+
count # again
|
118
|
+
else
|
119
|
+
result[:status].should == Memcached::Errors::NO_ERROR
|
120
|
+
@counted += 1
|
121
|
+
stop if @counted >= $n
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
run do
|
127
|
+
$n.times { count }
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should have counted up to #{$n}" do
|
132
|
+
run do
|
133
|
+
Memcached.get(:key => 'counter') do |result|
|
134
|
+
result[:status].should == Memcached::Errors::NO_ERROR
|
135
|
+
result[:value].to_i.should == $n
|
136
|
+
stop
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
24
143
|
context "when using multiple servers" do
|
25
144
|
it "should not return the same hash for the succeeding key" do
|
26
145
|
run do
|
@@ -56,4 +175,81 @@ describe Memcached::Client do
|
|
56
175
|
end
|
57
176
|
end
|
58
177
|
|
178
|
+
context "when manipulating multiple records at once" do
|
179
|
+
before :all do
|
180
|
+
@n = 10
|
181
|
+
end
|
182
|
+
|
183
|
+
def key(n)
|
184
|
+
"test:item:#{n}"
|
185
|
+
end
|
186
|
+
|
187
|
+
it "should add some items" do
|
188
|
+
run do
|
189
|
+
items = []
|
190
|
+
@n.times { |i|
|
191
|
+
items << { :key => key(i),
|
192
|
+
:value => 'Foo',
|
193
|
+
:expiration => 20 } if i % 2 == 0
|
194
|
+
}
|
195
|
+
Memcached.multi_add(items) { |responses|
|
196
|
+
stop
|
197
|
+
@n.times { |i|
|
198
|
+
if i % 2 == 0 && (response_i = responses[key(i)])
|
199
|
+
response_i[:status].should == Memcached::Errors::NO_ERROR
|
200
|
+
end
|
201
|
+
}
|
202
|
+
}
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
it "should get all items" do
|
207
|
+
run do
|
208
|
+
items = []
|
209
|
+
@n.times { |i|
|
210
|
+
items << { :key => key(i) }
|
211
|
+
}
|
212
|
+
Memcached.multi_get(items) { |responses|
|
213
|
+
stop
|
214
|
+
@n.times { |i|
|
215
|
+
if i % 2 == 0
|
216
|
+
responses.should have_key(key(i))
|
217
|
+
responses[key(i)][:status].should == Memcached::Errors::NO_ERROR
|
218
|
+
responses[key(i)][:value].should == 'Foo'
|
219
|
+
else
|
220
|
+
# either no response because request was quiet, or not
|
221
|
+
# found in case of last response
|
222
|
+
if (response_i = responses[key(i)])
|
223
|
+
response_i[:status].should == Memcached::Errors::KEY_NOT_FOUND
|
224
|
+
end
|
225
|
+
end
|
226
|
+
}
|
227
|
+
}
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
it "should delete all items" do
|
232
|
+
run do
|
233
|
+
items = []
|
234
|
+
@n.times { |i|
|
235
|
+
items << { :key => key(i) }
|
236
|
+
}
|
237
|
+
Memcached.multi_delete(items) { |responses|
|
238
|
+
stop
|
239
|
+
@n.times { |i|
|
240
|
+
if i % 2 == 0
|
241
|
+
# either no response because request was quiet, or ok in
|
242
|
+
# case of last response
|
243
|
+
if (response_i = responses[key(i)])
|
244
|
+
response_i[:status].should == Memcached::Errors::NO_ERROR
|
245
|
+
end
|
246
|
+
else
|
247
|
+
responses[key(i)][:status].should == Memcached::Errors::KEY_NOT_FOUND
|
248
|
+
end
|
249
|
+
}
|
250
|
+
}
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
59
255
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: astro-remcached
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stephan Maka
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-09-
|
12
|
+
date: 2009-09-17 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -62,6 +62,6 @@ signing_key:
|
|
62
62
|
specification_version: 3
|
63
63
|
summary: Ruby EventMachine memcached client
|
64
64
|
test_files:
|
65
|
+
- spec/packet_spec.rb
|
65
66
|
- spec/client_spec.rb
|
66
67
|
- spec/memcached_spec.rb
|
67
|
-
- spec/packet_spec.rb
|