couchbase 3.5.0-x86_64-linux-musl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +202 -0
  3. data/README.md +154 -0
  4. data/ext/extconf.rb +0 -0
  5. data/lib/active_support/cache/couchbase_store.rb +339 -0
  6. data/lib/couchbase/3.1/libcouchbase.so +0 -0
  7. data/lib/couchbase/3.2/libcouchbase.so +0 -0
  8. data/lib/couchbase/3.3/libcouchbase.so +0 -0
  9. data/lib/couchbase/analytics_options.rb +107 -0
  10. data/lib/couchbase/authenticator.rb +64 -0
  11. data/lib/couchbase/binary_collection.rb +128 -0
  12. data/lib/couchbase/binary_collection_options.rb +24 -0
  13. data/lib/couchbase/bucket.rb +144 -0
  14. data/lib/couchbase/cluster.rb +460 -0
  15. data/lib/couchbase/cluster_registry.rb +49 -0
  16. data/lib/couchbase/collection.rb +705 -0
  17. data/lib/couchbase/collection_options.rb +399 -0
  18. data/lib/couchbase/config_profiles.rb +55 -0
  19. data/lib/couchbase/configuration.rb +56 -0
  20. data/lib/couchbase/datastructures/couchbase_list.rb +160 -0
  21. data/lib/couchbase/datastructures/couchbase_map.rb +194 -0
  22. data/lib/couchbase/datastructures/couchbase_queue.rb +134 -0
  23. data/lib/couchbase/datastructures/couchbase_set.rb +128 -0
  24. data/lib/couchbase/datastructures.rb +24 -0
  25. data/lib/couchbase/diagnostics.rb +181 -0
  26. data/lib/couchbase/errors.rb +376 -0
  27. data/lib/couchbase/json_transcoder.rb +39 -0
  28. data/lib/couchbase/key_value_scan.rb +117 -0
  29. data/lib/couchbase/libcouchbase.rb +6 -0
  30. data/lib/couchbase/logger.rb +85 -0
  31. data/lib/couchbase/management/analytics_index_manager.rb +1127 -0
  32. data/lib/couchbase/management/bucket_manager.rb +443 -0
  33. data/lib/couchbase/management/collection_manager.rb +470 -0
  34. data/lib/couchbase/management/collection_query_index_manager.rb +222 -0
  35. data/lib/couchbase/management/query_index_manager.rb +617 -0
  36. data/lib/couchbase/management/scope_search_index_manager.rb +198 -0
  37. data/lib/couchbase/management/search_index_manager.rb +424 -0
  38. data/lib/couchbase/management/user_manager.rb +468 -0
  39. data/lib/couchbase/management/view_index_manager.rb +237 -0
  40. data/lib/couchbase/management.rb +29 -0
  41. data/lib/couchbase/mutation_state.rb +63 -0
  42. data/lib/couchbase/options.rb +2837 -0
  43. data/lib/couchbase/protostellar/binary_collection.rb +55 -0
  44. data/lib/couchbase/protostellar/bucket.rb +51 -0
  45. data/lib/couchbase/protostellar/client.rb +99 -0
  46. data/lib/couchbase/protostellar/cluster.rb +163 -0
  47. data/lib/couchbase/protostellar/collection.rb +152 -0
  48. data/lib/couchbase/protostellar/connect_options.rb +63 -0
  49. data/lib/couchbase/protostellar/error_handling.rb +203 -0
  50. data/lib/couchbase/protostellar/generated/admin/bucket/v1/bucket_pb.rb +61 -0
  51. data/lib/couchbase/protostellar/generated/admin/bucket/v1/bucket_services_pb.rb +35 -0
  52. data/lib/couchbase/protostellar/generated/admin/collection/v1/collection_pb.rb +57 -0
  53. data/lib/couchbase/protostellar/generated/admin/collection/v1/collection_services_pb.rb +36 -0
  54. data/lib/couchbase/protostellar/generated/admin/query/v1/query_pb.rb +61 -0
  55. data/lib/couchbase/protostellar/generated/admin/query/v1/query_services_pb.rb +37 -0
  56. data/lib/couchbase/protostellar/generated/admin/search/v1/search_pb.rb +72 -0
  57. data/lib/couchbase/protostellar/generated/admin/search/v1/search_services_pb.rb +44 -0
  58. data/lib/couchbase/protostellar/generated/analytics/v1/analytics_pb.rb +52 -0
  59. data/lib/couchbase/protostellar/generated/analytics/v1/analytics_services_pb.rb +30 -0
  60. data/lib/couchbase/protostellar/generated/internal/hooks/v1/hooks_pb.rb +70 -0
  61. data/lib/couchbase/protostellar/generated/internal/hooks/v1/hooks_services_pb.rb +36 -0
  62. data/lib/couchbase/protostellar/generated/kv/v1/kv_pb.rb +97 -0
  63. data/lib/couchbase/protostellar/generated/kv/v1/kv_services_pb.rb +46 -0
  64. data/lib/couchbase/protostellar/generated/query/v1/query_pb.rb +57 -0
  65. data/lib/couchbase/protostellar/generated/query/v1/query_services_pb.rb +30 -0
  66. data/lib/couchbase/protostellar/generated/routing/v1/routing_pb.rb +52 -0
  67. data/lib/couchbase/protostellar/generated/routing/v1/routing_services_pb.rb +30 -0
  68. data/lib/couchbase/protostellar/generated/search/v1/search_pb.rb +99 -0
  69. data/lib/couchbase/protostellar/generated/search/v1/search_services_pb.rb +30 -0
  70. data/lib/couchbase/protostellar/generated/transactions/v1/transactions_pb.rb +57 -0
  71. data/lib/couchbase/protostellar/generated/transactions/v1/transactions_services_pb.rb +36 -0
  72. data/lib/couchbase/protostellar/generated/view/v1/view_pb.rb +51 -0
  73. data/lib/couchbase/protostellar/generated/view/v1/view_services_pb.rb +30 -0
  74. data/lib/couchbase/protostellar/generated.rb +9 -0
  75. data/lib/couchbase/protostellar/management/bucket_manager.rb +67 -0
  76. data/lib/couchbase/protostellar/management/collection_manager.rb +94 -0
  77. data/lib/couchbase/protostellar/management/collection_query_index_manager.rb +124 -0
  78. data/lib/couchbase/protostellar/management/query_index_manager.rb +112 -0
  79. data/lib/couchbase/protostellar/management.rb +24 -0
  80. data/lib/couchbase/protostellar/request.rb +78 -0
  81. data/lib/couchbase/protostellar/request_behaviour.rb +42 -0
  82. data/lib/couchbase/protostellar/request_generator/admin/bucket.rb +124 -0
  83. data/lib/couchbase/protostellar/request_generator/admin/collection.rb +94 -0
  84. data/lib/couchbase/protostellar/request_generator/admin/query.rb +130 -0
  85. data/lib/couchbase/protostellar/request_generator/admin.rb +24 -0
  86. data/lib/couchbase/protostellar/request_generator/kv.rb +474 -0
  87. data/lib/couchbase/protostellar/request_generator/query.rb +133 -0
  88. data/lib/couchbase/protostellar/request_generator/search.rb +387 -0
  89. data/lib/couchbase/protostellar/request_generator.rb +26 -0
  90. data/lib/couchbase/protostellar/response_converter/admin/bucket.rb +55 -0
  91. data/lib/couchbase/protostellar/response_converter/admin/collection.rb +42 -0
  92. data/lib/couchbase/protostellar/response_converter/admin/query.rb +59 -0
  93. data/lib/couchbase/protostellar/response_converter/admin.rb +24 -0
  94. data/lib/couchbase/protostellar/response_converter/kv.rb +151 -0
  95. data/lib/couchbase/protostellar/response_converter/query.rb +84 -0
  96. data/lib/couchbase/protostellar/response_converter/search.rb +136 -0
  97. data/lib/couchbase/protostellar/response_converter.rb +26 -0
  98. data/lib/couchbase/protostellar/retry/action.rb +38 -0
  99. data/lib/couchbase/protostellar/retry/orchestrator.rb +60 -0
  100. data/lib/couchbase/protostellar/retry/reason.rb +67 -0
  101. data/lib/couchbase/protostellar/retry/strategies/best_effort.rb +49 -0
  102. data/lib/couchbase/protostellar/retry/strategies.rb +26 -0
  103. data/lib/couchbase/protostellar/retry.rb +28 -0
  104. data/lib/couchbase/protostellar/scope.rb +57 -0
  105. data/lib/couchbase/protostellar/timeout_defaults.rb +30 -0
  106. data/lib/couchbase/protostellar/timeouts.rb +83 -0
  107. data/lib/couchbase/protostellar.rb +29 -0
  108. data/lib/couchbase/query_options.rb +120 -0
  109. data/lib/couchbase/railtie.rb +45 -0
  110. data/lib/couchbase/raw_binary_transcoder.rb +37 -0
  111. data/lib/couchbase/raw_json_transcoder.rb +38 -0
  112. data/lib/couchbase/raw_string_transcoder.rb +40 -0
  113. data/lib/couchbase/scope.rb +256 -0
  114. data/lib/couchbase/search_options.rb +1622 -0
  115. data/lib/couchbase/subdoc.rb +290 -0
  116. data/lib/couchbase/transcoder_flags.rb +62 -0
  117. data/lib/couchbase/utils/generic_logger_adapter.rb +38 -0
  118. data/lib/couchbase/utils/stdlib_logger_adapter.rb +65 -0
  119. data/lib/couchbase/utils/time.rb +69 -0
  120. data/lib/couchbase/utils.rb +21 -0
  121. data/lib/couchbase/version.rb +23 -0
  122. data/lib/couchbase/view_options.rb +65 -0
  123. data/lib/couchbase.rb +28 -0
  124. data/lib/rails/generators/couchbase/config/config_generator.rb +27 -0
  125. metadata +190 -0
