couchbase 3.0.2 → 3.0.3

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 (136) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/ext/CMakeLists.txt +3 -0
  4. data/ext/build_version.hxx.in +1 -1
  5. data/ext/cmake/CompilerWarnings.cmake +1 -0
  6. data/ext/cmake/PreventInSourceBuilds.cmake +4 -1
  7. data/ext/couchbase/bucket.hxx +28 -2
  8. data/ext/couchbase/cluster.hxx +8 -2
  9. data/ext/couchbase/couchbase.cxx +955 -511
  10. data/ext/couchbase/error_context/analytics.hxx +46 -0
  11. data/ext/couchbase/error_context/http.hxx +44 -0
  12. data/ext/couchbase/error_context/key_value.hxx +47 -0
  13. data/ext/couchbase/error_context/query.hxx +46 -0
  14. data/ext/couchbase/error_context/search.hxx +47 -0
  15. data/ext/couchbase/error_context/view.hxx +47 -0
  16. data/ext/couchbase/io/dns_codec.hxx +1 -2
  17. data/ext/couchbase/io/http_command.hxx +16 -3
  18. data/ext/couchbase/io/http_context.hxx +1 -1
  19. data/ext/couchbase/io/http_session.hxx +12 -6
  20. data/ext/couchbase/io/http_session_manager.hxx +25 -24
  21. data/ext/couchbase/io/mcbp_session.hxx +8 -2
  22. data/ext/couchbase/io/retry_context.hxx +1 -1
  23. data/ext/couchbase/operations/analytics_dataset_create.hxx +19 -12
  24. data/ext/couchbase/operations/analytics_dataset_drop.hxx +18 -10
  25. data/ext/couchbase/operations/analytics_dataset_get_all.hxx +16 -10
  26. data/ext/couchbase/operations/analytics_dataverse_create.hxx +18 -11
  27. data/ext/couchbase/operations/analytics_dataverse_drop.hxx +17 -11
  28. data/ext/couchbase/operations/analytics_get_pending_mutations.hxx +17 -10
  29. data/ext/couchbase/operations/analytics_index_create.hxx +17 -11
  30. data/ext/couchbase/operations/analytics_index_drop.hxx +16 -10
  31. data/ext/couchbase/operations/analytics_index_get_all.hxx +14 -10
  32. data/ext/couchbase/operations/analytics_link_connect.hxx +15 -9
  33. data/ext/couchbase/operations/analytics_link_disconnect.hxx +16 -10
  34. data/ext/couchbase/operations/bucket_create.hxx +33 -10
  35. data/ext/couchbase/operations/bucket_drop.hxx +9 -8
  36. data/ext/couchbase/operations/bucket_flush.hxx +8 -8
  37. data/ext/couchbase/operations/bucket_get.hxx +15 -10
  38. data/ext/couchbase/operations/bucket_get_all.hxx +14 -7
  39. data/ext/couchbase/operations/bucket_settings.hxx +16 -0
  40. data/ext/couchbase/operations/bucket_update.hxx +32 -10
  41. data/ext/couchbase/operations/cluster_developer_preview_enable.hxx +6 -6
  42. data/ext/couchbase/operations/collection_create.hxx +19 -13
  43. data/ext/couchbase/operations/collection_drop.hxx +18 -12
  44. data/ext/couchbase/operations/collections_manifest_get.hxx +5 -10
  45. data/ext/couchbase/operations/document_analytics.hxx +39 -17
  46. data/ext/couchbase/operations/document_append.hxx +5 -10
  47. data/ext/couchbase/operations/document_decrement.hxx +5 -10
  48. data/ext/couchbase/operations/document_exists.hxx +4 -6
  49. data/ext/couchbase/operations/document_get.hxx +6 -10
  50. data/ext/couchbase/operations/document_get_and_lock.hxx +4 -9
  51. data/ext/couchbase/operations/document_get_and_touch.hxx +4 -9
  52. data/ext/couchbase/operations/document_get_projected.hxx +21 -14
  53. data/ext/couchbase/operations/document_increment.hxx +5 -10
  54. data/ext/couchbase/operations/document_insert.hxx +5 -10
  55. data/ext/couchbase/operations/document_lookup_in.hxx +4 -9
  56. data/ext/couchbase/operations/document_mutate_in.hxx +7 -12
  57. data/ext/couchbase/operations/document_prepend.hxx +5 -10
  58. data/ext/couchbase/operations/document_query.hxx +45 -28
  59. data/ext/couchbase/operations/document_remove.hxx +5 -10
  60. data/ext/couchbase/operations/document_replace.hxx +5 -10
  61. data/ext/couchbase/operations/document_search.hxx +37 -16
  62. data/ext/couchbase/operations/document_touch.hxx +4 -9
  63. data/ext/couchbase/operations/document_unlock.hxx +4 -9
  64. data/ext/couchbase/operations/document_upsert.hxx +5 -10
  65. data/ext/couchbase/operations/document_view.hxx +29 -13
  66. data/ext/couchbase/operations/group_drop.hxx +7 -7
  67. data/ext/couchbase/operations/group_get.hxx +14 -10
  68. data/ext/couchbase/operations/group_get_all.hxx +14 -8
  69. data/ext/couchbase/operations/group_upsert.hxx +15 -9
  70. data/ext/couchbase/operations/http_noop.hxx +5 -5
  71. data/ext/couchbase/operations/mcbp_noop.hxx +3 -9
  72. data/ext/couchbase/operations/query_index_build_deferred.hxx +15 -9
  73. data/ext/couchbase/operations/query_index_create.hxx +16 -10
  74. data/ext/couchbase/operations/query_index_drop.hxx +16 -10
  75. data/ext/couchbase/operations/query_index_get_all.hxx +13 -7
  76. data/ext/couchbase/operations/role_get_all.hxx +14 -8
  77. data/ext/couchbase/operations/scope_create.hxx +19 -13
  78. data/ext/couchbase/operations/scope_drop.hxx +17 -11
  79. data/ext/couchbase/operations/scope_get_all.hxx +15 -10
  80. data/ext/couchbase/operations/search_get_stats.hxx +5 -5
  81. data/ext/couchbase/operations/search_index_analyze_document.hxx +25 -13
  82. data/ext/couchbase/operations/search_index_control_ingest.hxx +23 -11
  83. data/ext/couchbase/operations/search_index_control_plan_freeze.hxx +23 -11
  84. data/ext/couchbase/operations/search_index_control_query.hxx +23 -11
  85. data/ext/couchbase/operations/search_index_drop.hxx +22 -10
  86. data/ext/couchbase/operations/search_index_get.hxx +22 -10
  87. data/ext/couchbase/operations/search_index_get_all.hxx +13 -7
  88. data/ext/couchbase/operations/search_index_get_documents_count.hxx +24 -13
  89. data/ext/couchbase/operations/search_index_get_stats.hxx +16 -10
  90. data/ext/couchbase/operations/search_index_upsert.hxx +23 -11
  91. data/ext/couchbase/operations/user_drop.hxx +8 -8
  92. data/ext/couchbase/operations/user_get.hxx +14 -10
  93. data/ext/couchbase/operations/user_get_all.hxx +14 -8
  94. data/ext/couchbase/operations/user_upsert.hxx +15 -9
  95. data/ext/couchbase/operations/view_index_drop.hxx +7 -7
  96. data/ext/couchbase/operations/view_index_get.hxx +15 -9
  97. data/ext/couchbase/operations/view_index_get_all.hxx +15 -9
  98. data/ext/couchbase/operations/view_index_upsert.hxx +8 -8
  99. data/ext/couchbase/origin.hxx +1 -0
  100. data/ext/couchbase/platform/terminate_handler.cc +12 -8
  101. data/ext/couchbase/protocol/client_request.hxx +2 -1
  102. data/ext/couchbase/protocol/client_response.hxx +18 -15
  103. data/ext/couchbase/protocol/cmd_exists.hxx +1 -0
  104. data/ext/couchbase/protocol/cmd_get.hxx +1 -1
  105. data/ext/couchbase/protocol/cmd_mutate_in.hxx +3 -4
  106. data/ext/couchbase/protocol/enhanced_error_info.hxx +28 -0
  107. data/ext/couchbase/utils/connection_string.hxx +1 -1
  108. data/ext/couchbase/version.hxx +1 -1
  109. data/ext/extconf.rb +1 -1
  110. data/ext/test/test_native_binary_operations.cxx +18 -18
  111. data/ext/test/test_native_diagnostics.cxx +2 -2
  112. data/ext/test/test_native_trivial_crud.cxx +2 -2
  113. data/ext/third_party/json/include/tao/json/external/pegtl/internal/file_reader.hpp +1 -5
  114. data/lib/active_support/cache/couchbase_store.rb +362 -0
  115. data/lib/couchbase.rb +2 -0
  116. data/lib/couchbase/authenticator.rb +26 -0
  117. data/lib/couchbase/binary_collection.rb +1 -0
  118. data/lib/couchbase/bucket.rb +1 -0
  119. data/lib/couchbase/cluster.rb +51 -27
  120. data/lib/couchbase/collection.rb +19 -4
  121. data/lib/couchbase/collection_options.rb +10 -0
  122. data/lib/couchbase/configuration.rb +57 -0
  123. data/lib/couchbase/datastructures.rb +6 -0
  124. data/lib/couchbase/errors.rb +111 -3
  125. data/lib/couchbase/management.rb +27 -0
  126. data/lib/couchbase/management/bucket_manager.rb +9 -2
  127. data/lib/couchbase/management/collection_manager.rb +1 -1
  128. data/lib/couchbase/management/user_manager.rb +18 -2
  129. data/lib/couchbase/options.rb +33 -23
  130. data/lib/couchbase/railtie.rb +45 -0
  131. data/lib/couchbase/scope.rb +44 -3
  132. data/lib/couchbase/utils.rb +21 -0
  133. data/lib/couchbase/utils/time.rb +52 -0
  134. data/lib/couchbase/version.rb +1 -1
  135. data/lib/rails/generators/couchbase/config/config_generator.rb +27 -0
  136. metadata +19 -5
