couchbase-jruby-client 0.1.0-java

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.
Files changed (65) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.ruby-version +1 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +203 -0
  6. data/README.md +347 -0
  7. data/Rakefile +10 -0
  8. data/couchbase-jruby-client.gemspec +30 -0
  9. data/lib/couchbase/async/callback.rb +19 -0
  10. data/lib/couchbase/async/queue.rb +26 -0
  11. data/lib/couchbase/async.rb +139 -0
  12. data/lib/couchbase/bucket.rb +663 -0
  13. data/lib/couchbase/cluster.rb +105 -0
  14. data/lib/couchbase/constants.rb +12 -0
  15. data/lib/couchbase/error.rb +28 -0
  16. data/lib/couchbase/jruby/couchbase_client.rb +22 -0
  17. data/lib/couchbase/jruby/future.rb +8 -0
  18. data/lib/couchbase/operations/arithmetic.rb +301 -0
  19. data/lib/couchbase/operations/delete.rb +104 -0
  20. data/lib/couchbase/operations/get.rb +298 -0
  21. data/lib/couchbase/operations/stats.rb +16 -0
  22. data/lib/couchbase/operations/store.rb +468 -0
  23. data/lib/couchbase/operations/touch.rb +123 -0
  24. data/lib/couchbase/operations/utils.rb +49 -0
  25. data/lib/couchbase/operations.rb +23 -0
  26. data/lib/couchbase/result.rb +43 -0
  27. data/lib/couchbase/transcoder.rb +83 -0
  28. data/lib/couchbase/utils.rb +62 -0
  29. data/lib/couchbase/version.rb +3 -0
  30. data/lib/couchbase/view.rb +506 -0
  31. data/lib/couchbase/view_row.rb +272 -0
  32. data/lib/couchbase.rb +177 -0
  33. data/lib/jars/commons-codec-1.5.jar +0 -0
  34. data/lib/jars/couchbase-client-1.2.0-javadoc.jar +0 -0
  35. data/lib/jars/couchbase-client-1.2.0-sources.jar +0 -0
  36. data/lib/jars/couchbase-client-1.2.0.jar +0 -0
  37. data/lib/jars/httpcore-4.1.1.jar +0 -0
  38. data/lib/jars/httpcore-nio-4.1.1.jar +0 -0
  39. data/lib/jars/jettison-1.1.jar +0 -0
  40. data/lib/jars/netty-3.5.5.Final.jar +0 -0
  41. data/lib/jars/spymemcached-2.10.0-javadoc.jar +0 -0
  42. data/lib/jars/spymemcached-2.10.0-sources.jar +0 -0
  43. data/lib/jars/spymemcached-2.10.0.jar +0 -0
  44. data/test/profile/.gitignore +1 -0
  45. data/test/profile/Gemfile +6 -0
  46. data/test/profile/benchmark.rb +195 -0
  47. data/test/setup.rb +201 -0
  48. data/test/test_arithmetic.rb +177 -0
  49. data/test/test_async.rb +324 -0
  50. data/test/test_bucket.rb +213 -0
  51. data/test/test_cas.rb +78 -0
  52. data/test/test_couchbase.rb +29 -0
  53. data/test/test_couchbase_rails_cache_store.rb +341 -0
  54. data/test/test_delete.rb +125 -0
  55. data/test/test_errors.rb +82 -0
  56. data/test/test_format.rb +161 -0
  57. data/test/test_get.rb +417 -0
  58. data/test/test_stats.rb +57 -0
  59. data/test/test_store.rb +216 -0
  60. data/test/test_timer.rb +42 -0
  61. data/test/test_touch.rb +97 -0
  62. data/test/test_unlock.rb +119 -0
  63. data/test/test_utils.rb +58 -0
  64. data/test/test_version.rb +52 -0
  65. metadata +226 -0