@@ -0,0 +1,339 @@
1
+ # Copyright 2020-2021 Couchbase, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require "couchbase"
16
+ require "digest/sha2"
17
+ require "active_support/cache"
18
+
19
+ module ActiveSupport
20
+ module Cache
21
+ # A cache store implementation which stores data in Couchbase: https://couchbase.com
22
+ #
23
+ # * Local cache. Hot in-memory primary cache within block/middleware scope.
24
+ # * +read_multi+ and +write_multi+ support.
25
+ # * +delete_matched+ support using N1QL queries.
26
+ # * +clear+ for erasing whole collection (optionally can flush the bucket).
27
+ #
28
+ # To use this store, add the select it in application config
29
+ #
30
+ # config.cache_store = :couchbase_store, {
31
+ # connection_string: "couchbase://localhost",
32
+ # username: "app_cache_user",
33
+ # password: "s3cret",
34
+ # bucket: "app_cache"
35
+ # }
36
+ #
37
+ # @see https://guides.rubyonrails.org/caching_with_rails.html#cache-stores
38
+ class CouchbaseStore < Store
39
+ MAX_KEY_BYTESIZE = 250
40
+ DEFAULT_ERROR_HANDLER = lambda do |method:, returning:, exception:, logger: CouchbaseStore.logger|
41
+ logger&.error { "CouchbaseStore: #{method} failed, returned #{returning.inspect}: #{exception.class}: #{exception.message}" }
42
+ end
43
+
44
+ # Advertise cache versioning support.
45
+ def self.supports_cache_versioning?
46
+ true
47
+ end
48
+
49
+ prepend Strategy::LocalCache
50
+
51
+ def initialize(options = nil)
52
+ super
53
+ @error_handler = @options.delete(:error_handler) { DEFAULT_ERROR_HANDLER }
54
+ @couchbase_options = {}
55
+ @couchbase_options[:connection_string] =
56
+ @options.delete(:connection_string) do
57
+ raise ArgumentError, "Missing connection string for Couchbase cache store. Use :connection_string in the store options"
58
+ end
59
+ @couchbase_options[:username] =
60
+ @options.delete(:username) do
61
+ raise ArgumentError, "Missing username for Couchbase cache store. Use :username in the store options"
62
+ end
63
+ @couchbase_options[:password] =
64
+ @options.delete(:password) do
65
+ raise ArgumentError, "Missing password for Couchbase cache store. Use :password in the store options"
66
+ end
67
+ @couchbase_options[:bucket] =
68
+ @options.delete(:bucket) { raise ArgumentError, "Missing bucket for Couchbase cache store. Use :bucket in the store options" }
69
+ @couchbase_options[:scope] = @options.delete(:scope) if @options.key?(:scope)
70
+ @couchbase_options[:collection] = @options.delete(:collection) if @options.key?(:collection)
71
+ @last_mutation_token = nil
72
+ end
73
+
74
+ def collection
75
+ @collection ||= build_collection
76
+ end
77
+
78
+ def cluster
79
+ @cluster ||= build_cluster
80
+ end
81
+
82
+ def inspect
83
+ "#<#{self.class} options=#{options.inspect} collection=#{@collection.inspect}>"
84
+ end
85
+
86
+ # Deletes all entries with keys matching the regular expression.
87
+ #
88
+ # The +matcher+ must be valid pattern for N1QL +REGEXP_MATCHES+ function. More info at
89
+ # https://docs.couchbase.com/server/current/n1ql/n1ql-language-reference/patternmatchingfun.html#section_regex_matches
90
+ #
91
+ # Because the operation performed on query engine, and it might take time to propagate changes
92
+ # from key/value engine to the indexer. Therefore the keys, that were created a moment ago
93
+ # might not be deleted.
94
+ #
95
+ # Also this method assumes, that primary index created on the target bucket
96
+ def delete_matched(matcher, _options = nil)
97
+ pattern =
98
+ case matcher
99
+ when Regexp
100
+ matcher.inspect[1..-2]
101
+ when String
102
+ matcher.tr("?", ".").gsub("*", ".*")
103
+ else
104
+ raise NotImplementedError, "Unable to convert #{matcher.inspect} to Regexp pattern"
105
+ end
106
+ operation_options = ::Couchbase::Options::Query(named_parameters: {"pattern" => pattern}, metrics: true)
107
+ operation_options.consistent_with(::Couchbase::MutationState.new(@last_mutation_token)) if @last_mutation_token
108
+ begin
109
+ result = cluster.query("DELETE FROM #{scope_qualifier} cache WHERE REGEXP_MATCHES(META(cache).id, $pattern)", operation_options)
110
+ result.meta_data.metrics.mutation_count
111
+ rescue ::Couchbase::Error::ParsingFailure, ::Couchbase::Error::ServiceNotAvailable
112
+ raise NotImplementedError, "The server does not support delete_matched operation"
113
+ end
114
+ end
115
+
116
+ # Increments an integer value in the cache.
117
+ #
118
+ # Note that it uses binary collection interface, therefore will fail if the value is not
119
+ # represented as ASCII-encoded number using +:raw+.
120
+ def increment(name, amount = 1, expires_in: nil, initial: nil, **options)
121
+ instrument :increment, name, amount: amount do
122
+ failsafe :increment do
123
+ key = normalize_key(name, options)
124
+ res = collection.binary.increment(
125
+ key, ::Couchbase::Options::Increment(delta: amount, expiry: expires_in, initial: initial)
126
+ )
127
+ @last_mutation_token = res.mutation_token
128
+ res.content
129
+ end
130
+ end
131
+ end
132
+
133
+ # Decrements an integer value in the cache.
134
+ #
135
+ # Note that it uses binary collection interface, therefore will fail if the value is not
136
+ # represented as ASCII-encoded number using +:raw+.
137
+ #
138
+ # Note that the counter represented by non-negative number on the server, and it will not
139
+ # cycle to maximum integer when decrementing zero.
140
+ def decrement(name, amount = 1, expires_in: nil, initial: nil, **_options)
141
+ instrument :decrement, name, amount: amount do
142
+ failsafe :decrement do
143
+ key = normalize_key(name, options)
144
+ res = collection.binary.decrement(
145
+ key, ::Couchbase::Options::Decrement(delta: amount, expiry: expires_in, initial: initial)
146
+ )
147
+ @last_mutation_token = res.mutation_token
148
+ res.content
149
+ end
150
+ end
151
+ end
152
+
153
+ # Clears the entire cache. Be careful with this method since it could
154
+ # affect other processes if shared cache is being used.
155
+ #
156
+ # When +use_flush+ option set to +true+ it will flush the bucket. Otherwise, it uses N1QL query
157
+ # and relies on default index.
158
+ def clear(use_flush: false, **_options)
159
+ failsafe(:clear) do
160
+ if use_flush
161
+ cluster.buckets.flush_bucket(@couchbase_options[:bucket_name])
162
+ else
163
+ operation_options = ::Couchbase::Options::Query.new
164
+ operation_options.consistent_with(::Couchbase::MutationState.new(@last_mutation_token)) if @last_mutation_token
165
+ cluster.query("DELETE FROM #{scope_qualifier}", operation_options)
166
+ end
167
+ end
168
+ end
169
+
170
+ private
171
+
172
+ def deserialize_entry(payload, raw: false, **)
173
+ if payload && raw
174
+ Entry.new(payload, compress: false)
175
+ else
176
+ super(payload)
177
+ end
178
+ end
179
+
180
+ def serialize_entry(entry, raw: false, **options)
181
+ if raw
182
+ entry.value.to_s
183
+ else
184
+ super(entry, **options)
185
+ end
186
+ end
187
+
188
+ def serialize_entries(entries, **options)
189
+ entries.transform_values do |entry|
190
+ serialize_entry(entry, **options)
191
+ end
192
+ end
193
+
194
+ # Reads an entry from the cache
195
+ def read_entry(key, **options)
196
+ deserialize_entry(read_serialized_entry(key, **options), **options)
197
+ end
198
+
199
+ def read_serialized_entry(key, **)
200
+ failsafe(:read_entry, returning: nil) do
201
+ res = collection.get(key, ::Couchbase::Options::Get(transcoder: nil))
202
+ res.content
203
+ end
204
+ end
205
+
206
+ # Reads multiple entries from the cache implementation. Subclasses MAY
207
+ # implement this method.
208
+ def read_multi_entries(names, **options)
209
+ return {} if names.empty?
210
+
211
+ keys = names.map { |name| normalize_key(name, options) }
212
+ return_value = {}
213
+ failsafe(:read_multi_entries, returning: return_value) do
214
+ results = collection.get_multi(keys, ::Couchbase::Options::GetMulti(transcoder: nil))
215
+ results.each_with_index do |result, index|
216
+ next unless result.success?
217
+
218
+ entry = deserialize_entry(result.content, raw: options[:raw])
219
+ unless entry.nil? || entry.expired? || entry.mismatched?(normalize_version(names[index], options))
220
+ return_value[names[index]] = entry.value
221
+ end
222
+ end
223
+ return_value
224
+ end
225
+ end
226
+
227
+ # Writes an entry to the cache
228
+ def write_entry(key, entry, raw: false, **options)
229
+ write_serialized_entry(key, serialize_entry(entry, raw: raw, **options), raw: raw, **options)
230
+ end
231
+
232
+ def write_serialized_entry(key, payload, expires_in: nil, race_condition_ttl: nil, raw: false, **)
233
+ if race_condition_ttl && expires_in && expires_in.positive? && !raw
234
+ # Add few minutes to expiry in the future to support race condition TTLs on read
235
+ expires_in += 5.minutes
236
+ end
237
+ failsafe(:write_entry, returning: false) do
238
+ res = collection.upsert(key, payload, ::Couchbase::Options::Upsert(transcoder: nil, expiry: expires_in))
239
+ @last_mutation_token = res.mutation_token
240
+ true
241
+ end
242
+ end
243
+
244
+ def write_multi_entries(entries, **options)
245
+ return 0 if entries.empty?
246
+
247
+ return super if local_cache
248
+
249
+ expires_in = options[:expires_in]
250
+ if options[:race_condition_ttl] && expires_in && expires_in.positive?
251
+ # Add few minutes to expiry in the future to support race condition TTLs on read
252
+ expires_in += 5.minutes
253
+ end
254
+ operation_options = ::Couchbase::Options::UpsertMulti(transcoder: nil, expiry: expires_in)
255
+ failsafe(:write_multi_entries, returning: nil) do
256
+ successful = collection.upsert_multi(serialize_entries(entries, **options), operation_options).select(&:success?)
257
+ return 0 if successful.empty?
258
+
259
+ @last_mutation_token = successful.max_by { |r| r.mutation_token.sequence_number }
260
+ successful.count
261
+ end
262
+ end
263
+
264
+ # Deletes an entry from the cache implementation. Subclasses must
265
+ # implement this method.
266
+ def delete_entry(key, **_options)
267
+ failsafe(:delete_entry, returning: false) do
268
+ res = collection.remove(key)
269
+ @last_mutation_token = res.mutation_token
270
+ true
271
+ end
272
+ end
273
+
274
+ # Deletes multiple entries in the cache. Returns the number of entries deleted.
275
+ def delete_multi_entries(entries, **_options)
276
+ return if entries.empty?
277
+
278
+ failsafe(:delete_multi_entries, returning: nil) do
279
+ successful = collection.remove_multi(entries).select(&:success?)
280
+ return 0 if successful.empty?
281
+
282
+ @last_mutation_token = successful.max_by { |r| r.mutation_token.sequence_number }
283
+ successful.count
284
+ end
285
+ end
286
+
287
+ def failsafe(method, returning: nil)
288
+ yield
289
+ rescue ::Couchbase::Error::CouchbaseError => e
290
+ ActiveSupport.error_reporter&.report(e, handled: true, severity: :warning)
291
+ @error_handler&.call(method: method, exception: e, returning: returning)
292
+ returning
293
+ end
294
+
295
+ # Truncate keys that exceed 250 characters
296
+ def normalize_key(key, options)
297
+ truncate_key super
298
+ end
299
+
300
+ def truncate_key(key)
301
+ if key && key.bytesize > MAX_KEY_BYTESIZE
302
+ suffix = ":sha2:#{::Digest::SHA2.hexdigest(key)}"
303
+ truncate_at = MAX_KEY_BYTESIZE - suffix.bytesize
304
+ "#{key.mb_chars.limit(truncate_at)}#{suffix}"
305
+ else
306
+ key
307
+ end
308
+ end
309
+
310
+ # Connects to the Couchbase cluster
311
+ def build_cluster
312
+ ::Couchbase::Cluster.connect(
313
+ @couchbase_options[:connection_string],
314
+ ::Couchbase::Options::Cluster(authenticator: ::Couchbase::PasswordAuthenticator.new(
315
+ @couchbase_options[:username], @couchbase_options[:password]
316
+ ))
317
+ )
318
+ end
319
+
320
+ # Connects to the Couchbase cluster, opens specified bucket and returns collection object.
321
+ def build_collection
322
+ bucket = cluster.bucket(@couchbase_options[:bucket])
323
+ if @couchbase_options[:scope] && @couchbase_options[:collection]
324
+ bucket.scope(@couchbase_options[:scope]).collection(@couchbase_options[:collection])
325
+ else
326
+ bucket.default_collection
327
+ end
328
+ end
329
+
330
+ def scope_qualifier
331
+ if @couchbase_options[:scope] && @couchbase_options[:collection]
332
+ "`#{@couchbase_options[:bucket]}`.#{@couchbase_options[:scope]}.#{@couchbase_options[:collection]}"
333
+ else
334
+ "`#{@couchbase_options[:bucket]}`"
335
+ end
336
+ end
337
+ end
338
+ end
339
+ end
Binary file
Binary file
Binary file
@@ -0,0 +1,107 @@
1
+ # Copyright 2020-2021 Couchbase, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require "couchbase/json_transcoder"
16
+
17
+ module Couchbase
18
+ class Cluster
19
+ class AnalyticsWarning
20
+ # @return [Integer]
21
+ attr_accessor :code
22
+
23
+ # @return [String]
24
+ attr_accessor :message
25
+
26
+ # @param [Integer] code
27
+ # @param [String] message
28
+ def initialize(code, message)
29
+ @code = code
30
+ @message = message
31
+ end
32
+ end
33
+
34
+ class AnalyticsMetrics
35
+ # @return [Integer] duration in milliseconds
36
+ attr_accessor :elapsed_time
37
+
38
+ # @return [Integer] duration in milliseconds
39
+ attr_accessor :execution_time
40
+
41
+ # @return [Integer]
42
+ attr_accessor :result_count
43
+
44
+ # @return [Integer]
45
+ attr_accessor :result_size
46
+
47
+ # @return [Integer]
48
+ attr_accessor :error_count
49
+
50
+ # @return [Integer]
51
+ attr_accessor :processed_objects
52
+
53
+ # @return [Integer]
54
+ attr_accessor :warning_count
55
+
56
+ # @yieldparam [AnalyticsMetrics] self
57
+ def initialize
58
+ yield self if block_given?
59
+ end
60
+ end
61
+
62
+ class AnalyticsMetaData
63
+ # @return [String]
64
+ attr_accessor :request_id
65
+
66
+ # @return [String]
67
+ attr_accessor :client_context_id
68
+
69
+ # @return [:running, :success, :errors, :completed, :stopped, :timeout, :closed, :fatal, :aborted, :unknown]
70
+ attr_accessor :status
71
+
72
+ # @return [Hash] returns the signature as returned by the query engine which is then decoded as JSON object
73
+ attr_accessor :signature
74
+
75
+ # @return [Array<AnalyticsWarning>]
76
+ attr_accessor :warnings
77
+
78
+ # @return [AnalyticsMetrics]
79
+ attr_accessor :metrics
80
+
81
+ # @yieldparam [AnalyticsMetaData] self
82
+ def initialize
83
+ yield self if block_given?
84
+ end
85
+ end
86
+
87
+ class AnalyticsResult
88
+ # @return [AnalyticsMetaData]
89
+ attr_accessor :meta_data
90
+
91
+ attr_accessor :transcoder
92
+
93
+ # Returns all rows converted using a transcoder
94
+ #
95
+ # @return [Array]
96
+ def rows(transcoder = self.transcoder)
97
+ @rows.lazy.map { |row| transcoder.decode(row, 0) }
98
+ end
99
+
100
+ # @yieldparam [AnalyticsResult] self
101
+ def initialize
102
+ @transcoder = JsonTranscoder.new
103
+ yield self if block_given?
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,64 @@
1
+ # Copyright 2020-2021 Couchbase, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Couchbase
16
+ # Authenticator for username/password credentials
17
+ class PasswordAuthenticator
18
+ DEFAULT_SASL_MECHANISMS = [:scram_sha512, :scram_sha256, :scram_sha1].freeze
19
+
20
+ attr_accessor :username
21
+ attr_accessor :password
22
+ attr_accessor :allowed_sasl_mechanisms
23
+
24
+ # Creates a new password authenticator with the default settings.
25
+ #
26
+ # @param [String] password the username to use for all authentication requests
27
+ # @param [String] username the password
28
+ def initialize(username, password)
29
+ @username = username
30
+ @password = password
31
+ end
32
+
33
+ # Creates a LDAP compatible password authenticator which is INSECURE if not used with TLS.
34
+ #
35
+ # Please note that this is INSECURE and will leak user credentials on the wire to eavesdroppers. This should
36
+ # only be enabled in trusted environments.
37
+ #
38
+ # @param [String] username the username to use for all authentication.
39
+ # @param [String] password the password to use alongside the username.
40
+ # @return [PasswordAuthenticator]
41
+ def self.ldap_compatible(username, password)
42
+ new(username, password).tap do |auth|
43
+ auth.allowed_sasl_mechanisms = [:plain]
44
+ end
45
+ end
46
+ end
47
+
48
+ # Authenticator for TLS client certificate
49
+ #
50
+ # @see https://docs.couchbase.com/server/current/manage/manage-security/configure-client-certificates.html
51
+ class CertificateAuthenticator
52
+ attr_accessor :certificate_path
53
+ attr_accessor :key_path
54
+
55
+ # Creates a new authenticator with certificate and key paths
56
+ #
57
+ # @param [String] certificate_path path to certificate
58
+ # @param [String] key_path path to private key
59
+ def initialize(certificate_path, key_path)
60
+ @certificate_path = certificate_path
61
+ @key_path = key_path
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,128 @@
1
+ # Copyright 2020-2021 Couchbase, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require "couchbase/options"
16
+ require "couchbase/binary_collection_options"
17
+
18
+ module Couchbase
19
+ # Allows to perform certain operations on non-JSON documents.
20
+ class BinaryCollection
21
+ alias inspect to_s
22
+
23
+ # @param [Couchbase::Collection] collection parent collection
24
+ def initialize(collection)
25
+ @collection = collection
26
+ @backend = collection.instance_variable_get(:@backend)
27
+ end
28
+
29
+ # Appends binary content to the document
30
+ #
31
+ # @param [String] id the document id which is used to uniquely identify it
32
+ # @param [String] content the binary content to append to the document
33
+ # @param [Options::Append] options custom options to customize the request
34
+ #
35
+ # @example Append "bar" to the content of the existing document
36
+ # collection.upsert("mydoc", "foo")
37
+ # collection.binary.append("mydoc", "bar", Options::Append(timeout: 3_000))
38
+ # collection.get("mydoc", Options::Get(transcoder: nil)).content #=> "foobar"
39
+ #
40
+ # @return [Collection::MutationResult]
41
+ def append(id, content, options = Options::Append::DEFAULT)
42
+ resp = @backend.document_append(@collection.bucket_name, @collection.scope_name, @collection.name,
43
+ id, content, options.to_backend)
44
+ Collection::MutationResult.new do |res|
45
+ res.cas = resp[:cas]
46
+ res.mutation_token = @collection.send(:extract_mutation_token, resp)
47
+ end
48
+ end
49
+
50
+ # Prepends binary content to the document
51
+ #
52
+ # @param [String] id the document id which is used to uniquely identify it
53
+ # @param [String] content the binary content to prepend to the document
54
+ # @param [Options::Prepend] options custom options to customize the request
55
+ #
56
+ # @example Prepend "bar" to the content of the existing document
57
+ # collection.upsert("mydoc", "foo")
58
+ # collection.binary.prepend("mydoc", "bar", Options::Prepend(timeout: 3_000))
59
+ # collection.get("mydoc", Options::Get(transcoder: nil)).content #=> "barfoo"
60
+ #
61
+ # @return [Collection::MutationResult]
62
+ def prepend(id, content, options = Options::Prepend::DEFAULT)
63
+ resp = @backend.document_prepend(@collection.bucket_name, @collection.scope_name, @collection.name,
64
+ id, content, options.to_backend)
65
+ Collection::MutationResult.new do |res|
66
+ res.cas = resp[:cas]
67
+ res.mutation_token = @collection.send(:extract_mutation_token, resp)
68
+ end
69
+ end
70
+
71
+ # Increments the counter document by one of the number defined in the options
72
+ #
73
+ # @param [String] id the document id which is used to uniquely identify it
74
+ # @param [Options::Increment] options custom options to customize the request
75
+ #
76
+ # @example Increment value by 10, and initialize to 0 if it does not exist
77
+ # res = collection.binary.increment("raw_counter", Options::Increment(delta: 10, initial: 0))
78
+ # res.content #=> 0
79
+ # res = collection.binary.increment("raw_counter", Options::Increment(delta: 10, initial: 0))
80
+ # res.content #=> 10
81
+ #
82
+ # @return [CounterResult]
83
+ def increment(id, options = Options::Increment::DEFAULT)
84
+ resp = @backend.document_increment(@collection.bucket_name, @collection.scope_name, @collection.name, id,
85
+ options.to_backend)
86
+ CounterResult.new do |res|
87
+ res.cas = resp[:cas]
88
+ res.content = resp[:content]
89
+ res.mutation_token = @collection.send(:extract_mutation_token, resp)
90
+ end
91
+ end
92
+
93
+ # Decrements the counter document by one of the number defined in the options
94
+ #
95
+ # @param [String] id the document id which is used to uniquely identify it
96
+ # @param [Options::Decrement] options custom options to customize the request
97
+ #
98
+ # @example Decrement value by 2, and initialize to 100 if it does not exist
99
+ # res = collection.binary.decrement("raw_counter", Options::Decrement(delta: 2, initial: 100))
100
+ # res.value #=> 100
101
+ # res = collection.binary.decrement("raw_counter", Options::Decrement(delta: 2, initial: 100))
102
+ # res.value #=> 98
103
+ #
104
+ # @return [CounterResult]
105
+ def decrement(id, options = Options::Decrement::DEFAULT)
106
+ resp = @backend.document_decrement(@collection.bucket_name, @collection.scope_name, @collection.name, id,
107
+ options.to_backend)
108
+ CounterResult.new do |res|
109
+ res.cas = resp[:cas]
110
+ res.content = resp[:content]
111
+ res.mutation_token = @collection.send(:extract_mutation_token, resp)
112
+ end
113
+ end
114
+
115
+ # @api private
116
+ # TODO: deprecate in 3.1
117
+ AppendOptions = ::Couchbase::Options::Append
118
+ # @api private
119
+ # TODO: deprecate in 3.1
120
+ PrependOptions = ::Couchbase::Options::Prepend
121
+ # @api private
122
+ # TODO: deprecate in 3.1
123
+ IncrementOptions = ::Couchbase::Options::Increment
124
+ # @api private
125
+ # TODO: deprecate in 3.1
126
+ DecrementOptions = ::Couchbase::Options::Decrement
127
+ end
128
+ end
@@ -0,0 +1,24 @@
1
+ # Copyright 2020-2021 Couchbase, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require "couchbase/collection_options"
16
+
17
+ module Couchbase
18
+ class BinaryCollection
19
+ class CounterResult < ::Couchbase::Collection::MutationResult
20
+ # @return [Integer] current value of the counter
21
+ attr_accessor :content
22
+ end
23
+ end
24
+ end