data/lib/couchbase.rb CHANGED
@@ -16,3 +16,5 @@ require "couchbase/version"
16
16
  require "couchbase/libcouchbase"
17
17
  require "couchbase/logger"
18
18
  require "couchbase/cluster"
19
+
20
+ require "couchbase/railtie" if defined?(Rails)
@@ -15,12 +15,34 @@
15
15
  module Couchbase
16
16
  # Authenticator for username/password credentials
17
17
  class PasswordAuthenticator
18
+ DEFAULT_SASL_MECHANISMS = [:scram_sha512, :scram_sha256, :scram_sha1].freeze
19
+
18
20
  attr_accessor :username
19
21
  attr_accessor :password
22
+ attr_accessor :allowed_sasl_mechanisms
20
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
21
28
  def initialize(username, password)
22
29
  @username = username
23
30
  @password = password
31
+ @allowed_sasl_mechanisms = DEFAULT_SASL_MECHANISMS
32
+ end
33
+
34
+ # Creates a LDAP compatible password authenticator which is INSECURE if not used with TLS.
35
+ #
36
+ # Please note that this is INSECURE and will leak user credentials on the wire to eavesdroppers. This should
37
+ # only be enabled in trusted environments.
38
+ #
39
+ # @param [String] username the username to use for all authentication.
40
+ # @param [String] password the password to use alongside the username.
41
+ # @return [PasswordAuthenticator]
42
+ def self.ldap_compatible(username, password)
43
+ new(username, password).tap do |auth|
44
+ auth.allowed_sasl_mechanisms = [:plain]
45
+ end
24
46
  end
