couchbase 3.8.1-aarch64-linux → 3.9.0-aarch64-linux

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 (35) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/lib/active_support/cache/couchbase_store.rb +77 -12
  4. data/lib/couchbase/3.2/libcouchbase.so +0 -0
  5. data/lib/couchbase/3.3/libcouchbase.so +0 -0
  6. data/lib/couchbase/3.4/libcouchbase.so +0 -0
  7. data/lib/couchbase/4.0/libcouchbase.so +0 -0
  8. data/lib/couchbase/bucket.rb +20 -0
  9. data/lib/couchbase/cluster.rb +33 -14
  10. data/lib/couchbase/collection.rb +36 -1
  11. data/lib/couchbase/errors.rb +18 -0
  12. data/lib/couchbase/fork_hooks.rb +16 -7
  13. data/lib/couchbase/get_replica_strategy.rb +89 -0
  14. data/lib/couchbase/logger.rb +1 -1
  15. data/lib/couchbase/management/analytics_index_manager.rb +15 -15
  16. data/lib/couchbase/management/bucket_manager.rb +6 -6
  17. data/lib/couchbase/management/collection_manager.rb +6 -6
  18. data/lib/couchbase/management/query_index_manager.rb +7 -7
  19. data/lib/couchbase/management/search_index_manager.rb +13 -13
  20. data/lib/couchbase/management/user_manager.rb +10 -10
  21. data/lib/couchbase/management/view_index_manager.rb +5 -5
  22. data/lib/couchbase/options.rb +181 -44
  23. data/lib/couchbase/protostellar/bucket.rb +4 -0
  24. data/lib/couchbase/protostellar/cluster.rb +4 -0
  25. data/lib/couchbase/protostellar/collection.rb +4 -0
  26. data/lib/couchbase/protostellar/error_handling.rb +2 -1
  27. data/lib/couchbase/protostellar/request.rb +1 -0
  28. data/lib/couchbase/protostellar/request_generator/kv.rb +16 -2
  29. data/lib/couchbase/protostellar/request_generator/search.rb +17 -1
  30. data/lib/couchbase/protostellar/retry/orchestrator.rb +3 -2
  31. data/lib/couchbase/protostellar/retry/strategies/fail_fast.rb +33 -0
  32. data/lib/couchbase/protostellar/retry/strategies.rb +1 -0
  33. data/lib/couchbase/search_options.rb +95 -6
  34. data/lib/couchbase/version.rb +1 -1
  35. metadata +7 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6a145852bb94555177f45760a9eb43d15953c2b8e74193ea6e07a81b0b2dec70
4
- data.tar.gz: d3d12e4d879c3538c232fe3a0a07b130951e9eb88ce4b43f0b2b1c45707ce641
3
+ metadata.gz: 5a4d838edd719c54da2b7b0cc4775238c38dbf42fded0ea7ea15c664bac5f875
4
+ data.tar.gz: d1bd00c3504a9c16408aafb7342b1a8e245ec0207098cb891fcf0578f37b5c74
5
5
  SHA512:
6
- metadata.gz: 538f5da7c18ae5c855ce376b153f7c07f666d6e799b00dd94712d79192844d425144f164ccf94c17a1c717a1bc6bcbd9fb21e0480fbf16c7ebf353c6b8868608
7
- data.tar.gz: d112f017ed44924962c9880a0c43a223c81ea04cd2df4869b7a606bab19bd07e5ef372ccc2c4acd76f1aa9e8755f9e6094c1afe4131d122816157d0dce65c0c9
6
+ metadata.gz: 74f8ddc4fc9b7e91080832a29b996552571414919182ad94eea896ba5475b9054e5ad805e1766203f0c0c4eff867411581962ccfa6ec0e6f864f6ccaef29ecbc
7
+ data.tar.gz: 82ecd27fa9fd9241069ba96b0edff6ea6f6bff27ddb8215c62a560ee7acc874c3dad06b6e794bd77b1293e222da76139ed2ef592315d49a8a047f2563ce67e66
data/README.md CHANGED
@@ -9,7 +9,7 @@ This repository contains the third generation of the official Couchbase SDK for
9
9
 
10
10
  ## Support and Feedback
11
11
 
