couchbase 3.0.0.alpha.5 → 3.0.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (123) 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/management/user_manager.rb +1 -1
  98. data/lib/couchbase/mutation_state.rb +1 -0
  99. data/lib/couchbase/query_options.rb +25 -2
  100. data/lib/couchbase/scope.rb +0 -7
  101. data/lib/couchbase/search_options.rb +7 -0
  102. data/lib/couchbase/version.rb +1 -1
  103. data/lib/couchbase/view_options.rb +4 -3
  104. metadata +20 -82
  105. data/.github/workflows/tests-6.0.3.yml +0 -52
  106. data/.github/workflows/tests-dev-preview.yml +0 -55
  107. data/.github/workflows/tests.yml +0 -50
  108. data/.gitignore +0 -20
  109. data/.gitmodules +0 -21
  110. data/.idea/.gitignore +0 -5
  111. data/.idea/dictionaries/gem_terms.xml +0 -18
  112. data/.idea/inspectionProfiles/Project_Default.xml +0 -8
  113. data/.idea/vcs.xml +0 -13
  114. data/bin/check-cluster +0 -31
  115. data/bin/fetch-stats +0 -19
  116. data/bin/init-cluster +0 -82
  117. data/bin/jenkins/build-extension +0 -35
  118. data/bin/jenkins/install-dependencies +0 -47
  119. data/bin/jenkins/test-with-cbdyncluster +0 -58
  120. data/bin/setup +0 -24
  121. data/ext/couchbase/configuration_monitor.hxx +0 -93
  122. data/ext/couchbase/operations/command.hxx +0 -163
  123. 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