25
47
  end
26
48
 
@@ -31,6 +53,10 @@ module Couchbase
31
53
  attr_accessor :certificate_path
32
54
  attr_accessor :key_path
33
55
 
56
+ # Creates a new authenticator with certificate and key paths
57
+ #
58
+ # @param [String] certificate_path path to certificate
59
+ # @param [String] key_path path to private key
34
60
  def initialize(certificate_path, key_path)
35
61
  @certificate_path = certificate_path
36
62
  @key_path = key_path
@@ -16,6 +16,7 @@ require "couchbase/options"
16
16
  require "couchbase/binary_collection_options"
17
17
 
18
18
  module Couchbase
19
+ # Allows to perform certain operations on non-JSON documents.
19
20
  class BinaryCollection
20
21
  alias inspect to_s
21
22
 
@@ -20,6 +20,7 @@ require "couchbase/view_options"
20
20
  require "couchbase/diagnostics"
21
21
 
22
22
  module Couchbase
23
+ # Provides access to a Couchbase bucket APIs
23
24
  class Bucket
24
25
  # @return [String] name of the bucket
25
26
  attr_reader :name
@@ -12,15 +12,11 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ require "couchbase/configuration"
15
16
  require "couchbase/authenticator"
16
17
  require "couchbase/bucket"
17
18
 
18
- require "couchbase/management/user_manager"
19
- require "couchbase/management/bucket_manager"
20
- require "couchbase/management/query_index_manager"
21
- require "couchbase/management/analytics_index_manager"
22
- require "couchbase/management/search_index_manager"
23
-
19
+ require "couchbase/management"
24
20
  require "couchbase/options"
25
21
 
26
22
  require "couchbase/search_options"
@@ -29,6 +25,7 @@ require "couchbase/analytics_options"
29
25
  require "couchbase/diagnostics"
30
26
 
31
27
  module Couchbase
28
+ # The main entry point when connecting to a Couchbase cluster.
32
29
  class Cluster
33
30
  alias inspect to_s
34
31
 
@@ -86,6 +83,14 @@ module Couchbase
86
83
  # cluster.query("SELECT * FROM `travel-sample` WHERE type = $type LIMIT 10",
