couchbase 3.0.0.alpha.5-universal-darwin-19 → 3.0.0.beta.1-universal-darwin-19

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 (124) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +12 -3
  3. data/README.md +4 -2
  4. data/Rakefile +1 -1
  5. data/couchbase.gemspec +17 -12
  6. data/ext/.idea/misc.xml +12 -0
  7. data/ext/CMakeLists.txt +10 -1
  8. data/ext/build_config.hxx.in +20 -0
  9. data/ext/build_version.hxx.in +1 -1
  10. data/ext/couchbase/bucket.hxx +90 -24
  11. data/ext/couchbase/cluster.hxx +125 -84
  12. data/ext/couchbase/cluster_options.hxx +53 -0
  13. data/ext/couchbase/configuration.hxx +220 -2
  14. data/ext/couchbase/couchbase.cxx +134 -127
  15. data/ext/couchbase/io/dns_client.hxx +3 -1
  16. data/ext/couchbase/io/http_command.hxx +91 -0
  17. data/ext/couchbase/io/http_session.hxx +58 -19
  18. data/ext/couchbase/io/http_session_manager.hxx +26 -31
  19. data/ext/couchbase/io/mcbp_command.hxx +180 -0
  20. data/ext/couchbase/io/mcbp_message.hxx +5 -0
  21. data/ext/couchbase/io/mcbp_session.hxx +213 -98
  22. data/ext/couchbase/io/streams.hxx +165 -0
  23. data/ext/couchbase/operations.hxx +1 -1
  24. data/ext/couchbase/operations/analytics_dataset_create.hxx +1 -1
  25. data/ext/couchbase/operations/bucket_create.hxx +4 -2
  26. data/ext/couchbase/operations/bucket_drop.hxx +4 -2
  27. data/ext/couchbase/operations/bucket_flush.hxx +4 -2
  28. data/ext/couchbase/operations/bucket_get.hxx +4 -2
  29. data/ext/couchbase/operations/bucket_get_all.hxx +4 -2
  30. data/ext/couchbase/operations/bucket_update.hxx +4 -2
  31. data/ext/couchbase/operations/cluster_developer_preview_enable.hxx +4 -2
  32. data/ext/couchbase/operations/collection_create.hxx +4 -2
  33. data/ext/couchbase/operations/collection_drop.hxx +4 -2
  34. data/ext/couchbase/operations/document_analytics.hxx +0 -4
  35. data/ext/couchbase/operations/document_decrement.hxx +6 -3
  36. data/ext/couchbase/operations/document_get.hxx +3 -0
  37. data/ext/couchbase/operations/document_get_and_lock.hxx +3 -0
  38. data/ext/couchbase/operations/document_get_and_touch.hxx +5 -2
  39. data/ext/couchbase/operations/document_get_projected.hxx +12 -9
  40. data/ext/couchbase/operations/document_increment.hxx +6 -3
  41. data/ext/couchbase/operations/document_insert.hxx +5 -2
  42. data/ext/couchbase/operations/document_lookup_in.hxx +3 -0
  43. data/ext/couchbase/operations/document_mutate_in.hxx +6 -3
  44. data/ext/couchbase/operations/document_remove.hxx +3 -0
  45. data/ext/couchbase/operations/document_replace.hxx +5 -2
  46. data/ext/couchbase/operations/document_search.hxx +6 -7
  47. data/ext/couchbase/operations/document_touch.hxx +5 -2
  48. data/ext/couchbase/operations/document_unlock.hxx +3 -0
  49. data/ext/couchbase/operations/document_upsert.hxx +5 -2
  50. data/ext/couchbase/operations/query_index_build_deferred.hxx +3 -3
  51. data/ext/couchbase/operations/query_index_create.hxx +3 -3
  52. data/ext/couchbase/operations/query_index_drop.hxx +3 -3
  53. data/ext/couchbase/operations/query_index_get_all.hxx +3 -3
  54. data/ext/couchbase/operations/scope_create.hxx +4 -2
  55. data/ext/couchbase/operations/scope_drop.hxx +4 -2
  56. data/ext/couchbase/operations/scope_get_all.hxx +4 -2
  57. data/ext/couchbase/operations/search_index_analyze_document.hxx +2 -2
  58. data/ext/couchbase/operations/search_index_control_ingest.hxx +2 -2
  59. data/ext/couchbase/operations/search_index_control_plan_freeze.hxx +2 -2
  60. data/ext/couchbase/operations/search_index_control_query.hxx +2 -2
  61. data/ext/couchbase/operations/search_index_drop.hxx +2 -2
  62. data/ext/couchbase/operations/search_index_get.hxx +2 -2
  63. data/ext/couchbase/operations/search_index_get_all.hxx +2 -2
  64. data/ext/couchbase/operations/search_index_get_documents_count.hxx +2 -2
  65. data/ext/couchbase/operations/search_index_upsert.hxx +2 -2
  66. data/ext/couchbase/origin.hxx +148 -0
  67. data/ext/couchbase/protocol/cmd_cluster_map_change_notification.hxx +1 -6
  68. data/ext/couchbase/protocol/cmd_decrement.hxx +5 -5
  69. data/ext/couchbase/protocol/cmd_get_and_touch.hxx +5 -5
  70. data/ext/couchbase/protocol/cmd_get_cluster_config.hxx +1 -6
  71. data/ext/couchbase/protocol/cmd_increment.hxx +5 -5
  72. data/ext/couchbase/protocol/cmd_info.hxx +0 -11
  73. data/ext/couchbase/protocol/cmd_insert.hxx +5 -5
  74. data/ext/couchbase/protocol/cmd_mutate_in.hxx +6 -6
  75. data/ext/couchbase/protocol/cmd_replace.hxx +5 -5
  76. data/ext/couchbase/protocol/cmd_touch.hxx +1 -1
  77. data/ext/couchbase/protocol/cmd_upsert.hxx +5 -5
  78. data/ext/couchbase/timeout_defaults.hxx +7 -0
  79. data/ext/couchbase/utils/connection_string.hxx +139 -0
  80. data/ext/extconf.rb +44 -11
  81. data/ext/test/main.cxx +93 -15
  82. data/ext/third_party/http_parser/Makefile +160 -0
  83. data/ext/third_party/json/Makefile +77 -0
  84. data/lib/couchbase/analytics_options.rb +18 -4
  85. data/lib/couchbase/binary_collection.rb +2 -2
  86. data/lib/couchbase/binary_collection_options.rb +2 -2
  87. data/lib/couchbase/bucket.rb +4 -4
  88. data/lib/couchbase/cluster.rb +60 -46
  89. data/lib/couchbase/collection.rb +13 -13
  90. data/lib/couchbase/collection_options.rb +15 -9
  91. data/{bin/console → lib/couchbase/datastructures.rb} +4 -7
  92. data/lib/couchbase/datastructures/couchbase_list.rb +171 -0
  93. data/lib/couchbase/datastructures/couchbase_map.rb +205 -0
  94. data/lib/couchbase/datastructures/couchbase_queue.rb +145 -0
  95. data/lib/couchbase/datastructures/couchbase_set.rb +138 -0
  96. data/lib/couchbase/errors.rb +66 -63
  97. data/lib/couchbase/libcouchbase.bundle +0 -0
  98. data/lib/couchbase/management/user_manager.rb +1 -1
  99. data/lib/couchbase/mutation_state.rb +1 -0
  100. data/lib/couchbase/query_options.rb +25 -2
  101. data/lib/couchbase/scope.rb +0 -7
  102. data/lib/couchbase/search_options.rb +7 -0
  103. data/lib/couchbase/version.rb +1 -1
  104. data/lib/couchbase/view_options.rb +4 -3
  105. metadata +20 -82
  106. data/.github/workflows/tests-6.0.3.yml +0 -52
  107. data/.github/workflows/tests-dev-preview.yml +0 -55
  108. data/.github/workflows/tests.yml +0 -50
  109. data/.gitignore +0 -20
  110. data/.gitmodules +0 -21
  111. data/.idea/.gitignore +0 -5
  112. data/.idea/dictionaries/gem_terms.xml +0 -18
  113. data/.idea/inspectionProfiles/Project_Default.xml +0 -8
  114. data/.idea/vcs.xml +0 -13
  115. data/bin/check-cluster +0 -31
  116. data/bin/fetch-stats +0 -19
  117. data/bin/init-cluster +0 -82
  118. data/bin/jenkins/build-extension +0 -35
  119. data/bin/jenkins/install-dependencies +0 -47
  120. data/bin/jenkins/test-with-cbdyncluster +0 -58
  121. data/bin/setup +0 -24
  122. data/ext/couchbase/configuration_monitor.hxx +0 -93
  123. data/ext/couchbase/operations/command.hxx +0 -163
  124. data/rbi/couchbase.rbi +0 -79
