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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +203 -0
- data/README.md +347 -0
- data/Rakefile +10 -0
- data/couchbase-jruby-client.gemspec +30 -0
- data/lib/couchbase/async/callback.rb +19 -0
- data/lib/couchbase/async/queue.rb +26 -0
- data/lib/couchbase/async.rb +139 -0
- data/lib/couchbase/bucket.rb +663 -0
- data/lib/couchbase/cluster.rb +105 -0
- data/lib/couchbase/constants.rb +12 -0
- data/lib/couchbase/error.rb +28 -0
- data/lib/couchbase/jruby/couchbase_client.rb +22 -0
- data/lib/couchbase/jruby/future.rb +8 -0
- data/lib/couchbase/operations/arithmetic.rb +301 -0
- data/lib/couchbase/operations/delete.rb +104 -0
- data/lib/couchbase/operations/get.rb +298 -0
- data/lib/couchbase/operations/stats.rb +16 -0
- data/lib/couchbase/operations/store.rb +468 -0
- data/lib/couchbase/operations/touch.rb +123 -0
- data/lib/couchbase/operations/utils.rb +49 -0
- data/lib/couchbase/operations.rb +23 -0
- data/lib/couchbase/result.rb +43 -0
- data/lib/couchbase/transcoder.rb +83 -0
- data/lib/couchbase/utils.rb +62 -0
- data/lib/couchbase/version.rb +3 -0
- data/lib/couchbase/view.rb +506 -0
- data/lib/couchbase/view_row.rb +272 -0
- data/lib/couchbase.rb +177 -0
- data/lib/jars/commons-codec-1.5.jar +0 -0
- data/lib/jars/couchbase-client-1.2.0-javadoc.jar +0 -0
- data/lib/jars/couchbase-client-1.2.0-sources.jar +0 -0
- data/lib/jars/couchbase-client-1.2.0.jar +0 -0
- data/lib/jars/httpcore-4.1.1.jar +0 -0
- data/lib/jars/httpcore-nio-4.1.1.jar +0 -0
- data/lib/jars/jettison-1.1.jar +0 -0
- data/lib/jars/netty-3.5.5.Final.jar +0 -0
- data/lib/jars/spymemcached-2.10.0-javadoc.jar +0 -0
- data/lib/jars/spymemcached-2.10.0-sources.jar +0 -0
- data/lib/jars/spymemcached-2.10.0.jar +0 -0
- data/test/profile/.gitignore +1 -0
- data/test/profile/Gemfile +6 -0
- data/test/profile/benchmark.rb +195 -0
- data/test/setup.rb +201 -0
- data/test/test_arithmetic.rb +177 -0
- data/test/test_async.rb +324 -0
- data/test/test_bucket.rb +213 -0
- data/test/test_cas.rb +78 -0
- data/test/test_couchbase.rb +29 -0
- data/test/test_couchbase_rails_cache_store.rb +341 -0
- data/test/test_delete.rb +125 -0
- data/test/test_errors.rb +82 -0
- data/test/test_format.rb +161 -0
- data/test/test_get.rb +417 -0
- data/test/test_stats.rb +57 -0
- data/test/test_store.rb +216 -0
- data/test/test_timer.rb +42 -0
- data/test/test_touch.rb +97 -0
- data/test/test_unlock.rb +119 -0
- data/test/test_utils.rb +58 -0
- data/test/test_version.rb +52 -0
- 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
|
+
|