87
84
  # Options::Query(named_parameters: {type: "hotel"}, metrics: true))
88
85
  #
86
+ # @example Execute query with consistency requirement. Make sure that the index is in sync with selected mutation
87
+ # res = collection.upsert("user:42", {
88
+ # "name" => "Brass Doorknob",
89
+ # "email" => "brass.doorknob@example.com",
90
+ # })
91
+ # cluster.query("SELECT name, email FROM `mybucket`",
92
+ # Options::Query(consistent_with: MutationState.new(res.mutation_token)))
93
+ #
89
94
  # @return [QueryResult]
90
95
  def query(statement, options = Options::Query.new)
91
96
  resp = @backend.document_query(statement, options.to_backend)
@@ -354,42 +359,61 @@ module Couchbase
354
359
  # @param [String] username name of the user
355
360
  # @param [String] password password of the user
356
361
  # @param [Options::Cluster, nil] options custom options when creating the cluster connection
362
+ #
363
+ # @overload new(configuration)
364
+ # @param [Configuration] configuration configuration object
357
365
  def initialize(connection_string, *args)
358
366
  credentials = {}
367
+ open_options = {}
359
368
 
360
- options = args.shift
361
- case options
362
- when String
363
- credentials[:username] = options
364
- credentials[:password] = args.shift
369
+ if connection_string.is_a?(Configuration)
370
+ options = connection_string
371
+ connection_string = options.connection_string
372
+ credentials[:username] = options.username
373
+ credentials[:password] = options.password
374
+ raise ArgumentError, "missing connection_string" unless connection_string
365
375
  raise ArgumentError, "missing username" unless credentials[:username]
366
376
  raise ArgumentError, "missing password" unless credentials[:password]
367
- when Options::Cluster
368
- authenticator = options&.authenticator
369
- case authenticator
370
- when PasswordAuthenticator
371
- credentials[:username] = authenticator&.username
372
- raise ArgumentError, "missing username" unless credentials[:username]
373
377
 
374
- credentials[:password] = authenticator&.password
378
+ open_options[:allowed_sasl_mechanisms] = PasswordAuthenticator::DEFAULT_SASL_MECHANISMS
379
+ else
380
+ options = args.shift
381
+ case options
382
+ when String
383
+ credentials[:username] = options
384
+ credentials[:password] = args.shift
385
+ raise ArgumentError, "missing username" unless credentials[:username]
375
386
  raise ArgumentError, "missing password" unless credentials[:password]
376
387
 
377
- when CertificateAuthenticator
378
- credentials[:certificate_path] = authenticator&.certificate_path
379
- raise ArgumentError, "missing certificate path" unless credentials[:certificate_path]
388
+ open_options[:allowed_sasl_mechanisms] = PasswordAuthenticator::DEFAULT_SASL_MECHANISMS
389
+ when Options::Cluster
390
+ authenticator = options&.authenticator
391
+ case authenticator
392
+ when PasswordAuthenticator
393
+ credentials[:username] = authenticator&.username
394
+ raise ArgumentError, "missing username" unless credentials[:username]
395
+
396
+ credentials[:password] = authenticator&.password
397
+ raise ArgumentError, "missing password" unless credentials[:password]
398
+
399
+ open_options[:allowed_sasl_mechanisms] = authenticator&.allowed_sasl_mechanisms
400
+ when CertificateAuthenticator
401
+ credentials[:certificate_path] = authenticator&.certificate_path
402
+ raise ArgumentError, "missing certificate path" unless credentials[:certificate_path]
380
403
 
381
- credentials[:key_path] = authenticator&.key_path
382
- raise ArgumentError, "missing key path" unless credentials[:key_path]
404
+ credentials[:key_path] = authenticator&.key_path
405
+ raise ArgumentError, "missing key path" unless credentials[:key_path]
383
406
 
407
+ else
408
+ raise ArgumentError, "options must have authenticator configured"
409
+ end
384
410
  else
385
- raise ArgumentError, "options must have authenticator configured"
411
+ raise ArgumentError, "unexpected second argument, have to be String or ClusterOptions"
386
412
  end
387
- else
388
- raise ArgumentError, "unexpected second argument, have to be String or ClusterOptions"
389
413
  end
390
414
 
391
415
  @backend = Backend.new
392
- @backend.open(connection_string, credentials, {})
416
+ @backend.open(connection_string, credentials, open_options)
393
417
  end
394
418
 
395
419
  # @api private
@@ -17,6 +17,7 @@ require "couchbase/collection_options"
17
17
  require "couchbase/binary_collection"
18
18
 
