couchbase-jruby-client 0.1.0-java

Sign up to get free protection for your applications and to get access to all the features.
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,468 @@
1
+ module Couchbase::Operations
2
+ module Store
3
+
4
+ # Unconditionally store the object in the Couchbase
5
+ #
6
+ # @since 1.0.0
7
+ #
8
+ # @overload set(key, value, options = {})
9
+ #
10
+ # @param key [String, Symbol] Key used to reference the value.
11
+ # @param value [Object] Value to be stored
12
+ # @param options [Hash] Options for operation.
13
+ # @option options [Fixnum] :ttl (self.default_ttl) Expiry time for key.
14
+ # Values larger than 30*24*60*60 seconds (30 days) are interpreted as
15
+ # absolute times (from the epoch).
16
+ # @option options [Fixnum] :flags (self.default_flags) Flags for storage
17
+ # options. Flags are ignored by the server but preserved for use by the
18
+ # client. For more info see {Bucket#default_flags}.
19
+ # @option options [Symbol] :format (self.default_format) The
20
+ # representation for storing the value in the bucket. For more info see
21
+ # {Bucket#default_format}.
22
+ # @option options [Fixnum] :cas The CAS value for an object. This value is
23
+ # created on the server and is guaranteed to be unique for each value of
24
+ # a given key. This value is used to provide simple optimistic
25
+ # concurrency control when multiple clients or threads try to update an
26
+ # item simultaneously.
27
+ # @option options [Hash] :observe Apply persistence condition before
28
+ # returning result. When this option specified the library will observe
29
+ # given condition. See {Bucket#observe_and_wait}.
30
+ #
31
+ # @yieldparam ret [Result] the result of operation in asynchronous mode
32
+ # (valid attributes: +error+, +operation+, +key+).
33
+ #
34
+ # @return [Fixnum] The CAS value of the object.
35
+ #
36
+ # @raise [Couchbase::Error::Connect] if connection closed (see {Bucket#reconnect}).
37
+ # @raise [Couchbase::Error::KeyExists] if the key already exists on the
38
+ # server.
39
+ # @raise [Couchbase::Error::ValueFormat] if the value cannot be serialized
40
+ # with chosen encoder, e.g. if you try to store the Hash in +:plain+
41
+ # mode.
42
+ # @raise [ArgumentError] when passing the block in synchronous mode
43
+ # @raise [Couchbase::Error::Timeout] if timeout interval for observe
44
+ # exceeds
45
+ #
46
+ # @example Store the key which will be expired in 2 seconds using relative TTL.
47
+ # c.set("foo", "bar", :ttl => 2)
48
+ #
49
+ # @example Perform multi-set operation. It takes a Hash store its keys/values into the bucket
50
+ # c.set("foo1" => "bar1", "foo2" => "bar2")
51
+ # #=> {"foo1" => cas1, "foo2" => cas2}
52
+ #
53
+ # @example More advanced multi-set using asynchronous mode
54
+ # c.run do
55
+ # # fire and forget
56
+ # c.set("foo1", "bar1", :ttl => 10)
57
+ # # receive result into the callback
58
+ # c.set("foo2", "bar2", :ttl => 10) do |ret|
59
+ # if ret.success?
60
+ # puts ret.cas
61
+ # end
62
+ # end
63
+ # end
64
+ #
65
+ # @example Store the key which will be expired in 2 seconds using absolute TTL.
66
+ # c.set("foo", "bar", :ttl => Time.now.to_i + 2)
67
+ #
68
+ # @example Force JSON document format for value
69
+ # c.set("foo", {"bar" => "baz}, :format => :document)
70
+ #
71
+ # @example Use hash-like syntax to store the value
72
+ # c["foo"] = {"bar" => "baz}
73
+ #
74
+ # @example Use extended hash-like syntax
75
+ # c["foo", {:flags => 0x1000, :format => :plain}] = "bar"
76
+ # c["foo", :flags => 0x1000] = "bar" # for ruby 1.9.x only
77
+ #
78
+ # @example Set application specific flags (note that it will be OR-ed with format flags)
79
+ # c.set("foo", "bar", :flags => 0x1000)
80
+ #
81
+ # @example Perform optimistic locking by specifying last known CAS version
82
+ # c.set("foo", "bar", :cas => 8835713818674332672)
83
+ #
84
+ # @example Perform asynchronous call
85
+ # c.run do
86
+ # c.set("foo", "bar") do |ret|
87
+ # ret.operation #=> :set
88
+ # ret.success? #=> true
89
+ # ret.key #=> "foo"
90
+ # ret.cas
91
+ # end
92
+ # end
93
+ #
94
+ # @example Ensure that the key will be persisted at least on the one node
95
+ # c.set("foo", "bar", :observe => {:persisted => 1})
96
+ #
97
+ def set(key, value = nil, options = {}, &block)
98
+ sync_block_error if !async? && block_given?
99
+ op, key, value, ttl = store_args_parser(key, value, options)
100
+
101
+ if op == :single
102
+ set_single(key, value, ttl, options, &block)
103
+ else
104
+ set_multi(key)
105
+ end
106
+ end
107
+
108
+ def []=(key, *args)
109
+ options = args.size > 1 ? args.shift : {}
110
+ value = args.pop
111
+
112
+ set(key, value, options)
113
+ end
114
+
115
+ # Add the item to the database, but fail if the object exists already
116
+ #
117
+ # @since 1.0.0
118
+ #
119
+ # @overload add(key, value, options = {})
120
+ #
121
+ # @param key [String, Symbol] Key used to reference the value.
122
+ # @param value [Object] Value to be stored
123
+ # @param options [Hash] Options for operation.
124
+ # @option options [Fixnum] :ttl (self.default_ttl) Expiry time for key.
125
+ # Values larger than 30*24*60*60 seconds (30 days) are interpreted as
126
+ # absolute times (from the epoch).
127
+ # @option options [Fixnum] :flags (self.default_flags) Flags for storage
128
+ # options. Flags are ignored by the server but preserved for use by the
129
+ # client. For more info see {Bucket#default_flags}.
130
+ # @option options [Symbol] :format (self.default_format) The
131
+ # representation for storing the value in the bucket. For more info see
132
+ # {Bucket#default_format}.
133
+ # @option options [Fixnum] :cas The CAS value for an object. This value
134
+ # created on the server and is guaranteed to be unique for each value of
135
+ # a given key. This value is used to provide simple optimistic
136
+ # concurrency control when multiple clients or threads try to update an
137
+ # item simultaneously.
138
+ # @option options [Hash] :observe Apply persistence condition before
139
+ # returning result. When this option specified the library will observe
140
+ # given condition. See {Bucket#observe_and_wait}.
141
+ #
142
+ # @yieldparam ret [Result] the result of operation in asynchronous mode
143
+ # (valid attributes: +error+, +operation+, +key+).
144
+ #
145
+ # @return [Fixnum] The CAS value of the object.
146
+ #
147
+ # @raise [Couchbase::Error::Connect] if connection closed (see {Bucket#reconnect})
148
+ # @raise [Couchbase::Error::KeyExists] if the key already exists on the
149
+ # server
150
+ # @raise [Couchbase::Error::ValueFormat] if the value cannot be serialized
151
+ # with chosen encoder, e.g. if you try to store the Hash in +:plain+
152
+ # mode.
153
+ # @raise [ArgumentError] when passing the block in synchronous mode
154
+ # @raise [Couchbase::Error::Timeout] if timeout interval for observe
155
+ # exceeds
156
+ #
157
+ # @example Add the same key twice
158
+ # c.add("foo", "bar") #=> stored successully
159
+ # c.add("foo", "baz") #=> will raise Couchbase::Error::KeyExists: failed to store value (key="foo", error=0x0c)
160
+ #
161
+ # @example Ensure that the key will be persisted at least on the one node
162
+ # c.add("foo", "bar", :observe => {:persisted => 1})
163
+ #
164
+ def add(key, value = nil, options = {}, &block)
165
+ sync_block_error if !async? && block_given?
166
+ op, key, value, ttl = store_args_parser(key, value, options)
167
+
168
+ if op == :single
169
+ add_single(key, value, ttl, options, &block)
170
+ else
171
+ add_multi(key)
172
+ end
173
+ end
174
+
175
+ # Replace the existing object in the database
176
+ #
177
+ # @since 1.0.0
178
+ #
179
+ # @overload replace(key, value, options = {})
180
+ # @param key [String, Symbol] Key used to reference the value.
181
+ # @param value [Object] Value to be stored
182
+ # @param options [Hash] Options for operation.
183
+ # @option options [Fixnum] :ttl (self.default_ttl) Expiry time for key.
184
+ # Values larger than 30*24*60*60 seconds (30 days) are interpreted as
185
+ # absolute times (from the epoch).
186
+ # @option options [Fixnum] :flags (self.default_flags) Flags for storage
187
+ # options. Flags are ignored by the server but preserved for use by the
188
+ # client. For more info see {Bucket#default_flags}.
189
+ # @option options [Symbol] :format (self.default_format) The
190
+ # representation for storing the value in the bucket. For more info see
191
+ # {Bucket#default_format}.
192
+ # @option options [Fixnum] :cas The CAS value for an object. This value
193
+ # created on the server and is guaranteed to be unique for each value of
194
+ # a given key. This value is used to provide simple optimistic
195
+ # concurrency control when multiple clients or threads try to update an
196
+ # item simultaneously.
197
+ # @option options [Hash] :observe Apply persistence condition before
198
+ # returning result. When this option specified the library will observe
199
+ # given condition. See {Bucket#observe_and_wait}.
200
+ #
201
+ # @return [Fixnum] The CAS value of the object.
202
+ #
203
+ # @raise [Couchbase::Error::Connect] if connection closed (see {Bucket#reconnect})
204
+ # @raise [Couchbase::Error::NotFound] if the key doesn't exists
205
+ # @raise [Couchbase::Error::KeyExists] on CAS mismatch
206
+ # @raise [ArgumentError] when passing the block in synchronous mode
207
+ # @raise [Couchbase::Error::Timeout] if timeout interval for observe
208
+ # exceeds
209
+ #
210
+ # @example Replacing missing key
211
+ # c.replace("foo", "baz") #=> will raise Couchbase::Error::NotFound: failed to store value (key="foo", error=0x0d)
212
+ #
213
+ # @example Ensure that the key will be persisted at least on the one node
214
+ # c.replace("foo", "bar", :observe => {:persisted => 1})
215
+ #
216
+ def replace(key, value, options = {})
217
+ sync_block_error if !async? && block_given?
218
+ if cas = java_replace(key, value, options[:ttl])
219
+ cas
220
+ else
221
+ raise Couchbase::Error::NotFound.new
222
+ end
223
+ end
224
+
225
+ # Append this object to the existing object
226
+ #
227
+ # @since 1.0.0
228
+ #
229
+ # @note This operation is kind of data-aware from server point of view.
230
+ # This mean that the server treats value as binary stream and just
231
+ # perform concatenation, therefore it won't work with +:marshal+ and
232
+ # +:document+ formats, because of lack of knowledge how to merge values
233
+ # in these formats. See {Bucket#cas} for workaround.
234
+ #
235
+ # @overload append(key, value, options = {})
236
+ # @param key [String, Symbol] Key used to reference the value.
237
+ # @param value [Object] Value to be stored
238
+ # @param options [Hash] Options for operation.
239
+ # @option options [Fixnum] :cas The CAS value for an object. This value
240
+ # created on the server and is guaranteed to be unique for each value of
241
+ # a given key. This value is used to provide simple optimistic
242
+ # concurrency control when multiple clients or threads try to update an
243
+ # item simultaneously.
244
+ # @option options [Symbol] :format (self.default_format) The
245
+ # representation for storing the value in the bucket. For more info see
246
+ # {Bucket#default_format}.
247
+ # @option options [Hash] :observe Apply persistence condition before
248
+ # returning result. When this option specified the library will observe
249
+ # given condition. See {Bucket#observe_and_wait}.
250
+ #
251
+ # @return [Fixnum] The CAS value of the object.
252
+ #
253
+ # @raise [Couchbase::Error::Connect] if connection closed (see {Bucket#reconnect})
254
+ # @raise [Couchbase::Error::KeyExists] on CAS mismatch
255
+ # @raise [Couchbase::Error::NotStored] if the key doesn't exist
256
+ # @raise [ArgumentError] when passing the block in synchronous mode
257
+ # @raise [Couchbase::Error::Timeout] if timeout interval for observe
258
+ # exceeds
259
+ #
260
+ # @example Simple append
261
+ # c.set("foo", "aaa")
262
+ # c.append("foo", "bbb")
263
+ # c.get("foo") #=> "aaabbb"
264
+ #
265
+ # @example Implementing sets using append
266
+ # def set_add(key, *values)
267
+ # encoded = values.flatten.map{|v| "+#{v} "}.join
268
+ # append(key, encoded)
269
+ # end
270
+ #
271
+ # def set_remove(key, *values)
272
+ # encoded = values.flatten.map{|v| "-#{v} "}.join
273
+ # append(key, encoded)
274
+ # end
275
+ #
276
+ # def set_get(key)
277
+ # encoded = get(key)
278
+ # ret = Set.new
279
+ # encoded.split(' ').each do |v|
280
+ # op, val = v[0], v[1..-1]
281
+ # case op
282
+ # when "-"
283
+ # ret.delete(val)
284
+ # when "+"
285
+ # ret.add(val)
286
+ # end
287
+ # end
288
+ # ret
289
+ # end
290
+ #
291
+ # @example Using optimistic locking. The operation will fail on CAS mismatch
292
+ # ver = c.set("foo", "aaa")
293
+ # c.append("foo", "bbb", :cas => ver)
294
+ #
295
+ # @example Ensure that the key will be persisted at least on the one node
296
+ # c.append("foo", "bar", :observe => {:persisted => 1})
297
+ #
298
+ def append(key, value)
299
+ sync_block_error if !async? && block_given?
300
+ if cas = java_append(validate_key(key), value)
301
+ cas
302
+ else
303
+ raise Couchbase::Error::NotFound.new
304
+ end
305
+ end
306
+
307
+ # Prepend this object to the existing object
308
+ #
309
+ # @since 1.0.0
310
+ #
311
+ # @note This operation is kind of data-aware from server point of view.
312
+ # This mean that the server treats value as binary stream and just
313
+ # perform concatenation, therefore it won't work with +:marshal+ and
314
+ # +:document+ formats, because of lack of knowledge how to merge values
315
+ # in these formats. See {Bucket#cas} for workaround.
316
+ #
317
+ # @overload prepend(key, value, options = {})
318
+ # @param key [String, Symbol] Key used to reference the value.
319
+ # @param value [Object] Value to be stored
320
+ # @param options [Hash] Options for operation.
321
+ # @option options [Fixnum] :cas The CAS value for an object. This value
322
+ # created on the server and is guaranteed to be unique for each value of
323
+ # a given key. This value is used to provide simple optimistic
324
+ # concurrency control when multiple clients or threads try to update an
325
+ # item simultaneously.
326
+ # @option options [Symbol] :format (self.default_format) The
327
+ # representation for storing the value in the bucket. For more info see
328
+ # {Bucket#default_format}.
329
+ # @option options [Hash] :observe Apply persistence condition before
330
+ # returning result. When this option specified the library will observe
331
+ # given condition. See {Bucket#observe_and_wait}.
332
+ #
333
+ # @raise [Couchbase::Error::Connect] if connection closed (see {Bucket#reconnect})
334
+ # @raise [Couchbase::Error::KeyExists] on CAS mismatch
335
+ # @raise [Couchbase::Error::NotStored] if the key doesn't exist
336
+ # @raise [ArgumentError] when passing the block in synchronous mode
337
+ # @raise [Couchbase::Error::Timeout] if timeout interval for observe
338
+ # exceeds
339
+ #
340
+ # @example Simple prepend example
341
+ # c.set("foo", "aaa")
342
+ # c.prepend("foo", "bbb")
343
+ # c.get("foo") #=> "bbbaaa"
344
+ #
345
+ # @example Using explicit format option
346
+ # c.default_format #=> :document
347
+ # c.set("foo", {"y" => "z"})
348
+ # c.prepend("foo", '[', :format => :plain)
349
+ # c.append("foo", ', {"z": "y"}]', :format => :plain)
350
+ # c.get("foo") #=> [{"y"=>"z"}, {"z"=>"y"}]
351
+ #
352
+ # @example Using optimistic locking. The operation will fail on CAS mismatch
353
+ # ver = c.set("foo", "aaa")
354
+ # c.prepend("foo", "bbb", :cas => ver)
355
+ #
356
+ # @example Ensure that the key will be persisted at least on the one node
357
+ # c.prepend("foo", "bar", :observe => {:persisted => 1})
358
+ #
359
+ def prepend(*args)
360
+ sync_block_error if !async? && block_given?
361
+ end
362
+
363
+ private
364
+
365
+ def store_args_parser(key, value, options)
366
+ key = key.to_str if key.respond_to?(:to_str)
367
+ ttl = options[:ttl] || default_ttl
368
+
369
+ op = case key
370
+ when String, Symbol
371
+ :single
372
+ when Hash
373
+ raise TypeError.new if !value.nil?
374
+ :multi
375
+ else
376
+ raise TypeError.new
377
+ end
378
+
379
+ [op, key, value, ttl]
380
+ end
381
+
382
+ def set_single(key, value, ttl, options = {}, &block)
383
+ if async?
384
+ java_async_set(key, value, ttl, &block)
385
+ else
386
+ if options[:cas]
387
+ if java_set_cas(key, value, ttl, options[:cas])
388
+ get(key, extended: true)[2]
389
+ else
390
+ raise Couchbase::Error::KeyExists.new
391
+ end
392
+ else
393
+ if cas = java_set(key, value, ttl)
394
+ cas
395
+ else
396
+ raise Couchbase::Error::KeyExists.new
397
+ end
398
+ end
399
+ end
400
+ end
401
+
402
+ def add_single(key, value, ttl, options = {})
403
+ if async?
404
+ java_async_set(key, value, ttl, &Proc.new)
405
+ else
406
+ if cas = java_add(key, value, ttl)
407
+ cas
408
+ else
409
+ raise Couchbase::Error::KeyExists.new
410
+ end
411
+ end
412
+ end
413
+
414
+ # TODO:
415
+ def set_multi(keys)
416
+ {}.tap do |results|
417
+ keys.each_pair do |key, value|
418
+ results[key] = java_set(key, value, default_ttl)
419
+ end
420
+ end
421
+ end
422
+
423
+ def add_multi(keys)
424
+ {}.tap do |results|
425
+ keys.each_pair do |key, value|
426
+ results[key] = java_add(key, value, default_ttl)
427
+ end
428
+ end
429
+ end
430
+
431
+ def java_set(key, value, ttl)
432
+ future = client.set(key.to_s, ttl, dump(value))
433
+ future_cas(future)
434
+ end
435
+
436
+ def java_add(key, value, ttl)
437
+ future = client.add(key.to_s, ttl, dump(value))
438
+ future_cas(future)
439
+ end
440
+
441
+ def java_replace(key, value, ttl)
442
+ future = if ttl.nil?
443
+ client.replace(key.to_s, dump(value))
444
+ else
445
+ client.replace(key.to_s, ttl, dump(value))
446
+ end
447
+
448
+ future_cas(future)
449
+ end
450
+
451
+ def java_append(key, value)
452
+ future = client.append(key.to_s, dump(value))
453
+ future_cas(future)
454
+ end
455
+
456
+ def java_set_cas(key, value, ttl, cas)
457
+ cas_response = client.cas(key.to_s, cas, ttl, dump(value))
458
+ cas_response.to_s == 'OK'
459
+ end
460
+
461
+ def java_async_set(key, value, ttl, &block)
462
+ future = client.set(key.to_s, ttl, dump(value))
463
+ register_future(future, { op: :set }, &block)
464
+ end
465
+
466
+ end
467
+
468
+ end
@@ -0,0 +1,123 @@
1
+ module Couchbase::Operations
2
+ module Touch
3
+
4
+ # Update the expiry time of an item
5
+ #
6
+ # @since 1.0.0
7
+ #
8
+ # The +touch+ method allow you to update the expiration time on a given
9
+ # key. This can be useful for situations where you want to prevent an item
10
+ # from expiring without resetting the associated value. For example, for a
11
+ # session database you might want to keep the session alive in the database
12
+ # each time the user accesses a web page without explicitly updating the
13
+ # session value, keeping the user's session active and available.
14
+ #
15
+ # @overload touch(key, options = {})
16
+ # @param key [String, Symbol] Key used to reference the value.
17
+ # @param options [Hash] Options for operation.
18
+ # @option options [Fixnum] :ttl (self.default_ttl) Expiry time for key.
19
+ # Values larger than 30*24*60*60 seconds (30 days) are interpreted as
20
+ # absolute times (from the epoch).
21
+ # @option options [true, false] :quiet (self.quiet) If set to +true+, the
22
+ # operation won't raise error for missing key, it will return +nil+.
23
+ #
24
+ # @yieldparam ret [Result] the result of operation in asynchronous mode
25
+ # (valid attributes: +error+, +operation+, +key+).
26
+ #
27
+ # @return [true, false] +true+ if the operation was successful and +false+
28
+ # otherwise.
29
+ #
30
+ # @raise [Couchbase::Error::Connect] if connection closed (see {Bucket#reconnect})
31
+ #
32
+ # @raise [ArgumentError] when passing the block in synchronous mode
33
+ #
34
+ # @example Touch value using +default_ttl+
35
+ # c.touch("foo")
36
+ #
37
+ # @example Touch value using custom TTL (10 seconds)
38
+ # c.touch("foo", :ttl => 10)
39
+ #
40
+ # @overload touch(keys)
41
+ # @param keys [Hash] The Hash where keys represent the keys in the
42
+ # database, values -- the expiry times for corresponding key. See
43
+ # description of +:ttl+ argument above for more information about TTL
44
+ # values.
45
+ #
46
+ # @yieldparam ret [Result] the result of operation for each key in
47
+ # asynchronous mode (valid attributes: +error+, +operation+, +key+).
48
+ #
49
+ # @return [Hash] Mapping keys to result of touch operation (+true+ if the
50
+ # operation was successful and +false+ otherwise)
51
+ #
52
+ # @example Touch several values
53
+ # c.touch("foo" => 10, :bar => 20) #=> {"foo" => true, "bar" => true}
54
+ #
55
+ # @example Touch several values in async mode
56
+ # c.run do
57
+ # c.touch("foo" => 10, :bar => 20) do |ret|
58
+ # ret.operation #=> :touch
59
+ # ret.success? #=> true
60
+ # ret.key #=> "foo" and "bar" in separate calls
61
+ # end
62
+ # end
63
+ #
64
+ # @example Touch single value
65
+ # c.touch("foo" => 10) #=> true
66
+ #
67
+ def touch(*args, &block)
68
+ sync_block_error if !async? && block_given?
69
+ key, options = expand_touch_args(args)
70
+
71
+ if key.respond_to?(:to_hash)
72
+ multi_touch_hash(key, options)
73
+ elsif key.respond_to?(:to_ary)
74
+ multi_touch_array(key, options)
75
+ else
76
+ if async?
77
+ java_async_touch(key, options[:ttl], &block)
78
+ else
79
+ success = java_touch(key, options[:ttl])
80
+ not_found_error(!success, options)
81
+ success
82
+ end
83
+ end
84
+ end
85
+
86
+ private
87
+
88
+ def expand_touch_args(args)
89
+ options = extract_options_hash(args)
90
+ options[:ttl] ||= args.size > 1 ? args.pop : default_ttl
91
+ key = args.pop
92
+
93
+ [key, options]
94
+ end
95
+
96
+ def multi_touch_hash(keys, options = {})
97
+ {}.tap do |results|
98
+ keys.each_pair do |key, ttl|
99
+ results[key] = java_touch(key, ttl)
100
+ end
101
+ end
102
+ end
103
+
104
+ def multi_touch_array(keys, options = {})
105
+ ttl = options[:ttl] || default_ttl
106
+
107
+ {}.tap do |results|
108
+ keys.each do |key|
109
+ results[key] = java_touch(key, ttl)
110
+ end
111
+ end
112
+ end
113
+
114
+ def java_touch(key, ttl, options = {})
115
+ client.touch(key, ttl).get
116
+ end
117
+
118
+ def java_async_touch(key, ttl, &block)
119
+ register_future(client.touch(key, ttl), { op: :touch }, &block)
120
+ end
121
+
122
+ end
123
+ end
@@ -0,0 +1,49 @@
1
+ module Couchbase::Operations
2
+ module Utils
3
+
4
+ private
5
+
6
+ def validate_key(key)
7
+ if key_prefix
8
+ "#{key_prefix}key"
9
+ else
10
+ key.to_s
11
+ end
12
+ end
13
+
14
+ def extract_options_hash(args)
15
+ if args.size > 1 && args.last.respond_to?(:to_hash)
16
+ args.pop
17
+ else
18
+ {}
19
+ end
20
+ end
21
+
22
+ def sync_block_error
23
+ raise ArgumentError, "synchronous mode doesn't support callbacks"
24
+ end
25
+
26
+ def not_found_error(error, options = {})
27
+ if error
28
+ if options.key?(:quiet)
29
+ raise Error::NotFound.new if !options[:quiet]
30
+ elsif !quiet?
31
+ raise Error::NotFound.new
32
+ end
33
+ end
34
+ end
35
+
36
+ def future_cas(future)
37
+ future.get && future.getCas
38
+ end
39
+
40
+ def dump(obj)
41
+ transcoder.dump(obj)
42
+ end
43
+
44
+ def load(blob)
45
+ transcoder.load(blob)
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,23 @@
1
+ require 'couchbase/operations/touch'
2
+ require 'couchbase/operations/store'
3
+ require 'couchbase/operations/get'
4
+ require 'couchbase/operations/delete'
5
+ require 'couchbase/operations/arithmetic'
6
+ require 'couchbase/operations/stats'
7
+ require 'couchbase/operations/utils'
8
+
9
+ module Couchbase
10
+ module Operations
11
+
12
+ def self.included(klass)
13
+ klass.send(:include, Store)
14
+ klass.send(:include, Get)
15
+ klass.send(:include, Touch)
16
+ klass.send(:include, Delete)
17
+ klass.send(:include, Arithmetic)
18
+ klass.send(:include, Stats)
19
+ klass.send(:include, Utils)
20
+ end
21
+ end
22
+ end
23
+