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,99 @@
1
+ # Author:: Mike Evans <mike@urlgonomics.com>
2
+ # Copyright:: 2013 Urlgonomics LLC.
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::Operations
19
+ module DesignDocs
20
+
21
+ java_import com.couchbase.client.protocol.views.DesignDocument
22
+ java_import com.couchbase.client.protocol.views.ViewDesign
23
+
24
+ class DesignDocAccess
25
+ def initialize(bucket)
26
+ @bucket = bucket
27
+ end
28
+
29
+ def [](name)
30
+ doc = @bucket.client.getDesignDocument(name)
31
+ Couchbase::DesignDoc.new(@bucket, doc)
32
+ rescue Java::ComCouchbaseClientProtocolViews::InvalidViewException
33
+ nil
34
+ end
35
+ end
36
+
37
+ # Fetch design docs stored in current bucket
38
+ #
39
+ # @since 1.2.0
40
+ #
41
+ # @return [Hash]
42
+ def design_docs
43
+ DesignDocAccess.new(self)
44
+ end
45
+
46
+ # Update or create design doc with supplied views
47
+ #
48
+ # @since 1.2.0
49
+ #
50
+ # @param [Hash, IO, String] data The source object containing JSON
51
+ # encoded design document. It must have +_id+ key set, this key
52
+ # should start with +_design/+.
53
+ #
54
+ # @return [true, false]
55
+ def save_design_doc(data)
56
+ attrs = case data
57
+ when String
58
+ MultiJson.load(data)
59
+ when IO
60
+ MultiJson.load(data.read)
61
+ when Hash
62
+ data
63
+ else
64
+ raise ArgumentError, "Document should be Hash, String or IO instance"
65
+ end
66
+
67
+ id = attrs.delete('_id').to_s.split('/')[1]
68
+
69
+ design_doc = DesignDocument.new(id)
70
+
71
+ attrs['views'].each_pair do |view, functions|
72
+ view_design = if functions['reduce']
73
+ ViewDesign.new(view, functions['map'], functions['reduce'])
74
+ else
75
+ ViewDesign.new(view, functions['map'])
76
+ end
77
+ design_doc.getViews.add(view_design)
78
+ end
79
+
80
+ client.createDesignDoc(design_doc)
81
+ end
82
+
83
+ # Delete design doc with given id and revision.
84
+ #
85
+ # @since 1.2.0
86
+ #
87
+ # @param [String] id Design document id. It might have '_design/'
88
+ # prefix.
89
+ #
90
+ # @param [String] rev Document revision. It uses latest revision if
91
+ # +rev+ parameter is nil.
92
+ #
93
+ # @return [true, false]
94
+ def delete_design_doc(id, rev = nil)
95
+ client.deleteDesignDoc(id)
96
+ end
97
+
98
+ end
99
+ end
@@ -0,0 +1,282 @@
1
+ module Couchbase::Operations
2
+ module Get
3
+
4
+ # Obtain an object stored in Couchbase by given key.
5
+ #
6
+ # @since 1.0.0
7
+ #
8
+ # @see http://couchbase.com/docs/couchbase-manual-2.0/couchbase-architecture-apis-memcached-protocol-additions.html#couchbase-architecture-apis-memcached-protocol-additions-getl
9
+ #
10
+ # @overload get(*keys, options = {})
11
+ # @param keys [String, Symbol, Array] One or several keys to fetch
12
+ # @param options [Hash] Options for operation.
13
+ # @option options [true, false] :extended (false) If set to +true+, the
14
+ # operation will return a tuple +[value, flags, cas]+, otherwise (by
15
+ # default) it returns just the value.
16
+ # @option options [Fixnum] :ttl (self.default_ttl) Expiry time for key.
17
+ # Values larger than 30*24*60*60 seconds (30 days) are interpreted as
18
+ # absolute times (from the epoch).
19
+ # @option options [true, false] :quiet (self.quiet) If set to +true+, the
20
+ # operation won't raise error for missing key, it will return +nil+.
21
+ # Otherwise it will raise error in synchronous mode. In asynchronous
22
+ # mode this option ignored.
23
+ # @option options [Symbol] :format (nil) Explicitly choose the decoder
24
+ # for this key (+:plain+, +:document+, +:marshal+). See
25
+ # {Bucket#default_format}.
26
+ # @option options [Fixnum, Boolean] :lock Lock the keys for time span.
27
+ # If this parameter is +true+ the key(s) will be locked for default
28
+ # timeout. Also you can use number to setup your own timeout in
29
+ # seconds. If it will be lower that zero or exceed the maximum, the
30
+ # server will use default value. You can determine actual default and
31
+ # maximum values calling {Bucket#stats} without arguments and
32
+ # inspecting keys "ep_getl_default_timeout" and "ep_getl_max_timeout"
33
+ # correspondingly. See overloaded hash syntax to specify custom timeout
34
+ # per each key.
35
+ # @option options [true, false] :assemble_hash (false) Assemble Hash for
36
+ # results. Hash assembled automatically if +:extended+ option is true
37
+ # or in case of "get and touch" multimple keys.
38
+ # @option options [true, false] :replica (false) Read key from replica
39
+ # node. Options +:ttl+ and +:lock+ are not compatible with +:replica+.
40
+ #
41
+ # @yieldparam ret [Result] the result of operation in asynchronous mode
42
+ # (valid attributes: +error+, +operation+, +key+, +value+, +flags+,
43
+ # +cas+).
44
+ #
45
+ # @return [Object, Array, Hash] the value(s) (or tuples in extended mode)
46
+ # associated with the key.
47
+ #
48
+ # @raise [Couchbase::Error::NotFound] if the key is missing in the
49
+ # bucket.
50
+ #
51
+ # @raise [Couchbase::Error::Connect] if connection closed (see {Bucket#reconnect})
52
+ #
53
+ # @raise [ArgumentError] when passing the block in synchronous mode
54
+ #
55
+ # @example Get single value in quiet mode (the default)
56
+ # c.get("foo") #=> the associated value or nil
57
+ #
58
+ # @example Use alternative hash-like syntax
59
+ # c["foo"] #=> the associated value or nil
60
+ #
61
+ # @example Get single value in verbose mode
62
+ # c.get("missing-foo", :quiet => false) #=> raises Couchbase::NotFound
63
+ # c.get("missing-foo", :quiet => true) #=> returns nil
64
+ #
65
+ # @example Get and touch single value. The key won't be accessible after 10 seconds
66
+ # c.get("foo", :ttl => 10)
67
+ #
68
+ # @example Extended get
69
+ # val, flags, cas = c.get("foo", :extended => true)
70
+ #
71
+ # @example Get multiple keys
72
+ # c.get("foo", "bar", "baz") #=> [val1, val2, val3]
73
+ #
74
+ # @example Get multiple keys with assembing result into the Hash
75
+ # c.get("foo", "bar", "baz", :assemble_hash => true)
76
+ # #=> {"foo" => val1, "bar" => val2, "baz" => val3}
77
+ #
78
+ # @example Extended get multiple keys
79
+ # c.get("foo", "bar", :extended => true)
80
+ # #=> {"foo" => [val1, flags1, cas1], "bar" => [val2, flags2, cas2]}
81
+ #
82
+ # @example Asynchronous get
83
+ # c.run do
84
+ # c.get("foo", "bar", "baz") do |res|
85
+ # ret.operation #=> :get
86
+ # ret.success? #=> true
87
+ # ret.key #=> "foo", "bar" or "baz" in separate calls
88
+ # ret.value
89
+ # ret.flags
90
+ # ret.cas
91
+ # end
92
+ # end
93
+ #
94
+ # @example Get and lock key using default timeout
95
+ # c.get("foo", :lock => true)
96
+ #
97
+ # @example Determine lock timeout parameters
98
+ # c.stats.values_at("ep_getl_default_timeout", "ep_getl_max_timeout")
99
+ # #=> [{"127.0.0.1:11210"=>"15"}, {"127.0.0.1:11210"=>"30"}]
100
+ #
101
+ # @example Get and lock key using custom timeout
102
+ # c.get("foo", :lock => 3)
103
+ #
104
+ # @example Get and lock multiple keys using custom timeout
105
+ # c.get("foo", "bar", :lock => 3)
106
+ #
107
+ # @overload get(keys, options = {})
108
+ # When the method receive hash map, it will behave like it receive list
109
+ # of keys (+keys.keys+), but also touch each key setting expiry time to
110
+ # the corresponding value. But unlike usual get this command always
111
+ # return hash map +{key => value}+ or +{key => [value, flags, cas]}+.
112
+ #
113
+ # @param keys [Hash] Map key-ttl
114
+ # @param options [Hash] Options for operation. (see options definition
115
+ # above)
116
+ #
117
+ # @return [Hash] the values (or tuples in extended mode) associated with
118
+ # the keys.
119
+ #
120
+ # @example Get and touch multiple keys
121
+ # c.get("foo" => 10, "bar" => 20) #=> {"foo" => val1, "bar" => val2}
122
+ #
123
+ # @example Extended get and touch multiple keys
124
+ # c.get({"foo" => 10, "bar" => 20}, :extended => true)
125
+ # #=> {"foo" => [val1, flags1, cas1], "bar" => [val2, flags2, cas2]}
126
+ #
127
+ # @example Get and lock multiple keys for chosen period in seconds
128
+ # c.get("foo" => 10, "bar" => 20, :lock => true)
129
+ # #=> {"foo" => val1, "bar" => val2}
130
+ #
131
+ def get(*args)
132
+ key, options = expand_get_args(args)
133
+
134
+ if async?
135
+ if block_given?
136
+ async_get(key, &Proc.new)
137
+ else
138
+ async_get(key)
139
+ end
140
+ else
141
+ sync_block_error if block_given?
142
+ case key
143
+ when String, Symbol
144
+ get_single(key, options)
145
+ when Array
146
+ get_bulk(key, options)
147
+ when Hash
148
+ get_and_touch(key, options)
149
+ end
150
+ end
151
+ end
152
+
153
+ def [](key, options = {})
154
+ get(key, options)
155
+ end
156
+
157
+ def get_bulk(keys, options)
158
+ results = if options[:extended]
159
+ get_bulk_extended(keys)
160
+ else
161
+ client_get_bulk(keys)
162
+ end
163
+
164
+ not_found_error(results.size != keys.size, options)
165
+
166
+ if options[:assemble_hash] || options[:extended]
167
+ results
168
+ else
169
+ ordered_multi_values(keys, results)
170
+ end
171
+ end
172
+
173
+ def async_get(key)
174
+ case key
175
+ when String, Symbol
176
+ meta = { op: :get, key: key }
177
+ future = client.asyncGet(key)
178
+ when Array
179
+ meta = { op: :get }
180
+ future = client.asyncGetBulk(keys)
181
+ when Hash
182
+ # async_get_and_touch(key, options, &block)
183
+ end
184
+ register_future(future, meta, &Proc.new) if block_given?
185
+ end
186
+
187
+ private
188
+
189
+ def expand_get_args(args)
190
+ options = extract_options_hash(args)
191
+ key = args.size == 1 ? args.first : args
192
+
193
+ [key, options]
194
+ end
195
+
196
+ def get_single(key, options)
197
+ if options[:lock]
198
+ client_get_and_lock(key, options)
199
+ elsif options[:extended]
200
+ get_extended(key, options)
201
+ else
202
+ value = if options.key?(:ttl)
203
+ client_get_and_touch(key, options[:ttl])
204
+ else
205
+ client.get(key)
206
+ end
207
+
208
+ not_found_error(value.nil?, options)
209
+ value.nil? ? nil : value
210
+ end
211
+ end
212
+
213
+ def get_extended(key, options = {})
214
+ if options.key?(:lock)
215
+ client_get_and_lock(key, options[:lock])
216
+ end
217
+ extended = client_get_extended(key)
218
+ not_found_error(extended.nil?, options)
219
+ extended
220
+ end
221
+
222
+ def get_and_touch(key, options = {})
223
+ if key.size > 1
224
+ get_bulk_and_touch(key, options)
225
+ else
226
+ key, ttl = key.first
227
+ value = client_get_and_touch(key, ttl)
228
+ not_found_error(value.nil?)
229
+ { key => value }
230
+ end
231
+ end
232
+
233
+ def get_bulk_and_touch(keys, options = {})
234
+ options.merge!(assemble_hash: true)
235
+ results = get_bulk(keys.keys, options)
236
+ touch(keys)
237
+ results.to_hash
238
+ end
239
+
240
+ def get_bulk_extended(keys, options = {})
241
+ {}.tap do |results|
242
+ keys.each do |key|
243
+ results[key] = get_extended(key, options)
244
+ end
245
+ end
246
+ end
247
+
248
+ def ordered_multi_values(keys, results)
249
+ keys.map { |key| results[key] }
250
+ end
251
+
252
+ def client_get_and_touch(key, ttl)
253
+ client.getAndTouch(key, ttl).getValue
254
+ end
255
+
256
+ def client_get_and_lock(key, options)
257
+ lock = options[:lock] == true ? 30 : options[:lock]
258
+ cas = client.getAndLock(key, lock)
259
+ if options[:extended]
260
+ [cas.getValue, nil, cas.getCas]
261
+ else
262
+ cas.getValue
263
+ end
264
+ end
265
+
266
+ def client_get_extended(key)
267
+ cas_value = client.gets(key)
268
+
269
+ if cas_value.nil?
270
+ nil
271
+ else
272
+ [cas_value.getValue, nil, cas_value.getCas]
273
+ end
274
+ end
275
+
276
+ def client_get_bulk(keys)
277
+ client.getBulk(keys)
278
+ rescue java.lang.ClassCastException
279
+ raise TypeError.new
280
+ end
281
+ end
282
+ end
@@ -0,0 +1,26 @@
1
+ module Couchbase::Operations
2
+ module Stats
3
+
4
+ def stats(statname = nil)
5
+ sync_block_error if !async? && block_given?
6
+ stats = if statname.nil?
7
+ client.getStats
8
+ else
9
+ client.getStats(statname)
10
+ end
11
+
12
+ stats = stats.to_hash
13
+
14
+ {}.tap do |hash|
15
+ stats.each_pair do |node, values|
16
+ node_value = node.to_s
17
+ values.each_pair do |stat, value|
18
+ hash[stat] ||= {}
19
+ hash[stat][node_value] = value
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ end
26
+ end