@@ -26,7 +26,7 @@ module Couchbase
26
26
 
27
27
  # @param [Couchbase::Backend] backend
28
28
  def initialize(backend, name)
29
- backend.open_bucket(name)
29
+ backend.open_bucket(name, true)
30
30
  @backend = backend
31
31
  @name = name
32
32
  end
@@ -60,7 +60,7 @@ module Couchbase
60
60
  #
61
61
  # @return [Collection]
62
62
  def default_collection
63
- default_scope.default_collection
63
+ Collection.new(@backend, @name, :_default, :_default)
64
64
  end
65
65
 
66
66
  # Performs query to view index.
@@ -69,7 +69,7 @@ module Couchbase
69
69
  # @param [String] view_name name of the view to query
70
70
  # @param [ViewOptions] options
71
71
  #
72
- # @return [ViewQueryResult]
72
+ # @return [ViewResult]
73
73
  def view_query(design_document_name, view_name, options = ViewOptions.new)
74
74
  resp = @backend.document_view(@name, design_document_name, view_name, options.namespace, {
75
75
  timeout: options.timeout,
@@ -84,7 +84,7 @@ module Couchbase
84
84
  group: options.group,
85
85
  group_level: options.group_level,
86
86
  key: (JSON.generate(options.key) unless options.key.nil?),
87
- keys: options.keys&.map { |key| JSON.generate(key) },
87
+ keys: (options.keys.map { |key| JSON.generate(key) } if options.keys),
88
88
  order: options.order,
89
89
  reduce: options.reduce,
90
90
  on_error: options.on_error,
@@ -67,18 +67,18 @@ module Couchbase
67
67
  pipeline_cap: options.pipeline_cap,
68
68
  metrics: options.metrics,
69
69
  profile: options.profile,
70
- positional_parameters: options.instance_variable_get("@positional_parameters")&.map { |p| JSON.dump(p) },
71
- named_parameters: options.instance_variable_get("@named_parameters")&.each_with_object({}) { |(n, v), o| o[n.to_s] = JSON.dump(v) },
72
- raw_parameters: options.instance_variable_get("@raw_parameters"),
73
- scan_consistency: options.instance_variable_get("@scan_consistency"),
74
- mutation_state: options.instance_variable_get("@mutation_state")&.tokens&.map { |t|
70
+ positional_parameters: options.export_positional_parameters,
71
+ named_parameters: options.export_named_parameters,
72
+ raw_parameters: options.raw_parameters,
73
+ scan_consistency: options.scan_consistency,
74
+ mutation_state: (options.mutation_state.tokens.map { |t|
75
75
  {
76
76
  bucket_name: t.bucket_name,
77
77
  partition_id: t.partition_id,
78
78
  partition_uuid: t.partition_uuid,
79
79
  sequence_number: t.sequence_number,
80
80
  }
81
- },
81
+ } if options.mutation_state),
82
82
  })