19
19
  module Couchbase
20
+ # Provides access to all collection APIs
20
21
  class Collection
21
22
  attr_reader :bucket_name
22
23
  attr_reader :scope_name
@@ -142,7 +143,7 @@ module Couchbase
142
143
  # Fetches a full document and resets its expiration time to the duration provided
143
144
  #
144
145
  # @param [String] id the document id which is used to uniquely identify it.
145
- # @param [Integer, #in_seconds] expiry the new expiration time for the document
146
+ # @param [Integer, #in_seconds, Time] expiry the new expiration time for the document
146
147
  # @param [Options::GetAndTouch] options request customization
147
148
  #
148
149
  # @example Retrieve document and prolong its expiration for another 10 seconds
@@ -151,7 +152,7 @@ module Couchbase
151
152
  # @return [GetResult]
152
153
  def get_and_touch(id, expiry, options = Options::GetAndTouch.new)
153
154
  resp = @backend.document_get_and_touch(bucket_name, "#{@scope_name}.#{@name}", id,
154
- expiry.respond_to?(:in_seconds) ? expiry.public_send(:in_seconds) : expiry,
155
+ Utils::Time.extract_expiry_time(expiry),
155
156
  options.to_backend)
156
157
  GetResult.new do |res|
157
158
  res.transcoder = options.transcoder
@@ -258,6 +259,7 @@ module Couchbase
258
259
  MutationResult.new do |res|
259
260
  res.cas = entry[:cas]
260
261
  res.mutation_token = extract_mutation_token(entry)
262
+ res.error = entry[:error]
261
263
  end
262
264
  end
263
265
  end
@@ -338,6 +340,7 @@ module Couchbase
338
340
  MutationResult.new do |res|
339
341
  res.cas = entry[:cas]
340
342
  res.mutation_token = extract_mutation_token(entry)
343
+ res.error = entry[:error]
341
344
  end
342
345
  end
343
346
  end
@@ -366,7 +369,7 @@ module Couchbase
366
369
  # Update the expiration of the document with the given id
367
370
  #
368
371
  # @param [String] id the document id which is used to uniquely identify it.
369
- # @param [Integer, #in_seconds] expiry new expiration time for the document
372
+ # @param [Integer, #in_seconds, Time] expiry new expiration time for the document
370
373
  # @param [Options::Touch] options request customization
371
374
  #
372
375
  # @example Reset expiration timer for document to 30 seconds
@@ -375,7 +378,7 @@ module Couchbase
375
378
  # @return [MutationResult]
376
379
  def touch(id, expiry, options = Options::Touch.new)
377
380
  resp = @backend.document_touch(bucket_name, "#{@scope_name}.#{@name}", id,
378
- expiry.respond_to?(:in_seconds) ? expiry.public_send(:in_seconds) : expiry,
381
+ Utils::Time.extract_expiry_time(expiry),
379
382
  options.to_backend)
380
383
  MutationResult.new do |res|
381
384
  res.cas = resp[:cas]
@@ -411,6 +414,11 @@ module Couchbase
411
414
  # ]
412
415
  # collection.lookup_in("customer123", lookup_specs)
413
416
  #
417
+ # @example Retrieve country name and check if pending purchases array is empty
418
+ # collection.lookup_in "customer123", [
419
+ # LookupInSpec.get("addresses.delivery.country"),
420
+ # LookupInSpec.exists("purchases.pending[-1]"),
421
+ # ]
414
422
  # @return [LookupInResult]
415
423
  def lookup_in(id, specs, options = Options::LookupIn.new)