12
- If you find an issue, please file it in [our JIRA issue tracker](https://jira.issues.couchbase.com/browse/RCBC). Also you are
12
+ Issues are tracked on [our JIRA issue tracker](https://jira.issues.couchbase.com/browse/RCBC). If you find an issue, you can report it by [opening an issue on GitHub](https://github.com/couchbase/couchbase-ruby-client/issues). Also, you are
13
13
  always welcome on [our forum](https://forums.couchbase.com/c/ruby-sdk) and [Discord](https://discord.com/invite/sQ5qbPZuTh).
14
14
 
15
15
  Please attach version information to the ticket/post. To obtain this information, use the following command:
@@ -23,7 +23,7 @@ The library has been tested with MRI 3.2, 3.3, 3.4 and 4.0. Supported platforms
23
23
  Add this line to your application's Gemfile:
24
24
 
25
25
  ```ruby
26
- gem "couchbase", "3.8.1"
26
+ gem "couchbase", "3.9.0"
27
27
  ```
28
28
 
29
29
  And then execute:
@@ -36,6 +36,13 @@ module ActiveSupport
36
36
  # bucket: "app_cache"
37
37
  # }
38
38
  #
39
+ # +delete_matched+ and +clear+ query with +consistent_with+ the store's writes.
40
+ # By default that covers the last write only, which leaves earlier writes to
41
+ # other vBuckets out of the query until the index catches up. With
42
+ # +mutation_tracking: :all+ the store keeps the newest mutation token of every
43
+ # vBucket it wrote to, so both see every earlier write. It also accepts an
44
+ # object that responds to +record(*tokens)+ and +mutation_state+.
45
+ #
39
46
  # @see https://guides.rubyonrails.org/caching_with_rails.html#cache-stores
40
47
  class CouchbaseStore < Store
41
48
  MAX_KEY_BYTESIZE = 250
@@ -43,6 +50,51 @@ module ActiveSupport
43
50
  logger&.error { "CouchbaseStore: #{method} failed, returned #{returning.inspect}: #{exception.class}: #{exception.message}" }
44
51
  end
45
52
 
53
+ # Default +mutation_tracking+: the token of the last write.
54
+ class LastMutation
55
+ def initialize
56
+ @token = nil
57
+ end
58
+
59
+ def record(*tokens)
60
+ latest = tokens.compact.max_by(&:sequence_number)
61
+ @token = latest if latest
62
+ end
63
+
64
+ def mutation_state
65
+ token = @token
66
+ token && ::Couchbase::MutationState.new(token)
67
+ end
68
+ end
69
+
70
+ # +mutation_tracking: :all+: the newest token of every vBucket written to,
71
+ # at most one per vBucket however many writes there were.
72
+ class AllMutations
73
+ def initialize
74
+ @tokens = {}
75
+ @lock = Mutex.new
76
+ end
77
+
78
+ def record(*tokens)
79
+ @lock.synchronize do
80
+ tokens.compact.each do |token|
81
+ key = [token.bucket_name, token.partition_id]
82
+ known = @tokens[key]
83
+ # After a failover the partition_uuid changes and sequence numbers
84
+ # do not compare across it, so the token recorded last is kept.
85
+ next if known && known.partition_uuid == token.partition_uuid && known.sequence_number >= token.sequence_number
86
+
87
+ @tokens[key] = token
88
+ end
89
+ end
90
+ end
91
+
92
+ def mutation_state
93
+ tokens = @lock.synchronize { @tokens.values }
94
+ ::Couchbase::MutationState.new(*tokens) unless tokens.empty?
95
+ end
96
+ end
97
+
46
98
  # Advertise cache versioning support.
47
99
  def self.supports_cache_versioning?
48
100
  true
@@ -70,7 +122,17 @@ module ActiveSupport
70
122
  @options.delete(:bucket) { raise ArgumentError, "Missing bucket for Couchbase cache store. Use :bucket in the store options" }
71
123
  @couchbase_options[:scope] = @options.delete(:scope) if @options.key?(:scope)
72
124
  @couchbase_options[:collection] = @options.delete(:collection) if @options.key?(:collection)
73
- @last_mutation_token = nil
125
+ @mutations =
126
+ case (tracking = @options.delete(:mutation_tracking) { :last })
127
+ when :last, "last" then LastMutation.new
128
+ when :all, "all" then AllMutations.new
129
+ else
130
+ unless tracking.respond_to?(:record) && tracking.respond_to?(:mutation_state)
131
+ raise ArgumentError, "mutation_tracking must be :last, :all, or respond to #record and #mutation_state"
132
+ end
133
+
134
+ tracking
135
+ end
74
136
  end
75
137
 
76
138
  def collection
@@ -90,9 +152,10 @@ module ActiveSupport
90
152
  # The +matcher+ must be valid pattern for N1QL +REGEXP_MATCHES+ function. More info at
91
153
  # https://docs.couchbase.com/server/current/n1ql/n1ql-language-reference/patternmatchingfun.html#section_regex_matches
92
154
  #
93
- # Because the operation performed on query engine, and it might take time to propagate changes
94
- # from key/value engine to the indexer. Therefore the keys, that were created a moment ago
95
- # might not be deleted.
155
+ # The query is consistent with the writes this store recorded, as selected by
156
+ # +mutation_tracking+. With the default +:last+, keys written shortly before the
157
+ # last write to other vBuckets might not be deleted. Writes by other processes
158
+ # are not covered.
96
159
  #
97
160
  # Also this method assumes, that primary index created on the target bucket
98
161
  def delete_matched(matcher, _options = nil)
@@ -106,7 +169,8 @@ module ActiveSupport
106
169
  raise NotImplementedError, "Unable to convert #{matcher.inspect} to Regexp pattern"
107
170
  end
108
171
  operation_options = ::Couchbase::Options::Query(named_parameters: {"pattern" => pattern}, metrics: true)
109
- operation_options.consistent_with(::Couchbase::MutationState.new(@last_mutation_token)) if @last_mutation_token
172
+ mutation_state = @mutations.mutation_state
173
+ operation_options.consistent_with(mutation_state) if mutation_state
110
174
  begin
111
175
  result = cluster.query("DELETE FROM #{scope_qualifier} cache_store_ WHERE REGEXP_MATCHES(META(cache_store_).id, $pattern)",
112
176
  operation_options)
@@ -127,7 +191,7 @@ module ActiveSupport
127
191
  res = collection.binary.increment(
128
192
  key, ::Couchbase::Options::Increment(delta: amount, expiry: expires_in, initial: initial)
129
193
  )
130
- @last_mutation_token = res.mutation_token
194
+ @mutations.record(res.mutation_token)
131
195
  res.content
132
196
  end
133
197
  end
@@ -147,7 +211,7 @@ module ActiveSupport
147
211
  res = collection.binary.decrement(
148
212
  key, ::Couchbase::Options::Decrement(delta: amount, expiry: expires_in, initial: initial)
149
213
  )
150
- @last_mutation_token = res.mutation_token
214
+ @mutations.record(res.mutation_token)
151
215
  res.content
152
216
  end
153
217
  end
@@ -164,7 +228,8 @@ module ActiveSupport
164
228
  cluster.buckets.flush_bucket(@couchbase_options[:bucket_name])
165
229
  else
166
230
  operation_options = ::Couchbase::Options::Query.new
167
- operation_options.consistent_with(::Couchbase::MutationState.new(@last_mutation_token)) if @last_mutation_token
231
+ mutation_state = @mutations.mutation_state
232
+ operation_options.consistent_with(mutation_state) if mutation_state
168
233
  cluster.query("DELETE FROM #{scope_qualifier}", operation_options)
169
234
  end
170
235
  end
@@ -239,7 +304,7 @@ module ActiveSupport
239
304
  end
240
305
  failsafe(:write_entry, returning: false) do
241
306
  res = collection.upsert(key, payload, ::Couchbase::Options::Upsert(transcoder: nil, expiry: expires_in))
242
- @last_mutation_token = res.mutation_token
307
+ @mutations.record(res.mutation_token)
243
308
  true
244
309
  end
245
310
  end
@@ -259,7 +324,7 @@ module ActiveSupport
259
324
  successful = collection.upsert_multi(serialize_entries(entries, **options), operation_options).select(&:success?)
260
325
  return 0 if successful.empty?
261
326
 
262
- @last_mutation_token = successful.max_by { |r| r.mutation_token.sequence_number }
327
+ @mutations.record(*successful.map(&:mutation_token))
263
328
  successful.count
264
329
  end
265
330
  end
@@ -269,7 +334,7 @@ module ActiveSupport
269
334
  def delete_entry(key, **_options)
270
335
  failsafe(:delete_entry, returning: false) do
271
336
  res = collection.remove(key)
272
- @last_mutation_token = res.mutation_token
337
+ @mutations.record(res.mutation_token)
273
338
  true
274
339
  end
275
340
  end
@@ -282,7 +347,7 @@ module ActiveSupport
282
347
  successful = collection.remove_multi(entries).select(&:success?)
283
348
  return 0 if successful.empty?
284
349
 
285
- @last_mutation_token = successful.max_by { |r| r.mutation_token.sequence_number }
350
+ @mutations.record(*successful.map(&:mutation_token))
286
351
  successful.count
287
352
  end
288
353
  end
Binary file
Binary file
Binary file
Binary file
@@ -149,5 +149,25 @@ module Couchbase
149
149
  end
150
150
  end
151
151
  end
152
+
153
+ # Waits until the bucket reaches the desired state, actively pinging its services
154
+ #
155
+ # With +:online+, the wait also requires the bucket's vbucket map to be placed: every vbucket has its active copy
156
+ # and each replica the data nodes can hold assigned to a node. +:degraded+ only pings.
157
+ #
158
+ # +Thread#raise+ does not interrupt the wait. It ends on success, on +timeout+, or when the cluster is disconnected.
159
+ #
160
+ # @param [Integer, #in_milliseconds] timeout the maximum time to wait
161
+ # @param [Options::WaitUntilReady] options
162
+ #
163
+ # @return [void]
164
+ #
165
+ # @raise [Error::UnambiguousTimeout] if the desired state is not reached within +timeout+
166
+ # @raise [Error::ClusterClosed] if the cluster has been disconnected
167
+ # @raise [Error::InvalidArgument] if +timeout+ is negative or longer than 365 days, or +options+ name an
168
+ # unsupported desired state or service type
169
+ def wait_until_ready(timeout, options = Options::WaitUntilReady::DEFAULT)
170
+ @backend.wait_until_ready(@name, Utils::Time.extract_duration(timeout), options.to_backend)
171
+ end
152
172
  end
153
173
  end
@@ -326,26 +326,45 @@ module Couchbase
326
326
  #
327
327
  # @return [PingResult]
328
328
  def ping(options = Options::Ping::DEFAULT)
329
- resp = @backend.ping(nil, options.to_backend)
330
- PingResult.new do |res|
331
- res.version = resp[:version]
332
- res.id = resp[:id]
333
- res.sdk = resp[:sdk]
334
- resp[:services].each do |type, svcs|
335
- res.services[type] = svcs.map do |svc|
336
- PingResult::ServiceInfo.new do |info|
337
- info.id = svc[:id]
338
- info.state = svc[:state]
339
- info.latency = svc[:latency]
340
- info.remote = svc[:remote]
341
- info.local = svc[:local]
342
- info.error = svc[:error]
329
+ @observability.record_operation(Observability::OP_PING, options.parent_span, self) do |_obs_handler|
330
+ resp = @backend.ping(nil, options.to_backend)
331
+ PingResult.new do |res|
332
+ res.version = resp[:version]
333
+ res.id = resp[:id]
334
+ res.sdk = resp[:sdk]
335
+ resp[:services].each do |type, svcs|
336
+ res.services[type] = svcs.map do |svc|
337
+ PingResult::ServiceInfo.new do |info|
338
+ info.id = svc[:id]
339
+ info.state = svc[:state]
340
+ info.latency = svc[:latency]
341
+ info.remote = svc[:remote]
342
+ info.local = svc[:local]
343
+ info.error = svc[:error]
344
+ end
343
345
  end
344
346
  end
345
347
  end
346
348
  end
347
349
  end
348
350
 
351
+ # Waits until the cluster reaches the desired state, actively pinging its services
352
+ #
353
+ # +Thread#raise+ does not interrupt the wait. It ends on success, on +timeout+, or when the cluster is disconnected.
354
+ #
355
+ # @param [Integer, #in_milliseconds] timeout the maximum time to wait
356
+ # @param [Options::WaitUntilReady] options
357
+ #
358
+ # @return [void]
359
+ #
360
+ # @raise [Error::UnambiguousTimeout] if the desired state is not reached within +timeout+
361
+ # @raise [Error::ClusterClosed] if the cluster has been disconnected
362
+ # @raise [Error::InvalidArgument] if +timeout+ is negative or longer than 365 days, or +options+ name an
363
+ # unsupported desired state or service type
364
+ def wait_until_ready(timeout, options = Options::WaitUntilReady::DEFAULT)
365
+ @backend.wait_until_ready(nil, Utils::Time.extract_duration(timeout), options.to_backend)
366
+ end
367
+
349
368
  private
350
369
 
351
370
  # Initialize {Cluster} object
@@ -18,6 +18,7 @@ require "couchbase/errors"
18
18
  require "couchbase/collection_options"
19
19
  require "couchbase/binary_collection"
20
20
  require "couchbase/key_value_scan"
21
+ require "couchbase/get_replica_strategy"
21
22
 
22
23
  module Couchbase
23
24
  # Provides access to all collection APIs
@@ -203,6 +204,40 @@ module Couchbase
203
204
  end
204
205
  end
205
206
 
207
+ # Reads the document from the replica the strategy selects.
208
+ #
209
+ # @param [String] id the document id which is used to uniquely identify it.
210
+ # @param [GetReplicaStrategy] strategy selects the replica to read from
211
+ # @param [Options::GetReplica] options request customization
212
+ #
213
+ # @example Read the document from the second replica
214
+ # res = collection.get_replica("airline_10", GetReplicaStrategy.from_index(:second))
215
+ # res.replica? #=> true
216
+ # res.content["name"]
217
+ #
218
+ # @raise [Error::DocumentNotFoundOnReplica] if the replica does not hold the document
219
+ # @raise [Error::ReplicaIndexOutOfBounds] if the bucket is not configured with the requested replica
220
+ # @raise [Error::ReplicaIndexCurrentlyUnavailable] if the vbucket map places the requested replica on no node
221
+ # @raise [Error::UnambiguousTimeout] if the replica does not answer before the timeout
222
+ # @raise [Error::FeatureNotAvailable] over +couchbase2://+, which does not carry the operation
223
+ #
224
+ # @since 3.9.0
225
+ #
226
+ # @return [GetReplicaResult]
227
+ def get_replica(id, strategy, options = Options::GetReplica::DEFAULT)
228
+ @observability.record_operation(Observability::OP_GET_REPLICA, options.parent_span, self, :kv) do |obs_handler|
229
+ resp = @backend.document_get_replica(@bucket_name, @scope_name, @name, id, strategy.to_backend,
230
+ options.to_backend, obs_handler)
231
+ GetReplicaResult.new do |res|
232
+ res.transcoder = options.transcoder
233
+ res.cas = resp[:cas]
234
+ res.flags = resp[:flags]
235
+ res.encoded = resp[:content]
236
+ res.is_replica = true
237
+ end
238
+ end
239
+ end
240
+
206
241
  # Reads all available replicas and active, and returns the first found.
207
242
  #
208
243
  # @param [String] id the document id which is used to uniquely identify it.
@@ -210,7 +245,7 @@ module Couchbase
210
245
  #
211
246
  # @example Get document contents
212
247
  # res = collection.get_any_replica("customer123")
213
- # res.is_active #=> false
248
+ # res.replica? #=> true when a replica answered first, false for the active copy
214
249
  # res.content["addresses"]
215
250
  #
216
251
  # # {"billing"=>
@@ -185,6 +185,24 @@ module Couchbase
185
185
  class DocumentNotFound < CouchbaseError
186
186
  end
187
187
 
188
+ # Indicates that the replica selected by {Collection#get_replica} does not hold the document.
189
+ #
190
+ # @since 3.9.0
191
+ class DocumentNotFoundOnReplica < DocumentNotFound
192
+ end
193
+
194
+ # Indicates that {Collection#get_replica} requested a replica the bucket is not configured with.
195
+ #
196
+ # @since 3.9.0
197
+ class ReplicaIndexOutOfBounds < CouchbaseError
198
+ end
199
+
200
+ # Indicates that {Collection#get_replica} requested a configured replica. The vbucket map places it on no node.
201
+ #
202
+ # @since 3.9.0
203
+ class ReplicaIndexCurrentlyUnavailable < CouchbaseError
204
+ end
205
+
188
206
  # Indicates an operation completed but no successful document was retrievable.
189
207
  class DocumentIrretrievable < CouchbaseError
190
208
  end
@@ -17,14 +17,23 @@
17
17
  module Couchbase
18
18
  module ForkHooks
19
19
  def _fork
20
- Couchbase::Backend.notify_fork(:prepare)
21
- pid = super
22
- if pid
23
- Couchbase::Backend.notify_fork(:parent)
24
- else
25
- Couchbase::Backend.notify_fork(:child)
20
+ # :prepare stops the instances and only :parent or :child restarts them, so an asynchronous
21
+ # exception is deferred everywhere except inside the fork itself.
22
+ Thread.handle_interrupt(Object => :never) do
23
+ parent_pid = Process.pid
24
+ Couchbase::Backend.notify_fork(:prepare)
25
+ begin
26
+ Thread.handle_interrupt(Object => :immediate) do
27
+ # A check point: an interrupt deferred during :prepare lands here, before the fork.
28
+ Thread.pass
29
+ super
30
+ end
31
+ ensure
32
+ # Decided by pid rather than by the return value, which an exception raised after the fork
33
+ # never delivers.
34
+ Couchbase::Backend.notify_fork(Process.pid == parent_pid ? :parent : :child)
35
+ end
26
36
  end
27
- pid
28
37
  end
29
38
  end
30
39
  end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2026. Couchbase, Inc.
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
+ require "couchbase/errors"
18
+
19
+ module Couchbase
20
+ # Selects the replica that {Collection#get_replica} reads from.
21
+ #
22
+ # @since 3.9.0
23
+ class GetReplicaStrategy
24
+ REPLICA_INDEXES = {first: 0, second: 1, third: 2}.freeze
25
+ private_constant :REPLICA_INDEXES
26
+
27
+ # @return [Symbol] the requested replica, one of +:first+, +:second+ or +:third+
28
+ attr_reader :index
29
+
30
+ # @return [Boolean] whether an index that cannot be read resolves to the next replica that can
31
+ attr_reader :wrap
32
+
33
+ private_class_method :new
34
+
35
+ # Selects the replica at the given index.
36
+ #
37
+ # Without +wrap+, the SDK resolves the index against the vbucket map it already holds. No network round trip
38
+ # is made for these two errors:
39
+ # * an index at or beyond the bucket's configured replica count raises {Error::ReplicaIndexOutOfBounds}
40
+ # * a configured replica the vbucket map places on no node raises {Error::ReplicaIndexCurrentlyUnavailable}
41
+ #
42
+ # The replica is chosen from the vbucket map, not from node health. A replica on a node that is down is still
43
+ # chosen. The read can then wait for that node until the read times out.
44
+ #
45
+ # @param [Symbol] index the replica to read from, one of +:first+, +:second+ or +:third+
46
+ # @param [Boolean] wrap if +true+, an unreadable index moves to the next readable replica. The walk starts at the
47
+ # index modulo the configured replica count. A bucket configured without replicas still raises
48
+ # {Error::ReplicaIndexOutOfBounds}. If no replica is readable, it still raises
49
+ # {Error::ReplicaIndexCurrentlyUnavailable}.
50
+ #
51
+ # @raise [Error::InvalidArgument] if +index+ is not one of the supported symbols, or +wrap+ is not a Boolean
52
+ #
53
+ # @example Read the first replica, or the next readable one
54
+ # collection.get_replica("airline_10", GetReplicaStrategy.from_index(:first, wrap: true))
55
+ #
56
+ # @example Bound the wait for a replica whose node is down, then read any copy
57
+ # begin
58
+ # collection.get_replica("airline_10", GetReplicaStrategy.from_index(:first, wrap: true),
59
+ # Options::GetReplica(timeout: 500))
60
+ # rescue Error::UnambiguousTimeout
61
+ # collection.get_any_replica("airline_10")
62
+ # end
63
+ #
64
+ # @return [GetReplicaStrategy]
65
+ def self.from_index(index, wrap: false)
66
+ unless REPLICA_INDEXES.key?(index)
67
+ raise Error::InvalidArgument, "replica index must be one of #{REPLICA_INDEXES.keys.inspect}, but given #{index.inspect}"
68
+ end
69
+ raise Error::InvalidArgument, "wrap must be a Boolean, but given #{wrap.inspect}" unless [true, false].include?(wrap)
70
+
71
+ new(index, wrap)
72
+ end
73
+
74
+ # @api private
75
+ def initialize(index, wrap)
76
+ @index = index
77
+ @wrap = wrap
78
+ freeze
79
+ end
80
+
81
+ # @api private
82
+ def to_backend
83
+ {
84
+ replica_index: REPLICA_INDEXES.fetch(@index),
85
+ wrap: @wrap,
86
+ }
87
+ end
88
+ end
89
+ end
@@ -69,7 +69,7 @@ module Couchbase
69
69
  def self.set_logger(logger, adapter_class: nil, verbose: false, level: :info)
70
70
  @logger = logger # rubocop:disable ThreadSafety/ClassInstanceVariable
71
71
  if @logger.nil? # rubocop:disable ThreadSafety/ClassInstanceVariable
72
- Backend.install_logger_shim(nil)
72
+ Backend.install_logger_shim(nil, nil)
73
73
  return
74
74
  end
75
75
  shim =
@@ -31,7 +31,7 @@ module Couchbase
31
31
  # dataverse with the specified name already exists.
32
32
  #
33
33
  # @param [Integer, #in_milliseconds, nil] timeout the time in milliseconds allowed for the operation to complete
34
- # @param [Proc, nil] retry_strategy the custom retry strategy, if set
34
+ # @param [Symbol, nil] retry_strategy ignored by this operation
35
35
  # @param [Hash, nil] client_context the client context data, if set
36
36
  # @param [Span, nil] parent_span if set holds the parent span, that should be used for this request
37
37
  #
@@ -65,7 +65,7 @@ module Couchbase
65
65
  # if the dataverse with the specified name does not exist.
66
66
  #
67
67
  # @param [Integer, #in_milliseconds, nil] timeout the time in milliseconds allowed for the operation to complete
68
- # @param [Proc, nil] retry_strategy the custom retry strategy, if set
68
+ # @param [Symbol, nil] retry_strategy ignored by this operation
69
69
  # @param [Hash, nil] client_context the client context data, if set
70
70
  # @param [Span, nil] parent_span if set holds the parent span, that should be used for this request
71
71
  #
@@ -103,7 +103,7 @@ module Couchbase
103
103
  # @param [String] dataverse_name the name of the dataverse to use (defaults to +nil+)
104
104
  #
105
105
  # @param [Integer, #in_milliseconds, nil] timeout the time in milliseconds allowed for the operation to complete
106
- # @param [Proc, nil] retry_strategy the custom retry strategy, if set
106
+ # @param [Symbol, nil] retry_strategy ignored by this operation
107
107
  # @param [Hash, nil] client_context the client context data, if set
108
108
  # @param [Span, nil] parent_span if set holds the parent span, that should be used for this request
109
109
  #
@@ -145,7 +145,7 @@ module Couchbase
145
145
  # @param [String] dataverse_name the name of the dataverse to use (defaults to +nil+)
146
146
  #
147
147
  # @param [Integer, #in_milliseconds, nil] timeout the time in milliseconds allowed for the operation to complete
148
- # @param [Proc, nil] retry_strategy the custom retry strategy, if set
148
+ # @param [Symbol, nil] retry_strategy ignored by this operation
149
149
  # @param [Hash, nil] client_context the client context data, if set
150
150
  # @param [Span, nil] parent_span if set holds the parent span, that should be used for this request
151
151
  #
@@ -177,7 +177,7 @@ module Couchbase
177
177
  # Creates an instance of options for {AnalyticsIndexManager#get_all_datasets}
178
178
  #
179
179
  # @param [Integer, #in_milliseconds, nil] timeout the time in milliseconds allowed for the operation to complete
180
- # @param [Proc, nil] retry_strategy the custom retry strategy, if set
180
+ # @param [Symbol, nil] retry_strategy ignored by this operation
181
181
  # @param [Hash, nil] client_context the client context data, if set
182
182
  # @param [Span, nil] parent_span if set holds the parent span, that should be used for this request
183
183
  #
@@ -203,7 +203,7 @@ module Couchbase
203
203
  # @param [String] dataverse_name the name of the dataverse to use (defaults to +nil+)
204
204
  #
205
205
  # @param [Integer, #in_milliseconds, nil] timeout the time in milliseconds allowed for the operation to complete
206
- # @param [Proc, nil] retry_strategy the custom retry strategy, if set
206
+ # @param [Symbol, nil] retry_strategy ignored by this operation
207
207
  # @param [Hash, nil] client_context the client context data, if set
208
208
  # @param [Span, nil] parent_span if set holds the parent span, that should be used for this request
209
209
  #
@@ -242,7 +242,7 @@ module Couchbase
242
242
  # @param [String] dataverse_name the name of the dataverse to use (defaults to +nil+)
243
243
  #
244
244
  # @param [Integer, #in_milliseconds, nil] timeout the time in milliseconds allowed for the operation to complete
245
- # @param [Proc, nil] retry_strategy the custom retry strategy, if set
245
+ # @param [Symbol, nil] retry_strategy ignored by this operation
246
246
  # @param [Hash, nil] client_context the client context data, if set
247
247
  # @param [Span, nil] parent_span if set holds the parent span, that should be used for this request
248
248
  #
@@ -274,7 +274,7 @@ module Couchbase
274
274
  # Creates an instance of options for {AnalyticsIndexManager#get_all_indexes}
275
275
  #
276
276
  # @param [Integer, #in_milliseconds, nil] timeout the time in milliseconds allowed for the operation to complete
277
- # @param [Proc, nil] retry_strategy the custom retry strategy, if set
277
+ # @param [Symbol, nil] retry_strategy ignored by this operation
278
278
  # @param [Hash, nil] client_context the client context data, if set
279
279
  # @param [Span, nil] parent_span if set holds the parent span, that should be used for this request
280
280
  #
@@ -302,7 +302,7 @@ module Couchbase
302
302
  # @param [String] dataverse_name the name of the dataverse to use (defaults to +nil+)
303
303
  #
304
304
  # @param [Integer, #in_milliseconds, nil] timeout the time in milliseconds allowed for the operation to complete
305
- # @param [Proc, nil] retry_strategy the custom retry strategy, if set
305
+ # @param [Symbol, nil] retry_strategy ignored by this operation
306
306
  # @param [Hash, nil] client_context the client context data, if set
307
307
  # @param [Span, nil] parent_span if set holds the parent span, that should be used for this request
308
308
  #
@@ -343,7 +343,7 @@ module Couchbase
343
343
  # @param [String] dataverse_name the name of the dataverse to use (defaults to +nil+)
344
344
  #
345
345
  # @param [Integer, #in_milliseconds, nil] timeout the time in milliseconds allowed for the operation to complete
346
- # @param [Proc, nil] retry_strategy the custom retry strategy, if set
346
+ # @param [Symbol, nil] retry_strategy ignored by this operation
347
347
  # @param [Hash, nil] client_context the client context data, if set
348
348
  # @param [Span, nil] parent_span if set holds the parent span, that should be used for this request
349
349
  #
@@ -375,7 +375,7 @@ module Couchbase
375
375
  # Creates an instance of options for {AnalyticsIndexManager#get_pending_mutations}
376
376
  #
377
377
  # @param [Integer, #in_milliseconds, nil] timeout the time in milliseconds allowed for the operation to complete
378
- # @param [Proc, nil] retry_strategy the custom retry strategy, if set
378
+ # @param [Symbol, nil] retry_strategy ignored by this operation
379
379
  # @param [Hash, nil] client_context the client context data, if set
380
380
  # @param [Span, nil] parent_span if set holds the parent span, that should be used for this request
381
381
  #
@@ -394,7 +394,7 @@ module Couchbase
394
394
  # Creates an instance of options for {AnalyticsIndexManager#create_link}
395
395
  #
396
396
  # @param [Integer, #in_milliseconds, nil] timeout the time in milliseconds allowed for the operation to complete
397
- # @param [Proc, nil] retry_strategy the custom retry strategy, if set
397
+ # @param [Symbol, nil] retry_strategy ignored by this operation
398
398
  # @param [Hash, nil] client_context the client context data, if set
399
399
  # @param [Span, nil] parent_span if set holds the parent span, that should be used for this request
400
400
  #
@@ -420,7 +420,7 @@ module Couchbase
420
420
  # Creates an instance of options for {AnalyticsIndexManager#replace_link}
421
421
  #
422
422
  # @param [Integer, #in_milliseconds, nil] timeout the time in milliseconds allowed for the operation to complete
423
- # @param [Proc, nil] retry_strategy the custom retry strategy, if set
423
+ # @param [Symbol, nil] retry_strategy ignored by this operation
424
424
  # @param [Hash, nil] client_context the client context data, if set
425
425
  # @param [Span, nil] parent_span if set holds the parent span, that should be used for this request
426
426
  #
@@ -446,7 +446,7 @@ module Couchbase
446
446
  # Creates an instance of options for {AnalyticsIndexManager#drop_link}
447
447
  #
448
448
  # @param [Integer, #in_milliseconds, nil] timeout the time in milliseconds allowed for the operation to complete
449
- # @param [Proc, nil] retry_strategy the custom retry strategy, if set
449
+ # @param [Symbol, nil] retry_strategy ignored by this operation
450
450
  # @param [Hash, nil] client_context the client context data, if set
451
451
  # @param [Span, nil] parent_span if set holds the parent span, that should be used for this request
452
452
  #
@@ -483,7 +483,7 @@ module Couchbase
483
483
  #
484
484
  # @param [Integer, #in_milliseconds, nil] timeout the time in milliseconds allowed for the operation to
485
485
  # complete
486
- # @param [Proc, nil] retry_strategy the custom retry strategy, if set
486
+ # @param [Symbol, nil] retry_strategy ignored by this operation
487
487
  # @param [Hash, nil] client_context the client context data, if set
488
488
  # @param [Span, nil] parent_span if set holds the parent span, that should be used for this request
489
489
  #