83
83
 
84
84
  QueryResult.new do |res|
@@ -119,9 +119,9 @@ module Couchbase
119
119
  scan_consistency: options.scan_consistency,
120
120
  readonly: options.readonly,
121
121
  priority: options.priority,
122
- positional_parameters: options.instance_variable_get("@positional_parameters")&.map { |p| JSON.dump(p) },
123
- named_parameters: options.instance_variable_get("@named_parameters")&.each_with_object({}) { |(n, v), o| o[n.to_s] = JSON.dump(v) },
124
- raw_parameters: options.instance_variable_get("@raw_parameters"),
122
+ positional_parameters: options.export_positional_parameters,
123
+ named_parameters: options.export_named_parameters,
124
+ raw_parameters: options.raw_parameters,
125
125
  })
126
126
 
127
127
  AnalyticsResult.new do |res|
@@ -165,17 +165,17 @@ module Couchbase
165
165
  highlight_style: options.highlight_style,
166
166
  highlight_fields: options.highlight_fields,
167
167
  fields: options.fields,
168
- sort: options.sort&.map { |v| JSON.generate(v) },
169
- facets: options.facets&.map { |(k, v)| [k, JSON.generate(v)] },
170
- scan_consistency: options.instance_variable_get("@scan_consistency"),
171
- mutation_state: options.instance_variable_get("@mutation_state")&.tokens&.map { |t|
168
+ sort: (options.sort.map { |v| JSON.generate(v) } if options.sort),
169
+ facets: (options.facets.map { |(k, v)| [k, JSON.generate(v)] } if options.facets),
170
+ scan_consistency: options.scan_consistency,
171
+ mutation_state: (options.mutation_state.tokens.map { |t|
172
172
  {
173
173
  bucket_name: t.bucket_name,
174
174
  partition_id: t.partition_id,
175
175
  partition_uuid: t.partition_uuid,
176
176
  sequence_number: t.sequence_number,
177
177
  }
178
- },
178
+ } if options.mutation_state),
179
179
  })
