couchbase-jruby-client 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.jrubyrc +722 -0
  4. data/.ruby-version +1 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +203 -0
  7. data/README.md +349 -0
  8. data/Rakefile +10 -0
  9. data/couchbase-jruby-client.gemspec +31 -0
  10. data/lib/couchbase/async/callback.rb +19 -0
  11. data/lib/couchbase/async/queue.rb +26 -0
  12. data/lib/couchbase/async.rb +140 -0
  13. data/lib/couchbase/bucket.rb +556 -0
  14. data/lib/couchbase/cluster.rb +105 -0
  15. data/lib/couchbase/constants.rb +12 -0
  16. data/lib/couchbase/design_doc.rb +61 -0
  17. data/lib/couchbase/error.rb +43 -0
  18. data/lib/couchbase/jruby/couchbase_client.rb +22 -0
  19. data/lib/couchbase/jruby/future.rb +8 -0
  20. data/lib/couchbase/operations/arithmetic.rb +301 -0
  21. data/lib/couchbase/operations/delete.rb +104 -0
  22. data/lib/couchbase/operations/design_docs.rb +99 -0
  23. data/lib/couchbase/operations/get.rb +282 -0
  24. data/lib/couchbase/operations/stats.rb +26 -0
  25. data/lib/couchbase/operations/store.rb +461 -0
  26. data/lib/couchbase/operations/touch.rb +136 -0
  27. data/lib/couchbase/operations/unlock.rb +192 -0
  28. data/lib/couchbase/operations/utils.rb +44 -0
  29. data/lib/couchbase/operations.rb +27 -0
  30. data/lib/couchbase/query.rb +73 -0
  31. data/lib/couchbase/result.rb +43 -0
  32. data/lib/couchbase/transcoder.rb +77 -0
  33. data/lib/couchbase/utils.rb +62 -0
  34. data/lib/couchbase/version.rb +3 -0
  35. data/lib/couchbase/view.rb +367 -0
  36. data/lib/couchbase/view_row.rb +193 -0
  37. data/lib/couchbase.rb +157 -0
  38. data/lib/jars/commons-codec-1.5.jar +0 -0
  39. data/lib/jars/couchbase-client-1.2.0-javadoc.jar +0 -0
  40. data/lib/jars/couchbase-client-1.2.0-sources.jar +0 -0
  41. data/lib/jars/couchbase-client-1.2.0.jar +0 -0
  42. data/lib/jars/httpcore-4.1.1.jar +0 -0
  43. data/lib/jars/httpcore-nio-4.1.1.jar +0 -0
  44. data/lib/jars/jettison-1.1.jar +0 -0
  45. data/lib/jars/netty-3.5.5.Final.jar +0 -0
  46. data/lib/jars/spymemcached-2.10.0-javadoc.jar +0 -0
  47. data/lib/jars/spymemcached-2.10.0-sources.jar +0 -0
  48. data/lib/jars/spymemcached-2.10.0.jar +0 -0
  49. data/test/profile/.gitignore +1 -0
  50. data/test/profile/.jrubyrc +722 -0
  51. data/test/profile/Gemfile +6 -0
  52. data/test/profile/benchmark.rb +168 -0
  53. data/test/profile/profile.rb +59 -0
  54. data/test/setup.rb +203 -0
  55. data/test/test_arithmetic.rb +177 -0
  56. data/test/test_async.rb +324 -0
  57. data/test/test_bucket.rb +213 -0
  58. data/test/test_cas.rb +79 -0
  59. data/test/test_couchbase.rb +29 -0
  60. data/test/test_couchbase_rails_cache_store.rb +341 -0
  61. data/test/test_delete.rb +125 -0
  62. data/test/test_design_docs.rb +72 -0
  63. data/test/test_errors.rb +82 -0
  64. data/test/test_format.rb +161 -0
  65. data/test/test_get.rb +417 -0
  66. data/test/test_query.rb +23 -0
  67. data/test/test_stats.rb +57 -0
  68. data/test/test_store.rb +213 -0
  69. data/test/test_timer.rb +43 -0
  70. data/test/test_touch.rb +97 -0
  71. data/test/test_unlock.rb +121 -0
  72. data/test/test_utils.rb +58 -0
  73. data/test/test_version.rb +53 -0
  74. data/test/test_view.rb +94 -0
  75. metadata +255 -0