416
424
  resp = @backend.document_lookup_in(
@@ -453,6 +461,13 @@ module Couchbase
453
461
  # ]
454
462
  # collection.mutate_in("customer123", mutation_specs, Options::MutateIn(expiry: 10))
455
463
  #
464
+ # @example Write meta attribute, remove array entry and replace email field
465
+ # collection.mutate_in("customer123", [
466
+ # MutateInSpec.upsert("_framework.model_type", "Customer").xattr,
467
+ # MutateInSpec.remove("addresses.billing[2]"),
468
+ # MutateInSpec.replace("email", "dougr96@hotmail.com"),
469
+ # ])
470
+ #
456
471
  # @return [MutateInResult]
457
472
  def mutate_in(id, specs, options = Options::MutateIn.new)
458
473
  resp = @backend.document_mutate_in(
@@ -32,6 +32,11 @@ module Couchbase
32
32
  # @return [Error::CouchbaseError, nil] error associated with the result, or nil (used in {Collection#get_multi})
33
33
  attr_accessor :error
34
34
 
35
+ # @return [Boolean] true if error was not associated with the result (useful for multi-operations)
36
+ def success?
37
+ !error
38
+ end
39
+
35
40
  # @return [String] The encoded content when loading the document
36
41
  # @api private
37
42
  attr_accessor :encoded
@@ -112,6 +117,11 @@ module Couchbase
112
117
  # {Collection#remove_multi})
113
118
  attr_accessor :error
114
119
 
120
+ # @return [Boolean] true if error was not associated with the result (useful for multi-operations)
121
+ def success?
122
+ !error
123
+ end
124
+
115
125
  # @yieldparam [MutationResult] self
116
126
  def initialize
117
127
  @error = nil
@@ -0,0 +1,57 @@
1
+ # Copyright 2020 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 "yaml"
16
+ require "erb"
17
+
18
+ module Couchbase
19
+ class Configuration
20
+ attr_accessor :connection_string
21
+ attr_accessor :username
22
+ attr_accessor :password
23
+
24
+ def initialize
25
+ @connection_string = "couchbase://localhost"
26
+ end
27
+
28
+ def load!(path, environment = default_environment_name)
29
+ settings = load_yaml(path, environment)
30
+ load_configuration(settings)
31
+ end
32
+
33
+ private
34
+
35
+ def load_configuration(settings)
36
+ configuration = settings.with_indifferent_access
37
+ @connection_string = configuration[:connection_string]
38
+ @username = configuration[:username]
39
+ @password = configuration[:password]
40
+ end
41
+
42
+ def load_yaml(path, environment)
43
+ file_content = ERB.new(File.read(path)).result
44
+ YAML.safe_load(file_content, aliases: :default)[environment]
45
+ end
46
+
47
+ def default_environment_name
48
+ if defined?(::Rails)
49
+ ::Rails.env
50
+ elsif defined?(::Sinatra)
51
+ ::Sinatra::Base.environment.to_s
52
+ else
53
+ ENV["RACK_ENV"] || ENV["COUCHBASE_ENV"] or raise ::Couchbase::Error::NoEnvironment
54
+ end
55
+ end
56
+ end
57
+ end
@@ -12,6 +12,12 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ module Couchbase
16
+ # This namespace includes easy-to-use wrappers for various concurrent data-structures.
17
+ module Datastructures
18
+ end
19
+ end
20
+
15
21
  require "couchbase/datastructures/couchbase_list"
16
22
  require "couchbase/datastructures/couchbase_set"
17
23
  require "couchbase/datastructures/couchbase_queue"
@@ -12,34 +12,59 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ require "json"
16
+
15
17
  module Couchbase
18
+ # This namespace contains all error types that the library might raise.
16
19
  module Error
17
20
  class CouchbaseError < StandardError
21
+ # @return [Hash] attributes associated with the error
22
+ attr_reader :context
23
+
24
+ def to_s
25
+ defined?(@context) ? "#{super}, context=#{JSON.generate(@context)}" : super
26
+ end
18
27
  end
19
28
 
20
- # Common exceptions
29
+ class InvalidArgument < ArgumentError
30
+ # @return [Hash] attributes associated with the error
31
+ attr_reader :context
21
32
 
22
- class RequestCanceled < CouchbaseError
33
+ def to_s
34
+ defined?(@context) ? "#{super}, context=#{JSON.generate(@context)}" : super
35
+ end
23
36
  end
24
37
 
25
- class InvalidArgument < ArgumentError
38
+ # Common exceptions
39
+
40
+ class RequestCanceled < CouchbaseError
26
41
  end
27
42
 
28
43
  class ServiceNotAvailable < CouchbaseError
29
44
  end
30
45
 
46
+ # Indicates an operation failed because there has been an internal error in the server.
31
47
  class InternalServerFailure < CouchbaseError
32
48
  end
33
49
 
50
+ # Every exception that has to do with authentication problems should either instantiate or subclass from this type.
34
51
  class AuthenticationFailure < CouchbaseError
35
52
  end
36
53
 
37
54
  class TemporaryFailure < CouchbaseError
38
55
  end
39
56
 
57
+ # Indicates an operation failed because parsing of the input returned with an error.
40
58
  class ParsingFailure < CouchbaseError
41
59
  end
42
60
 
61
+ # Indicates an optimistic locking failure.
62
+ #
63
+ # The operation failed because the specified compare and swap (CAS) value differs from the document's actual CAS
64
+ # value. This means the document was modified since the original CAS value was acquired.
65
+ #
66
+ # The application should usually respond by fetching a fresh version of the document and repeating the failed
67
+ # operation.
43
68
  class CasMismatch < CouchbaseError
44
69
  end
45
70
 
@@ -58,123 +83,201 @@ module Couchbase
58
83
  class IndexExists < CouchbaseError
59
84
  end
60
85
 
86
+ # Raised when provided content could not be successfully encoded.
61
87
  class EncodingFailure < CouchbaseError
62
88
  end
63
89
 
90
+ # Raised when provided content could not be successfully decoded.
64
91
  class DecodingFailure < CouchbaseError
65
92
  end
66
93
 
67
94
  class UnsupportedOperation < CouchbaseError
68
95
  end
69
96
 
97
+ # The {Timeout} signals that an operation timed out before it could be completed.
98
+ #
99
+ # It is important to understand that the timeout itself is always just the effect an underlying cause, never the
100
+ # issue itself. The root cause might not even be on the application side, also the network and server need to be
101
+ # taken into account.
102
+ #
103
+ # Right now the SDK can throw two different implementations of this class:
104
+ #
105
+ # {AmbiguousTimeout}::
106
+ # The operation might have caused a side effect on the server and should not be retried without
107
+ # actions and checks.
108
+ #
109
+ # {UnambiguousTimeout}::
110
+ # The operation has not caused a side effect on the server and is safe to retry. This is always the case for
111
+ # idempotent operations. For non-idempotent operations it depends on the state the operation was in at the time of
112
+ # cancellation.
70
113
  class Timeout < CouchbaseError
71
114
  end
72
115
 
116
+ # This is a special case of the timeout exception, signaling that the timeout happened with an ambiguous cause.
73
117
  class AmbiguousTimeout < Timeout
74
118
  end
75
119
 
120
+ # This is a special case of the timeout exception, signaling that the timeout happened with no ambiguous cause.
76
121
  class UnambiguousTimeout < Timeout
77
122
  end
78
123
 
124
+ # Exception which states that the feature is not available.
79
125
  class FeatureNotAvailable < CouchbaseError
80
126
  end
81
127
 
82
128
  # KeyValue exceptions
83
129
 
130
+ # Indicates an operation failed because the key does not exist.
84
131
  class DocumentNotFound < CouchbaseError
85
132
  end
86
133
 
134
+ # Indicates an operation completed but no successful document was retrievable.
87
135
  class DocumentIrretrievable < CouchbaseError
88
136
  end
89
137
 
138
+ # Thrown when the server reports a temporary failure that is very likely to be lock-related (like an already locked
139
+ # key or a bad cas used for unlock).
140
+ #
141
+ # See https://issues.couchbase.com/browse/MB-13087 for an explanation of why this is only _likely_ to be
142
+ # lock-related.
90
143
  class DocumentLocked < CouchbaseError
91
144
  end
92
145
 
146
+ # Thrown when the request is too big for some reason.
93
147
  class ValueTooLarge < CouchbaseError
94
148
  end
95
149
 
150
+ # Indicates an operation failed because the key already exists.
96
151
  class DocumentExists < CouchbaseError
97
152
  end
98
153
 
154
+ # This exception is raised when a durability level has been requested that is not available on the server.
99
155
  class DurabilityLevelNotAvailable < CouchbaseError
100
156
  end
101
157
 
158
+ # The given durability requirements are currently impossible to achieve, as not enough configured replicas are
159
+ # currently available.
102
160
  class DurabilityImpossible < CouchbaseError
103
161
  end
104
162
 
163
+ # The synchronous replication durability work can return an ambiguous error (or we timeout waiting for the response,
164
+ # which is effectively the same). Here we know the change is on a majority of replicas, or it's on none.
105
165
  class DurabilityAmbiguous < CouchbaseError
106
166
  end
107
167
 
168
+ # Returned if an attempt is made to mutate a key which already has a durable write pending.
108
169
  class DurableWriteInProgress < CouchbaseError
109
170
  end
110
171
 
172
+ # The requested key has a SyncWrite which is being re-committed.
111
173
  class DurableWriteReCommitInProgress < CouchbaseError
112
174
  end
113
175
 
176
+ # Subdocument exception thrown when a path does not exist in the document. The exact meaning of path existence
177
+ # depends on the operation and inputs.
114
178
  class PathNotFound < CouchbaseError
115
179
  end
116
180
 
181
+ # Subdocument exception thrown when the path structure conflicts with the document structure (for example, if a
182
+ # path mentions foo.bar[0].baz, but foo.bar is actually a JSON object).
117
183
  class PathMismatch < CouchbaseError
118
184
  end
119
185
 
186
+ # Subdocument exception thrown when path has a syntax error, or path syntax is incorrect for the operation (for
187
+ # example, if operation requires an array index).
120
188
  class PathInvalid < CouchbaseError
121
189
  end
122
190
 
191
+ # Subdocument exception thrown when path is too deep to parse. Depth of a path is determined by how many components
192
+ # (or levels) it contains.
193
+ #
194
+ # The current limitation is there to ensure a single parse does not consume too much memory (overloading the
195
+ # server). This error is similar to other TooDeep errors, which all relate to various validation stages to ensure
196
+ # the server does not consume too much memory when parsing a single document.
123
197
  class PathTooDeep < CouchbaseError
124
198
  end
125
199
 
126
200
  class PathTooBig < CouchbaseError
127
201
  end
128
202
 
203
+ # Subdocument exception thrown when proposed value would make the document too deep to parse.
204
+ #
205
+ # The current limitation is there to ensure a single parse does not consume too much memory (overloading the
206
+ # server). This error is similar to other TooDeep errors, which all relate to various validation stages to ensure
207
+ # the server does not consume too much memory when parsing a single document.
129
208
  class ValueTooDeep < CouchbaseError
130
209
  end
131
210
 
211
+ # Subdocument exception thrown when the provided value cannot be inserted at the given path.
212
+ #
213
+ # It is actually thrown when the delta in an counter operation is valid, but applying that delta would
214
+ # result in an out-of-range number (server interprets numbers as 64-bit integers).
132
215
  class ValueInvalid < CouchbaseError
133
216
  end
134
217
 
218
+ # Subdocument exception thrown when the targeted enclosing document itself is not JSON.
135
219
  class DocumentNotJson < CouchbaseError
136
220
  end
137
221
 
222
+ # Subdocument exception thrown when existing number value in document is too big.
223
+ #
224
+ # The value is interpreted as 64 bit on the server side.
138
225
  class NumberTooBig < CouchbaseError
139
226
  end
140
227
 
228
+ # Subdocument exception thrown when the delta in an arithmetic operation (eg counter) is invalid. In this SDK, this
229
+ # is equivalent to saying that the delta is zero.
230
+ #
231
+ # Note that the server also returns the corresponding error code when the delta value itself is too big, or not a
232
+ # number, but since the SDK enforces deltas to be of type long, these cases shouldn't come up.
141
233
  class DeltaInvalid < CouchbaseError
142
234
  end
143
235
 
236
+ # Subdocument exception thrown when a path already exists and it shouldn't
144
237
  class PathExists < CouchbaseError
145
238
  end
146
239
 
240
+ # Subdocument exception thrown when a macro has been requested which is not recognised by the server.
147
241
  class XattrUnknownMacro < CouchbaseError
148
242
  end
149
243
 
244
+ # Subdocument exception thrown when more than one xattr key has been requested.
150
245
  class XattrInvalidKeyCombo < CouchbaseError
151
246
  end
152
247
 
248
+ # Subdocument exception thrown when a virtual attribute has been requested which is not recognised by the server.
153
249
  class XattrUnknownVirtualAttribute < CouchbaseError
154
250
  end
155
251
 
252
+ # Subdocument exception thrown when the virtual attribute cannot be modified.
156
253
  class XattrCannotModifyVirtualAttribute < CouchbaseError
157
254
  end
158
255
 
159
256
  # Query exceptions
160
257
 
258
+ # Indicates an operation failed because there has been an issue with the query planner.
161
259
  class PlanningFailure < CouchbaseError
162
260
  end
163
261
 
262
+ # Indicates an operation failed because there has been an issue with the query planner or similar.
164
263
  class IndexFailure < CouchbaseError
165
264
  end
166
265
 
266
+ # Indicates an operation failed because there has been an issue with query prepared statements.
167
267
  class PreparedStatementFailure < CouchbaseError
168
268
  end
169
269
 
170
270
  # Analytics exceptions
171
271
 
272
+ # The analytics query failed to compile.
172
273
  class CompilationFailure < CouchbaseError
173
274
  end
174
275
 
276
+ # Indicates the analytics server job queue is full
175
277
  class JobQueueFull < CouchbaseError
176
278
  end
177
279
 
280
+ # The queried dataset is not found on the server.
178
281
  class DatasetNotFound < CouchbaseError
179
282
  end
180
283
 
@@ -203,6 +306,7 @@ module Couchbase
203
306
  class DesignDocumentNotFound < CouchbaseError
204
307
  end
205
308
 
309
+ # The queried view is not found on the server
206
310
  class ViewNotFound < CouchbaseError
207
311
  end
208
312
 
@@ -233,5 +337,9 @@ module Couchbase
233
337
 
234
338
  class BackendError < CouchbaseError
235
339
  end
340
+
341
+ # Environment name string cannot be determined
342
+ class NoEnvironment < CouchbaseError
343
+ end
236
344
  end
237
345
  end