180
180
 
181
181
  SearchResult.new do |res|
@@ -209,35 +209,52 @@ module Couchbase
209
209
  row.explanation = JSON.parse(r[:explanation]) if r[:explanation]
210
210
  end
211
211
  end
212
- res.facets = resp[:facets]&.each_with_object({}) do |(k, v), o|
213
- facet = case options.facets[k]
214
- when SearchFacet::SearchFacetTerm
215
- SearchFacetResult::TermFacetResult.new do |f|
216
- f.terms = v[:terms]&.map do |t|
217
- SearchFacetResult::TermFacetResult::TermFacet.new(t[:term], t[:count])
218
- end || []
219
- end
220
- when SearchFacet::SearchFacetDateRange
221
- SearchFacetResult::DateRangeFacetResult.new do |f|
222
- f.date_ranges = v[:date_ranges]&.map do |r|
223
- SearchFacetResult::DateRangeFacetResult::DateRangeFacet.new(r[:name], r[:count], r[:start_time], r[:end_time])
224
- end || []
212
+ if resp[:facets]
213
+ res.facets = resp[:facets].each_with_object({}) do |(k, v), o|
214
+ facet = case options.facets[k]
215
+ when SearchFacet::SearchFacetTerm
216
+ SearchFacetResult::TermFacetResult.new do |f|
217
+ f.terms =
218
+ if v[:terms]
219
+ v[:terms].map do |t|
220
+ SearchFacetResult::TermFacetResult::TermFacet.new(t[:term], t[:count])
221
+ end
222
+ else
223
+ []
224
+ end
225
+ end
226
+ when SearchFacet::SearchFacetDateRange
227
+ SearchFacetResult::DateRangeFacetResult.new do |f|
228
+ f.date_ranges =
229
+ if v[:date_ranges]
230
+ v[:date_ranges].map do |r|
231
+ SearchFacetResult::DateRangeFacetResult::DateRangeFacet.new(r[:name], r[:count], r[:start_time], r[:end_time])
232
+ end
233
+ else
234
+ []
235
+ end
236
+ end
237
+ when SearchFacet::SearchFacetNumericRange
238
+ SearchFacetResult::NumericRangeFacetResult.new do |f|
239
+ f.numeric_ranges =
240
+ if v[:numeric_ranges]
241
+ v[:numeric_ranges].map do |r|
242
+ SearchFacetResult::NumericRangeFacetResult::NumericRangeFacet.new(r[:name], r[:count], r[:min], r[:max])
243
+ end
244
+ else
245
+ []
246
+ end
247
+ end
248
+ else
249
+ next # ignore unknown facet result
225
250
  end