@@ -0,0 +1,105 @@
1
+ # Author:: Couchbase <info@couchbase.com>
2
+ # Copyright:: 2011, 2012 Couchbase, Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ module Couchbase
19
+
20
+ class Cluster
21
+
22
+ # Establish connection to the cluster for administration
23
+ #
24
+ # @param [Hash] options The connection parameter
25
+ # @option options [String] :username The username
26
+ # @option options [String] :password The password
27
+ # @option options [String] :pool ("default") The pool name
28
+ # @option options [String] :hostname ("localhost") The hostname
29
+ # @option options [String] :port (8091) The port
30
+ def initialize(options = {})
31
+ if options[:username].nil? || options[:password].nil?
32
+ raise ArgumentError, "username and password mandatory to connect to the cluster"
33
+ end
34
+ @connection = Bucket.new(options.merge(:type => :cluster))
35
+ end
36
+
37
+ # Create data bucket
38
+ #
39
+ # @param [String] name The name of the bucket
40
+ # @param [Hash] options The bucket parameters
41
+ # @option options [String] :bucket_type ("couchbase") The type of the
42
+ # bucket. Possible values are "memcached" and "couchbase".
43
+ # @option options [Fixnum] :ram_quota (100) The RAM quota in megabytes.
44
+ # @option options [Fixnum] :replica_number (1) The number of replicas of
45
+ # each document
46
+ # @option options [String] :auth_type ("sasl") The authentication type.
47
+ # Possible values are "sasl" and "none". Note you should specify free
48
+ # port for "none"
49
+ # @option options [Fixnum] :proxy_port The port for moxi
50
+ def create_bucket(name, options = {})
51
+ defaults = {
52
+ :type => "couchbase",
53
+ :ram_quota => 100,
54
+ :replica_number => 1,
55
+ :auth_type => "sasl",
56
+ :sasl_password => "",
57
+ :proxy_port => nil
58
+ }
59
+ options = defaults.merge(options)
60
+ params = {"name" => name}
61
+ params["bucketType"] = options[:type]
62
+ params["ramQuotaMB"] = options[:ram_quota]
63
+ params["replicaNumber"] = options[:replica_number]
64
+ params["authType"] = options[:auth_type]
65
+ params["saslPassword"] = options[:sasl_password]
66
+ params["proxyPort"] = options[:proxy_port]
67
+ payload = Utils.encode_params(params.reject!{|k, v| v.nil?})
68
+ request = @connection.make_http_request("/pools/default/buckets",
69
+ :content_type => "application/x-www-form-urlencoded",
70
+ :type => :management,
71
+ :method => :post,
72
+ :extended => true,
73
+ :body => payload)
74
+ response = nil
75
+ request.on_body do |r|
76
+ response = r
77
+ response.instance_variable_set("@operation", :create_bucket)
78
+ yield(response) if block_given?
79
+ end
80
+ request.continue
81
+ response
82
+ end
83
+
84
+ # Delete the data bucket
85
+ #
86
+ # @param [String] name The name of the bucket
87
+ # @param [Hash] options
88
+ def delete_bucket(name, options = {})
89
+ request = @connection.make_http_request("/pools/default/buckets/#{name}",
90
+ :type => :management,
91
+ :method => :delete,
92
+ :extended => true)
93
+ response = nil
94
+ request.on_body do |r|
95
+ response = r
96
+ response.instance_variable_set("@operation", :delete_bucket)
97
+ yield(response) if block_given?
98
+ end
99
+ request.continue
100
+ response
101
+ end
102
+
103
+ end
104
+
105
+ end
@@ -0,0 +1,12 @@
1
+ module Couchbase
2
+ module Constants # :nodoc:
3
+ S_ID = 'id'.freeze
4
+ S_DOC = 'doc'.freeze
5
+ S_VALUE = 'value'.freeze
6
+ S_META = 'meta'.freeze
7
+ S_FLAGS = 'flags'.freeze
8
+ S_CAS = 'cas'.freeze
9
+ S_KEY = 'key'.freeze
10
+ S_IS_LAST = Object.new.freeze
11
+ end
12
+ end
@@ -0,0 +1,28 @@
1
+
2
+ module Couchbase
3
+ module Error
4
+ class Base < Exception
5
+ end
6
+
7
+ class Connect < Base
8
+ end
9
+
10
+ class Auth < Base
11
+ end
12
+
13
+ class Connect < Base
14
+ end
15
+
16
+ class NotFound < Base
17
+ end
18
+
19
+ class Invalid < Base
20
+ end
21
+
22
+ class KeyExists < Base
23
+ end
24
+
25
+ class ValueFormat < Base
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,22 @@
1
+ module Couchbase
2
+ module Jruby
3
+ class CouchbaseClient < Java::ComCouchbaseClient::CouchbaseClient
4
+
5
+ # Futures
6
+ %w(add set append asyncCAS asyncDecr asyncGet asyncGetAndTouch asyncGetBulk
7
+ asyncGets asyncIncr delete flush prepend replace set touch).each do |op|
8
+ define_method(op) do |*|
9
+ super
10
+ end
11
+ end
12
+
13
+ def get(*)
14
+ super
15
+ end
16
+
17
+ VALUE_OPS = %w(
18
+
19
+ ).freeze
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,8 @@
1
+ module Couchbase
2
+ module Jruby
3
+ module Future
4
+
5
+
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,301 @@
1
+ module Couchbase::Operations
2
+ module Arithmetic
3
+
4
+ # Increment the value of an existing numeric key
5
+ #
6
+ # @since 1.0.0
7
+ #
8
+ # The increment methods allow you to increase a given stored integer
9
+ # value. These are the incremental equivalent of the decrement operations
10
+ # and work on the same basis; updating the value of a key if it can be
11
+ # parsed to an integer. The update operation occurs on the server and is
12
+ # provided at the protocol level. This simplifies what would otherwise be a
13
+ # two-stage get and set operation.
14
+ #
15
+ # @note that server values stored and transmitted as unsigned numbers,
16
+ # therefore if you try to store negative number and then increment or
17
+ # decrement it will cause overflow. (see "Integer overflow" example
18
+ # below)
19
+ #
20
+ # @overload incr(key, delta = 1, options = {})
21
+ # @param key [String, Symbol] Key used to reference the value.
22
+ # @param delta [Fixnum] Integer (up to 64 bits) value to increment
23
+ # @param options [Hash] Options for operation.
24
+ # @option options [true, false] :create (false) If set to +true+, it will
25
+ # initialize the key with zero value and zero flags (use +:initial+
26
+ # option to set another initial value). Note: it won't increment the
27
+ # missing value.
28
+ # @option options [Fixnum] :initial (0) Integer (up to 64 bits) value for
29
+ # missing key initialization. This option imply +:create+ option is
30
+ # +true+.
31
+ # @option options [Fixnum] :ttl (self.default_ttl) Expiry time for key.
32
+ # Values larger than 30*24*60*60 seconds (30 days) are interpreted as
33
+ # absolute times (from the epoch). This option ignored for existent
34
+ # keys.
35
+ # @option options [true, false] :extended (false) If set to +true+, the
36
+ # operation will return tuple +[value, cas]+, otherwise (by default) it
37
+ # returns just value.
38
+ #
39
+ # @yieldparam ret [Result] the result of operation in asynchronous mode
40
+ # (valid attributes: +error+, +operation+, +key+, +value+, +cas+).
41
+ #
42
+ # @return [Fixnum] the actual value of the key.
43
+ #
44
+ # @raise [Couchbase::Error::NotFound] if key is missing and +:create+
45
+ # option isn't +true+.
46
+ #
47
+ # @raise [Couchbase::Error::DeltaBadval] if the key contains non-numeric
48
+ # value
49
+ #
50
+ # @raise [Couchbase::Error::Connect] if connection closed (see {Bucket#reconnect})
51
+ #
52
+ # @raise [ArgumentError] when passing the block in synchronous mode
53
+ #
54
+ # @example Increment key by one
55
+ # c.incr("foo")
56
+ #
57
+ # @example Increment key by 50
58
+ # c.incr("foo", 50)
59
+ #
60
+ # @example Increment key by one <b>OR</b> initialize with zero
61
+ # c.incr("foo", :create => true) #=> will return old+1 or 0
62
+ #
63
+ # @example Increment key by one <b>OR</b> initialize with three
64
+ # c.incr("foo", 50, :initial => 3) #=> will return old+50 or 3
65
+ #
66
+ # @example Increment key and get its CAS value
67
+ # val, cas = c.incr("foo", :extended => true)
68
+ #
69
+ # @example Integer overflow
70
+ # c.set("foo", -100)
71
+ # c.get("foo") #=> -100
72
+ # c.incr("foo") #=> 18446744073709551517
73
+ #
74
+ # @example Asynchronous invocation
75
+ # c.run do
76
+ # c.incr("foo") do |ret|
77
+ # ret.operation #=> :increment
78
+ # ret.success? #=> true
79
+ # ret.key #=> "foo"
80
+ # ret.value
81
+ # ret.cas
82
+ # end
83
+ # end
84
+ #
85
+ def incr(*args)
86
+ sync_block_error if !async? && block_given?
87
+ do_arithmetic(:incr, *args)
88
+ end
89
+ alias_method :increment, :incr
90
+
91
+ # Decrement the value of an existing numeric key
92
+ #
93
+ # @since 1.0.0
94
+ #
95
+ # The decrement methods reduce the value of a given key if the
96
+ # corresponding value can be parsed to an integer value. These operations
97
+ # are provided at a protocol level to eliminate the need to get, update,
98
+ # and reset a simple integer value in the database. It supports the use of
99
+ # an explicit offset value that will be used to reduce the stored value in
100
+ # the database.
101
+ #
102
+ # @note that server values stored and transmitted as unsigned numbers,
103
+ # therefore if you try to decrement negative or zero key, you will always
104
+ # get zero.
105
+ #
106
+ # @overload decr(key, delta = 1, options = {})
107
+ # @param key [String, Symbol] Key used to reference the value.
108
+ # @param delta [Fixnum] Integer (up to 64 bits) value to decrement
109
+ # @param options [Hash] Options for operation.
110
+ # @option options [true, false] :create (false) If set to +true+, it will
111
+ # initialize the key with zero value and zero flags (use +:initial+
112
+ # option to set another initial value). Note: it won't decrement the
113
+ # missing value.
114
+ # @option options [Fixnum] :initial (0) Integer (up to 64 bits) value for
115
+ # missing key initialization. This option imply +:create+ option is
116
+ # +true+.
117
+ # @option options [Fixnum] :ttl (self.default_ttl) Expiry time for key.
118
+ # Values larger than 30*24*60*60 seconds (30 days) are interpreted as
119
+ # absolute times (from the epoch). This option ignored for existent
120
+ # keys.
121
+ # @option options [true, false] :extended (false) If set to +true+, the
122
+ # operation will return tuple +[value, cas]+, otherwise (by default) it
123
+ # returns just value.
124
+ #
125
+ # @yieldparam ret [Result] the result of operation in asynchronous mode
126
+ # (valid attributes: +error+, +operation+, +key+, +value+, +cas+).
127
+ #
128
+ # @return [Fixnum] the actual value of the key.
129
+ #
130
+ # @raise [Couchbase::Error::NotFound] if key is missing and +:create+
131
+ # option isn't +true+.
132
+ #
133
+ # @raise [Couchbase::Error::DeltaBadval] if the key contains non-numeric
134
+ # value
135
+ #
136
+ # @raise [Couchbase::Error::Connect] if connection closed (see {Bucket#reconnect})
137
+ #
138
+ # @raise [ArgumentError] when passing the block in synchronous mode
139
+ #
140
+ # @example Decrement key by one
141
+ # c.decr("foo")
142
+ #
143
+ # @example Decrement key by 50
144
+ # c.decr("foo", 50)
145
+ #
146
+ # @example Decrement key by one <b>OR</b> initialize with zero
147
+ # c.decr("foo", :create => true) #=> will return old-1 or 0
148
+ #
149
+ # @example Decrement key by one <b>OR</b> initialize with three
150
+ # c.decr("foo", 50, :initial => 3) #=> will return old-50 or 3
151
+ #
152
+ # @example Decrement key and get its CAS value
153
+ # val, cas = c.decr("foo", :extended => true)
154
+ #
155
+ # @example Decrementing zero
156
+ # c.set("foo", 0)
157
+ # c.decrement("foo", 100500) #=> 0
158
+ #
159
+ # @example Decrementing negative value
160
+ # c.set("foo", -100)
161
+ # c.decrement("foo", 100500) #=> 0
162
+ #
163
+ # @example Asynchronous invocation
164
+ # c.run do
165
+ # c.decr("foo") do |ret|
166
+ # ret.operation #=> :decrement
167
+ # ret.success? #=> true
168
+ # ret.key #=> "foo"
169
+ # ret.value
170
+ # ret.cas
171
+ # end
172
+ # end
173
+ #
174
+ def decr(*args)
175
+ sync_block_error if !async? && block_given?
176
+ do_arithmetic(:decr, *args)
177
+ end
178
+ alias_method :decrement, :decr
179
+
180
+ private
181
+
182
+ def do_arithmetic(op, *args)
183
+ key, delta, options = expand_arithmetic_args(args)
184
+
185
+ case key
186
+ when String, Symbol
187
+ single_arithmetic(op, key, delta, options)
188
+ when Array, Hash
189
+ multi_arithmetic(op, key, delta)
190
+ else
191
+ raise # something
192
+ end
193
+ end
194
+
195
+ def expand_arithmetic_args(args)
196
+ options = if args.size > 1 && args.last.respond_to?(:to_h)
197
+ args.pop
198
+ else
199
+ {}
200
+ end
201
+
202
+ delta = if args.size > 1 && args.last.respond_to?(:to_int)
203
+ args.pop
204
+ else
205
+ options[:delta] || 1
206
+ end
207
+
208
+ key = args.size == 1 ? args.first : args
209
+
210
+ [key, delta, options]
211
+ end
212
+
213
+ def single_arithmetic(op, key, delta, options = {})
214
+ if async?
215
+ java_async_arithmetic(op, key, delta)
216
+ else
217
+ result = java_arithmetic(op, key, delta)
218
+ set_default_arithmetic_or_raise(key, result, options)
219
+ end
220
+ end
221
+
222
+ def set_default_arithmetic_or_raise(key, result, options)
223
+ if result < 0
224
+ if options[:initial] || options[:create] || set_default_arithmetic_init?
225
+ value = if options[:initial]
226
+ options[:initial]
227
+ elsif options[:create]
228
+ 0
229
+ else
230
+ default_arithmetic_init_int
231
+ end
232
+
233
+ set(key, value, options) && value
234
+ else
235
+ not_found_error(true)
236
+ end
237
+ else
238
+ result
239
+ end
240
+ end
241
+
242
+ def set_default_arithmetic_init?
243
+ default_arithmetic_init == true ||
244
+ default_arithmetic_init.respond_to?(:to_int) &&
245
+ default_arithmetic_init > 0
246
+ end
247
+
248
+ def default_arithmetic_init_int
249
+ default_arithmetic_init == true ? 0 : default_arithmetic_init
250
+ end
251
+
252
+ def multi_arithmetic(op, keys, delta)
253
+ {}.tap do |results|
254
+ if keys.respond_to?(:each_pair)
255
+ keys.each_pair do |k, v|
256
+ results[k] = single_arithmetic(op, k, v)
257
+ end
258
+ else
259
+ keys.each do |k|
260
+ results[k] = single_arithmetic(op, k, delta)
261
+ end
262
+ end
263
+ end
264
+ end
265
+
266
+ def java_arithmetic(op, key, delta)
267
+ case op
268
+ when :incr
269
+ java_incr(key, delta)
270
+ when :decr
271
+ java_decr(key, delta)
272
+ end
273
+ end
274
+
275
+ def java_async_arithmetic(op, key, delta)
276
+ case op
277
+ when :incr
278
+ java_async_incr(key, delta)
279
+ when :decr
280
+ java_async_decr(key, delta)
281
+ end
282
+ end
283
+
284
+ def java_incr(key, delta)
285
+ client.incr(key, delta)
286
+ end
287
+
288
+ def java_async_incr(key, delta)
289
+ client.asyncIncr(key, delta)
290
+ end
291
+
292
+ def java_decr(key, delta)
293
+ client.decr(key, delta)
294
+ end
295
+
296
+ def java_async_decr(key, delta)
297
+ client.asyncDecr(key, delta)
298
+ end
299
+
300
+ end
301
+ end
@@ -0,0 +1,104 @@
1
+ module Couchbase::Operations
2
+ module Delete
3
+
4
+ # Delete the specified key
5
+ #
6
+ # @since 1.0.0
7
+ #
8
+ # @overload delete(key, options = {})
9
+ # @param key [String, Symbol] Key used to reference the value.
10
+ # @param options [Hash] Options for operation.
11
+ # @option options [true, false] :quiet (self.quiet) If set to +true+, the
12
+ # operation won't raise error for missing key, it will return +nil+.
13
+ # Otherwise it will raise error in synchronous mode. In asynchronous
14
+ # mode this option ignored.
15
+ # @option options [Fixnum] :cas The CAS value for an object. This value
16
+ # created on the server and is guaranteed to be unique for each value of
17
+ # a given key. This value is used to provide simple optimistic
18
+ # concurrency control when multiple clients or threads try to
19
+ # update/delete an item simultaneously.
20
+ #
21
+ # @raise [Couchbase::Error::Connect] if connection closed (see {Bucket#reconnect})
22
+ # @raise [ArgumentError] when passing the block in synchronous mode
23
+ # @raise [Couchbase::Error::KeyExists] on CAS mismatch
24
+ # @raise [Couchbase::Error::NotFound] if key is missing in verbose mode
25
+ #
26
+ # @return [true, false, Hash<String, Boolean>] the result of the
27
+ # operation
28
+ #
29
+ # @example Delete the key in quiet mode (default)
30
+ # c.set("foo", "bar")
31
+ # c.delete("foo") #=> true
32
+ # c.delete("foo") #=> false
33
+ #
34
+ # @example Delete the key verbosely
35
+ # c.set("foo", "bar")
36
+ # c.delete("foo", :quiet => false) #=> true
37
+ # c.delete("foo", :quiet => true) #=> nil (default behaviour)
38
+ # c.delete("foo", :quiet => false) #=> will raise Couchbase::Error::NotFound
39
+ #
40
+ # @example Delete the key with version check
41
+ # ver = c.set("foo", "bar") #=> 5992859822302167040
42
+ # c.delete("foo", :cas => 123456) #=> will raise Couchbase::Error::KeyExists
43
+ # c.delete("foo", :cas => ver) #=> true
44
+ #
45
+ def delete(*args, &block)
46
+ sync_block_error if !async? && block_given?
47
+ key, options = expand_get_args(args)
48
+ key, cas = delete_args_parser(key)
49
+
50
+ if key.respond_to?(:to_ary)
51
+ delete_multi(key, options)
52
+ else
53
+ delete_single(key, cas, options, &block)
54
+ end
55
+ end
56
+
57
+ private
58
+
59
+ def delete_args_parser(args)
60
+ if args.respond_to?(:to_str)
61
+ [args, nil]
62
+ else
63
+ cas = if args.size > 1 &&
64
+ args.last.respond_to?(:to_int)
65
+ args.pop
66
+ else
67
+ nil
68
+ end
69
+
70
+ key = args.size == 1 ? args.first : args
71
+
72
+ [key, cas]
73
+ end
74
+ end
75
+
76
+ def delete_single(key, cas, options, &block)
77
+ if async?
78
+ java_async_delete(key, &block)
79
+ else
80
+ cas = java_delete(key)
81
+ not_found_error(!cas, options)
82
+ cas
83
+ end
84
+ end
85
+
86
+ def delete_multi(keys, options = {})
87
+ {}.tap do |results|
88
+ keys.each do |key|
89
+ results[key] = delete_single(key, nil, options)
90
+ end
91
+ end
92
+ end
93
+
94
+ def java_delete(key)
95
+ future = client.delete(key)
96
+ future_cas(future)
97
+ end
98
+
99
+ def java_async_delete(key, &block)
100
+ future = client.delete(key)
101
+ register_future(future, { op: :delete }, &block)
102
+ end
103
+ end
104
+ end