@@ -0,0 +1,461 @@
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 = {})
98
+ if async?
99
+ if block_given?
100
+ async_set(key, value, options, &Proc.new)
101
+ else
102
+ async_set(key, value, options)
103
+ end
104
+ else
105
+ sync_block_error if block_given?
106
+ store_op(:set, key, value, options)
107
+ end
108
+ end
109
+
110
+ def async_set(key, value, options, &block)
111
+ async_store_op(:set, key, value, options, &block)
112
+ end
113
+
114
+ def []=(key, *args)
115
+ options = args.size > 1 ? args.shift : {}
116
+ value = args.pop
117
+
118
+ set(key, value, options)
119
+ end
120
+
121
+ # Add the item to the database, but fail if the object exists already
122
+ #
123
+ # @since 1.0.0
124
+ #
125
+ # @overload add(key, value, options = {})
126
+ #
127
+ # @param key [String, Symbol] Key used to reference the value.
128
+ # @param value [Object] Value to be stored
129
+ # @param options [Hash] Options for operation.
130
+ # @option options [Fixnum] :ttl (self.default_ttl) Expiry time for key.
131
+ # Values larger than 30*24*60*60 seconds (30 days) are interpreted as
132
+ # absolute times (from the epoch).
133
+ # @option options [Fixnum] :flags (self.default_flags) Flags for storage
134
+ # options. Flags are ignored by the server but preserved for use by the
135
+ # client. For more info see {Bucket#default_flags}.
136
+ # @option options [Symbol] :format (self.default_format) The
137
+ # representation for storing the value in the bucket. For more info see
138
+ # {Bucket#default_format}.
139
+ # @option options [Fixnum] :cas The CAS value for an object. This value
140
+ # created on the server and is guaranteed to be unique for each value of
141
+ # a given key. This value is used to provide simple optimistic
142
+ # concurrency control when multiple clients or threads try to update an
143
+ # item simultaneously.
144
+ # @option options [Hash] :observe Apply persistence condition before
145
+ # returning result. When this option specified the library will observe
146
+ # given condition. See {Bucket#observe_and_wait}.
147
+ #
148
+ # @yieldparam ret [Result] the result of operation in asynchronous mode
149
+ # (valid attributes: +error+, +operation+, +key+).
150
+ #
151
+ # @return [Fixnum] The CAS value of the object.
152
+ #
153
+ # @raise [Couchbase::Error::Connect] if connection closed (see {Bucket#reconnect})
154
+ # @raise [Couchbase::Error::KeyExists] if the key already exists on the
155
+ # server
156
+ # @raise [Couchbase::Error::ValueFormat] if the value cannot be serialized
157
+ # with chosen encoder, e.g. if you try to store the Hash in +:plain+
158
+ # mode.
159
+ # @raise [ArgumentError] when passing the block in synchronous mode
160
+ # @raise [Couchbase::Error::Timeout] if timeout interval for observe
161
+ # exceeds
162
+ #
163
+ # @example Add the same key twice
164
+ # c.add("foo", "bar") #=> stored successully
165
+ # c.add("foo", "baz") #=> will raise Couchbase::Error::KeyExists: failed to store value (key="foo", error=0x0c)
166
+ #
167
+ # @example Ensure that the key will be persisted at least on the one node
168
+ # c.add("foo", "bar", :observe => {:persisted => 1})
169
+ #
170
+ def add(key, value = nil, options = {})
171
+ if async?
172
+ if block_given?
173
+ async_add(key, value, options, &Proc.new)
174
+ else
175
+ async_add(key, value, options)
176
+ end
177
+ else
178
+ sync_block_error if block_given?
179
+ store_op(:add, key, value, options)
180
+ end
181
+ end
182
+
183
+ def async_add(key, value, options, &block)
184
+ async_store_op(:add, key, value, options, &block)
185
+ end
186
+
187
+ # Replace the existing object in the database
188
+ #
189
+ # @since 1.0.0
190
+ #
191
+ # @overload replace(key, value, options = {})
192
+ # @param key [String, Symbol] Key used to reference the value.
193
+ # @param value [Object] Value to be stored
194
+ # @param options [Hash] Options for operation.
195
+ # @option options [Fixnum] :ttl (self.default_ttl) Expiry time for key.
196
+ # Values larger than 30*24*60*60 seconds (30 days) are interpreted as
197
+ # absolute times (from the epoch).
198
+ # @option options [Fixnum] :flags (self.default_flags) Flags for storage
199
+ # options. Flags are ignored by the server but preserved for use by the
200
+ # client. For more info see {Bucket#default_flags}.
201
+ # @option options [Symbol] :format (self.default_format) The
202
+ # representation for storing the value in the bucket. For more info see
203
+ # {Bucket#default_format}.
204
+ # @option options [Fixnum] :cas The CAS value for an object. This value
205
+ # created on the server and is guaranteed to be unique for each value of
206
+ # a given key. This value is used to provide simple optimistic
207
+ # concurrency control when multiple clients or threads try to update an
208
+ # item simultaneously.
209
+ # @option options [Hash] :observe Apply persistence condition before
210
+ # returning result. When this option specified the library will observe
211
+ # given condition. See {Bucket#observe_and_wait}.
212
+ #
213
+ # @return [Fixnum] The CAS value of the object.
214
+ #
215
+ # @raise [Couchbase::Error::Connect] if connection closed (see {Bucket#reconnect})
216
+ # @raise [Couchbase::Error::NotFound] if the key doesn't exists
217
+ # @raise [Couchbase::Error::KeyExists] on CAS mismatch
218
+ # @raise [ArgumentError] when passing the block in synchronous mode
219
+ # @raise [Couchbase::Error::Timeout] if timeout interval for observe
220
+ # exceeds
221
+ #
222
+ # @example Replacing missing key
223
+ # c.replace("foo", "baz") #=> will raise Couchbase::Error::NotFound: failed to store value (key="foo", error=0x0d)
224
+ #
225
+ # @example Ensure that the key will be persisted at least on the one node
226
+ # c.replace("foo", "bar", :observe => {:persisted => 1})
227
+ #
228
+ def replace(key, value, options = {})
229
+ if async?
230
+ if block_given?
231
+ async_replace(key, value, options, &Proc.new)
232
+ else
233
+ async_replace(key, value, options)
234
+ end
235
+ else
236
+ sync_block_error if block_given?
237
+ store_op(:replace, key, value, options)
238
+ end
239
+ end
240
+
241
+ def async_replace(key, value, options, &block)
242
+ async_store_op(:replace, key, value, options, &block)
243
+ end
244
+
245
+ # Append this object to the existing object
246
+ #
247
+ # @since 1.0.0
248
+ #
249
+ # @note This operation is kind of data-aware from server point of view.
250
+ # This mean that the server treats value as binary stream and just
251
+ # perform concatenation, therefore it won't work with +:marshal+ and
252
+ # +:document+ formats, because of lack of knowledge how to merge values
253
+ # in these formats. See {Bucket#cas} for workaround.
254
+ #
255
+ # @overload append(key, value, options = {})
256
+ # @param key [String, Symbol] Key used to reference the value.
257
+ # @param value [Object] Value to be stored
258
+ # @param options [Hash] Options for operation.
259
+ # @option options [Fixnum] :cas The CAS value for an object. This value
260
+ # created on the server and is guaranteed to be unique for each value of
261
+ # a given key. This value is used to provide simple optimistic
262
+ # concurrency control when multiple clients or threads try to update an
263
+ # item simultaneously.
264
+ # @option options [Symbol] :format (self.default_format) The
265
+ # representation for storing the value in the bucket. For more info see
266
+ # {Bucket#default_format}.
267
+ # @option options [Hash] :observe Apply persistence condition before
268
+ # returning result. When this option specified the library will observe
269
+ # given condition. See {Bucket#observe_and_wait}.
270
+ #
271
+ # @return [Fixnum] The CAS value of the object.
272
+ #
273
+ # @raise [Couchbase::Error::Connect] if connection closed (see {Bucket#reconnect})
274
+ # @raise [Couchbase::Error::KeyExists] on CAS mismatch
275
+ # @raise [Couchbase::Error::NotStored] if the key doesn't exist
276
+ # @raise [ArgumentError] when passing the block in synchronous mode
277
+ # @raise [Couchbase::Error::Timeout] if timeout interval for observe
278
+ # exceeds
279
+ #
280
+ # @example Simple append
281
+ # c.set("foo", "aaa")
282
+ # c.append("foo", "bbb")
283
+ # c.get("foo") #=> "aaabbb"
284
+ #
285
+ # @example Implementing sets using append
286
+ # def set_add(key, *values)
287
+ # encoded = values.flatten.map{|v| "+#{v} "}.join
288
+ # append(key, encoded)
289
+ # end
290
+ #
291
+ # def set_remove(key, *values)
292
+ # encoded = values.flatten.map{|v| "-#{v} "}.join
293
+ # append(key, encoded)
294
+ # end
295
+ #
296
+ # def set_get(key)
297
+ # encoded = get(key)
298
+ # ret = Set.new
299
+ # encoded.split(' ').each do |v|
300
+ # op, val = v[0], v[1..-1]
301
+ # case op
302
+ # when "-"
303
+ # ret.delete(val)
304
+ # when "+"
305
+ # ret.add(val)
306
+ # end
307
+ # end
308
+ # ret
309
+ # end
310
+ #
311
+ # @example Using optimistic locking. The operation will fail on CAS mismatch
312
+ # ver = c.set("foo", "aaa")
313
+ # c.append("foo", "bbb", :cas => ver)
314
+ #
315
+ # @example Ensure that the key will be persisted at least on the one node
316
+ # c.append("foo", "bar", :observe => {:persisted => 1})
317
+ #
318
+ def append(key, value)
319
+ sync_block_error if block_given?
320
+ store_op(:append, key, value)
321
+ end
322
+
323
+ # Prepend this object to the existing object
324
+ #
325
+ # @since 1.0.0
326
+ #
327
+ # @note This operation is kind of data-aware from server point of view.
328
+ # This mean that the server treats value as binary stream and just
329
+ # perform concatenation, therefore it won't work with +:marshal+ and
330
+ # +:document+ formats, because of lack of knowledge how to merge values
331
+ # in these formats. See {Bucket#cas} for workaround.
332
+ #
333
+ # @overload prepend(key, value, options = {})
334
+ # @param key [String, Symbol] Key used to reference the value.
335
+ # @param value [Object] Value to be stored
336
+ # @param options [Hash] Options for operation.
337
+ # @option options [Fixnum] :cas The CAS value for an object. This value
338
+ # created on the server and is guaranteed to be unique for each value of
339
+ # a given key. This value is used to provide simple optimistic
340
+ # concurrency control when multiple clients or threads try to update an
341
+ # item simultaneously.
342
+ # @option options [Symbol] :format (self.default_format) The
343
+ # representation for storing the value in the bucket. For more info see
344
+ # {Bucket#default_format}.
345
+ # @option options [Hash] :observe Apply persistence condition before
346
+ # returning result. When this option specified the library will observe
347
+ # given condition. See {Bucket#observe_and_wait}.
348
+ #
349
+ # @raise [Couchbase::Error::Connect] if connection closed (see {Bucket#reconnect})
350
+ # @raise [Couchbase::Error::KeyExists] on CAS mismatch
351
+ # @raise [Couchbase::Error::NotStored] if the key doesn't exist
352
+ # @raise [ArgumentError] when passing the block in synchronous mode
353
+ # @raise [Couchbase::Error::Timeout] if timeout interval for observe
354
+ # exceeds
355
+ #
356
+ # @example Simple prepend example
357
+ # c.set("foo", "aaa")
358
+ # c.prepend("foo", "bbb")
359
+ # c.get("foo") #=> "bbbaaa"
360
+ #
361
+ # @example Using explicit format option
362
+ # c.default_format #=> :document
363
+ # c.set("foo", {"y" => "z"})
364
+ # c.prepend("foo", '[', :format => :plain)
365
+ # c.append("foo", ', {"z": "y"}]', :format => :plain)
366
+ # c.get("foo") #=> [{"y"=>"z"}, {"z"=>"y"}]
367
+ #
368
+ # @example Using optimistic locking. The operation will fail on CAS mismatch
369
+ # ver = c.set("foo", "aaa")
370
+ # c.prepend("foo", "bbb", :cas => ver)
371
+ #
372
+ # @example Ensure that the key will be persisted at least on the one node
373
+ # c.prepend("foo", "bar", :observe => {:persisted => 1})
374
+ #
375
+ def prepend(key, value)
376
+ sync_block_error if block_given?
377
+ store_op(:prepend, key, value)
378
+ end
379
+
380
+ private
381
+
382
+ def store_args_parser(key, value, options)
383
+ key = key.to_str if key.respond_to?(:to_str)
384
+ ttl = options.delete(:ttl) || default_ttl
385
+ transcoder = @transcoders[options.delete(:format)] || @transcoder
386
+
387
+ [key, value, ttl, transcoder]
388
+ end
389
+
390
+ def store_op(op, key, value, options = {})
391
+ key, value, ttl, transcoder = store_args_parser(key, value, options)
392
+
393
+ case key
394
+ when String, Symbol
395
+ key = key.to_s
396
+ if options[:cas] && op == :set
397
+ client_cas(key, value, ttl, options[:cas], transcoder)
398
+ else
399
+ future = client_store_op(op, key, value, ttl, transcoder)
400
+ if cas = future_cas(future)
401
+ cas
402
+ else
403
+ case op
404
+ when :replace
405
+ fail Couchbase::Error::NotFound
406
+ when :append, :prepend
407
+ fail Couchbase::Error::NotStored
408
+ else
409
+ fail Couchbase::Error::KeyExists
410
+ end
411
+ end
412
+ end
413
+ when Hash
414
+ fail TypeError.new if !value.nil?
415
+ multi_op(op, key)
416
+ else
417
+ fail TypeError.new
418
+ end
419
+ end
420
+
421
+ def async_store_op(op, key, value, options, &block)
422
+ key, value, ttl, transcoder = store_args_parser(key, value, options)
423
+ future = client_store_op(op, key, value, ttl, transcoder)
424
+ register_future(future, { op: op }, &block)
425
+ end
426
+
427
+ def multi_op(op, keys)
428
+ {}.tap do |results|
429
+ keys.each_pair do |key, value|
430
+ results[key] = client.send(op, key, default_ttl, value)
431
+ end
432
+ end
433
+ end
434
+
435
+ def client_store_op(op, key, value, ttl, transcoder)
436
+ case op
437
+ when :set
438
+ client.set(key, ttl, value, transcoder)
439
+ when :add
440
+ client.add(key, ttl, value, transcoder)
441
+ when :replace
442
+ client.replace(key, ttl, value, transcoder)
443
+ when :append
444
+ client.append(key, value)
445
+ when :prepend
446
+ client.prepend(key, value)
447
+ end
448
+ end
449
+
450
+ def client_cas(key, value, ttl, cas, transcoder)
451
+ cas_response = client.cas(key, cas, ttl, value, transcoder)
452
+ if cas_response.to_s == 'OK'
453
+ get(key, extended: true)[2]
454
+ else
455
+ raise Couchbase::Error::KeyExists.new
456
+ end
457
+ end
458
+
459
+ end
460
+
461
+ end
@@ -0,0 +1,136 @@
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)
68
+ sync_block_error if !async? && block_given?
69
+ key, ttl, options = expand_touch_args(args)
70
+
71
+ case key
72
+ when String, Symbol
73
+ if async?
74
+ if block_given?
75
+ async_touch(key, ttl, &Proc.new)
76
+ else
77
+ async_touch(key, ttl)
78
+ end
79
+ else
80
+ success = client_touch(key, ttl)
81
+ not_found_error(!success, options)
82
+ success
83
+ end
84
+ when Hash
85
+ multi_touch_hash(key, options)
86
+ when Array
87
+ multi_touch_array(key, options)
88
+ end
89
+ end
90
+
91
+ def async_touch(key, ttl)
92
+ if block_given?
93
+ register_future(client.touch(key, ttl), { op: :touch }, &Proc.new)
94
+ else
95
+ client.touch(key, ttl)
96
+ end
97
+ end
98
+
99
+ private
100
+
101
+ def expand_touch_args(args)
102
+ options = extract_options_hash(args)
103
+ ttl = options[:ttl] || if args.size > 1 && args.last.respond_to?(:to_int?)
104
+ args.pop
105
+ else
106
+ default_ttl
107
+ end
108
+ key = args.size > 1 ? args : args.pop
109
+
110
+ [key, ttl, options]
111
+ end
112
+
113
+ def multi_touch_hash(keys, options = {})
114
+ {}.tap do |results|
115
+ keys.each_pair do |key, ttl|
116
+ results[key] = client_touch(key, ttl)
117
+ end
118
+ end
119
+ end
120
+
121
+ def multi_touch_array(keys, options = {})
122
+ ttl = options[:ttl] || default_ttl
123
+
124
+ {}.tap do |results|
125
+ keys.each do |key|
126
+ results[key] = client_touch(key, ttl)
127
+ end
128
+ end
129
+ end
130
+
131
+ def client_touch(key, ttl, options = {})
132
+ client.touch(key, ttl).get
133
+ end
134
+
135
+ end
136
+ end