226
- when SearchFacet::SearchFacetNumericRange
227
- SearchFacetResult::NumericRangeFacetResult.new do |f|
228
- f.numeric_ranges = v[:numeric_ranges]&.map do |r|
229
- SearchFacetResult::NumericRangeFacetResult::NumericRangeFacet.new(r[:name], r[:count], r[:min], r[:max])
230
- end || []
231
- end
232
- else
233
- next # ignore unknown facet result
234
- end
235
- facet.name = v[:name]
236
- facet.field = v[:field]
237
- facet.total = v[:total]
238
- facet.missing = v[:missing]
239
- facet.other = v[:other]
240
- o[k] = facet
251
+ facet.name = v[:name]
252
+ facet.field = v[:field]
253
+ facet.total = v[:total]
254
+ facet.missing = v[:missing]
255
+ facet.other = v[:other]
256
+ o[k] = facet
257
+ end
241
258
  end
242
259
  end
243
260
  end
@@ -302,9 +319,6 @@ module Couchbase
302
319
  # @param [String] connection_string connection string used to locate the Couchbase Cluster
303
320
  # @param [ClusterOptions] options custom options when creating the cluster connection
304
321
  def initialize(connection_string, options)
305
- conn_info = Backend.parse_connection_string(connection_string)
306
- raise ArgumentError, "missing hostname" if conn_info[:nodes].empty?
307
- hostname = conn_info[:nodes].first[:address]
308
322
  raise ArgumentError, "options must have authenticator configured" unless options.authenticator
309
323
  username = options.authenticator.username
310
324
  raise ArgumentError, "missing username" unless username
@@ -312,7 +326,7 @@ module Couchbase
312
326
  raise ArgumentError, "missing password" unless password
313
327
 
314
328
  @backend = Backend.new
315
- @backend.open(hostname, username, password)
329
+ @backend.open(connection_string, username, password, {})
316
330
  end
317
331
  end
318
332
  end
@@ -52,7 +52,7 @@ module Couchbase
52
52
  resp = if options.need_projected_get?
53
53
  @backend.document_get_projected(bucket_name, "#{@scope_name}.#{@name}", id,
54
54
  options.timeout,
55
- options.with_expiration,
55
+ options.with_expiry,
56
56
  options.projections,
57
57
  options.preserve_array_indexes)
58
58
  else
@@ -63,7 +63,7 @@ module Couchbase
63
63
  res.cas = resp[:cas]
64
64
  res.flags = resp[:flags]
65
65
  res.encoded = resp[:content]
66
- res.expiration = resp[:expiration] if resp.key?(:expiration)
66
+ res.expiry = resp[:expiry] if resp.key?(:expiry)
67
67
  end
68
68
  end
69
69
 
@@ -84,15 +84,15 @@ module Couchbase
84
84
  end
85
85
  end
86
86
 
87
- # Fetches a full document and resets its expiration time to the expiration duration provided
87
+ # Fetches a full document and resets its expiration time to the duration provided
88
88
  #
89
89
  # @param [String] id the document id which is used to uniquely identify it.
90
- # @param [Integer] expiration the new expiration time for the document
90
+ # @param [Integer] expiry the new expiration time for the document
91
91
  # @param [GetAndTouchOptions] options request customization
92
92
  #
93
93
  # @return [GetResult]
94
- def get_and_touch(id, expiration, options = GetAndTouchOptions.new)
95
- resp = @backend.document_get_and_touch(bucket_name, "#{@scope_name}.#{@name}", id, options.timeout, expiration)
94
+ def get_and_touch(id, expiry, options = GetAndTouchOptions.new)
95
+ resp = @backend.document_get_and_touch(bucket_name, "#{@scope_name}.#{@name}", id, options.timeout, expiry)
96
96
  GetResult.new do |res|
97
97
  res.transcoder = options.transcoder
98
98
  res.cas = resp[:cas]
@@ -159,7 +159,7 @@ module Couchbase
159
159
  blob, flags = options.transcoder.encode(content)
160
160
  resp = @backend.document_insert(bucket_name, "#{@scope_name}.#{@name}", id, options.timeout, blob, flags, {
161
161
  durability_level: options.durability_level,
162
- expiration: options.expiration,
162
+ expiry: options.expiry,
163
163
  })
164
164
  MutationResult.new do |res|
165
165
  res.cas = resp[:cas]
@@ -178,7 +178,7 @@ module Couchbase
178
178
  blob, flags = options.transcoder.encode(content)
179
179
  resp = @backend.document_upsert(bucket_name, "#{@scope_name}.#{@name}", id, options.timeout, blob, flags, {
180
180
  durability_level: options.durability_level,
181
- expiration: options.expiration,
181
+ expiry: options.expiry,
182
182
  })
183
183
  MutationResult.new do |res|
184
184
  res.cas = resp[:cas]
@@ -197,7 +197,7 @@ module Couchbase
197
197
  blob, flags = options.transcoder.encode(content)
198
198
  resp = @backend.document_replace(bucket_name, "#{@scope_name}.#{@name}", id, options.timeout, blob, flags, {
199
199
  durability_level: options.durability_level,
200
- expiration: options.expiration,
200
+ expiry: options.expiry,
201
201
  cas: options.cas,
202
202
  })
203
203
  MutationResult.new do |res|
@@ -209,12 +209,12 @@ module Couchbase
209
209
  # Update the expiration of the document with the given id
210
210
  #
211
211
  # @param [String] id the document id which is used to uniquely identify it.
212
- # @param [Integer] expiration new expiration time for the document
212
+ # @param [Integer] expiry new expiration time for the document
213
213
  # @param [TouchOptions] options request customization
214
214
  #
215
215
  # @return [MutationResult]
216
- def touch(id, expiration, options = TouchOptions.new)
217
- resp = @backend.document_touch(bucket_name, "#{@scope_name}.#{@name}", id, options.timeout, expiration)
216
+ def touch(id, expiry, options = TouchOptions.new)
217
+ resp = @backend.document_touch(bucket_name, "#{@scope_name}.#{@name}", id, options.timeout, expiry)
218
218
  MutationResult.new do |res|
219
219
  res.cas = resp[:cas]
220
220
  end
@@ -291,7 +291,7 @@ module Couchbase
291
291
  store_semantics: options.store_semantics,
292
292
  access_deleted: options.access_deleted,
293
293
  cas: options.cas,
294
- expiration: options.expiration,
294
+ expiry: options.expiry,
295
295
  }
296
296
  )
297
297
  res = MutateInResult.new do |res|
@@ -21,7 +21,7 @@ module Couchbase
21
21
  class Collection
22
22
  class GetOptions < CommonOptions
23
23
  # @return [Boolean] if the expiration should also fetched with get
24
- attr_accessor :with_expiration
24
+ attr_accessor :with_expiry
25
25
 
26
26
  # @return [JsonTranscoder] transcoder used for decoding
27
27
  attr_accessor :transcoder
@@ -30,7 +30,7 @@ module Couchbase
30
30
  def initialize
31
31
  @transcoder = JsonTranscoder.new
32
32
  @preserve_array_indexes = false
33
- @with_expiration = nil
33
+ @with_expiry = nil
34
34
  @projections = nil
35
35
  yield self if block_given?
36
36
  end
@@ -57,7 +57,7 @@ module Couchbase
57
57
  # @api private
58
58
  # @return [Boolean]
59
59
  def need_projected_get?
60
- @with_expiration || !@projections.nil?
60
+ @with_expiry || !@projections.nil?
61
61
  end
62
62
  end
63
63
 
@@ -88,9 +88,10 @@ module Couchbase
88
88
  attr_accessor :cas
89
89
 
90
90
  # @return [Integer] the expiration if fetched and present
91
- attr_accessor :expiration
91
+ attr_accessor :expiry
92
92
 
93
93
  # @return [String] The encoded content when loading the document
94
+ # @api private
94
95
  attr_accessor :encoded
95
96
 
96
97
  # Decodes the content of the document using given (or default transcoder)
@@ -108,6 +109,7 @@ module Couchbase
108
109
  end
109
110
 
110
111
  # @return [Integer] The flags from the operation
112
+ # @api private
111
113
  attr_accessor :flags
112
114
 
113
115
  # @return [JsonTranscoder] The default transcoder which should be used
@@ -186,7 +188,7 @@ module Couchbase
186
188
 
187
189
  class InsertOptions < CommonOptions
188
190
  # @return [Integer] expiration time to associate with the document
189
- attr_accessor :expiration
191
+ attr_accessor :expiry
190
192
 
191
193
  # @return [Proc] transcoder used for encoding
192
194
  attr_accessor :transcoder
@@ -204,7 +206,7 @@ module Couchbase
204
206
 
205
207
  class UpsertOptions < CommonOptions
206
208
  # @return [Integer] expiration time to associate with the document
207
- attr_accessor :expiration
209
+ attr_accessor :expiry
208
210
 
209
211
  # @return [JsonTranscoder] transcoder used for encoding
210
212
  attr_accessor :transcoder
@@ -222,7 +224,7 @@ module Couchbase
222
224
 
223
225
  class ReplaceOptions < CommonOptions
224
226
  # @return [Integer] expiration time to associate with the document
225
- attr_accessor :expiration
227
+ attr_accessor :expiry
226
228
 
227
229
  # @return [JsonTranscoder] transcoder used for encoding
228
230
  attr_accessor :transcoder
@@ -301,7 +303,7 @@ module Couchbase
301
303
  #
302
304
  # @return [Boolean] true if a value is present at the index, false otherwise
303
305
  def exists?(index)
304
- encoded[index]&.exists
306
+ !encoded[index].nil? && encoded[index].exists
305
307
  end
306
308
 
307
309
  # @return [Array<SubDocumentField>] holds the encoded subdocument responses
@@ -330,7 +332,7 @@ module Couchbase
330
332
 
331
333
  class MutateInOptions < CommonOptions
332
334
  # @return [Integer] expiration time to associate with the document
333
- attr_accessor :expiration
335
+ attr_accessor :expiry
334
336
 
335
337
  # Describes how the outer document store semantics on subdoc should act
336
338
  #
@@ -384,18 +386,22 @@ module Couchbase
384
386
  yield self if block_given?
385
387
  end
386
388
 
389
+ # @api private
387
390
  def success?
388
391
  first_error_index.nil?
389
392
  end
390
393
 
394
+ # @api private
391
395
  def first_error
392
396
  encoded[first_error_index].error
393
397
  end
394
398
 
395
399
  # @return [Array<SubDocumentField>] holds the encoded subdocument responses
400
+ # @api private
396
401
  attr_accessor :encoded
397
402
 
398
403
  # @return [Integer, nil] index of first operation entry that generated an error
404
+ # @api private
399
405
  attr_accessor :first_error_index
400
406
 
401
407
  # @return [JsonTranscoder] The default transcoder which should be used
@@ -1,5 +1,3 @@
1
- #!/usr/bin/env ruby
2
-
3
1
  # Copyright 2020 Couchbase, Inc.
4
2
  #
5
3
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,8 +12,7 @@
14
12
  # See the License for the specific language governing permissions and
15
13
  # limitations under the License.
16
14
 
17
- require "bundler/setup"
18
- require "irb"
19
- require "couchbase"
20
-
21
- IRB.start(__FILE__)
15
+ require "couchbase/datastructures/couchbase_list"
16
+ require "couchbase/datastructures/couchbase_set"
17
+ require "couchbase/datastructures/couchbase_queue"
18
+ require "couchbase/datastructures/couchbase_map"
@@ -0,0 +1,171 @@
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 "couchbase/collection"
16
+ require "couchbase/errors"
17
+
18
+ module Couchbase
19
+ module Datastructures
20
+ # A {CouchbaseList} is implements +Enumerable+ interface and backed by {Collection} document (more specifically
21
+ # a JSON array).
22
+ #
23
+ # Note that as such, a {CouchbaseList} is restricted to the types that JSON array can contain.
24
+ class CouchbaseList
25
+ include Enumerable
26
+
27
+ # Create a new List, backed by the document identified by +id+ in +collection+.
28
+ #
29
+ # @param [String] id the id of the document to back the list.
30
+ # @param [Collection] collection the Couchbase collection through which to interact with the document.
31
+ # @param [CouchbaseListOptions] options customization of the datastructure
32
+ def initialize(id, collection, options = CouchbaseListOptions.new)
33
+ @id = id
34
+ @collection = collection
35
+ @options = options
36
+ @cas = 0
37
+ end
38
+
39
+ # Calls the given block once for each element in the list, passing that element as a parameter.
40
+ #
41
+ # @yieldparam [Object] item
42
+ #
43
+ # @return [CouchbaseList, Enumerable]
44
+ def each
45
+ if block_given?
46
+ begin
47
+ result = @collection.get(@id, @options.get_options)
48
+ current = result.content
49
+ @cas = result.cas
50
+ rescue Error::DocumentNotFound
51
+ current = []
52
+ @cas = 0
53
+ end
54
+ current.each do |entry|
55
+ yield entry
56
+ end
57
+ self
58
+ else
59
+ enum_for(:each)
60
+ end
61
+ end
62
+
63
+ # @return [Integer] returns the number of elements in the list.
64
+ def length
65
+ result = @collection.lookup_in(@id, [
66
+ LookupInSpec.count("")
67
+ ], @options.lookup_in_options)
68
+ result.content(0)
69
+ rescue Error::DocumentNotFound
70
+ 0
71
+ end
72
+
73
+ alias_method :size, :length
74
+
75
+ # @return [Boolean] returns true if list is empty
76
+ def empty?
77
+ size.zero?
78
+ end
79
+
80
+ # Appends the given object(s) on to the end of this error. This expression returns the array itself, so several
81
+ # appends may be chained together.
82
+ #
83
+ # @param [Object...] obj object(s) to append
84
+ # @return [CouchbaseList]
85
+ def push(*obj)
86
+ @collection.mutate_in(@id, [
87
+ MutateInSpec.array_append("", obj)
88
+ ], @options.mutate_in_options)
89
+ self
90
+ end
91
+
92
+ alias_method :append, :push
93
+
94
+ # Prepends objects to the front of the list, moving other elements upwards
95
+ #
96
+ # @param [Object...] obj object(s) to prepend
97
+ # @return [CouchbaseList]
98
+ def unshift(*obj)
99
+ @collection.mutate_in(@id, [
100
+ MutateInSpec.array_prepend("", obj)
101
+ ], @options.mutate_in_options)
102
+ self
103
+ end
104
+
105
+ alias_method :prepend, :unshift
106
+
107
+ # Inserts the given values before the element with the given +index+.
108
+ #
109
+ # @param [Integer] index
110
+ # @param [Object...] obj object(s) to insert
111
+ # @return [CouchbaseList]
112
+ def insert(index, *obj)
113
+ @collection.mutate_in(@id, [
114
+ MutateInSpec.array_insert("[#{index.to_i}]", obj)
115
+ ])
116
+ self
117
+ end
118
+
119
+ # Returns the element at +index+. A negative index counts from the end. Returns +nil+ if the index is out of range.
120
+ #
121
+ # @param [Integer] index
122
+ # @return [Object, nil]
123
+ def at(index)
124
+ result = @collection.lookup_in(@id, [
125
+ LookupInSpec.get("[#{index.to_i}]")
126
+ ], @options.lookup_in_options)
127
+ result.exists?(0) ? result.content(0) : nil
128
+ rescue Error::DocumentNotFound
129
+ nil
130
+ end
131
+
132
+ alias_method :[], :at
133
+
134
+ # Deletes the element at the specified +index+, returning that element, or nil
135
+ #
136
+ # @param [Integer] index
137
+ # @return [CouchbaseList]
138
+ def delete_at(index)
139
+ @collection.mutate_in(@id, [
140
+ MutateInSpec.remove("[#{index.to_i}]")
141
+ ])
142
+ self
143
+ rescue Error::DocumentNotFound
144
+ self
145
+ end
146
+
147
+ # Removes all elements from the list
148
+ def clear
149
+ @collection.remove(@id, @options.remove_options)
150
+ nil
151
+ rescue Error::DocumentNotFound
152
+ nil
153
+ end
154
+ end
155
+
156
+ class CouchbaseListOptions
157
+ attr_accessor :get_options
158
+ attr_accessor :lookup_in_options
159
+ attr_accessor :mutate_in_options
160
+ attr_accessor :remove_options
161
+
162
+ def initialize
163
+ @get_options = Collection::GetOptions.new
164
+ @remove_options = Collection::RemoveOptions.new
165
+ @lookup_in_options = Collection::LookupInOptions.new
166
+ @mutate_in_options = Collection::MutateInOptions.new
167
+ @mutate_in_options.store_semantics = :upsert
168
+ end
169
+ end
170
+ end
171
+ end