couchbase 3.4.3 → 3.4.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (148) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/ext/couchbase/CMakeLists.txt +15 -1
  4. data/ext/couchbase/core/bucket.cxx +183 -152
  5. data/ext/couchbase/core/bucket.hxx +17 -4
  6. data/ext/couchbase/core/cluster.hxx +34 -13
  7. data/ext/couchbase/core/cluster_options.hxx +3 -0
  8. data/ext/couchbase/core/crud_component.cxx +51 -22
  9. data/ext/couchbase/core/error_context/key_value.cxx +2 -1
  10. data/ext/couchbase/core/error_context/key_value.hxx +10 -12
  11. data/ext/couchbase/core/impl/build_deferred_query_indexes.cxx +115 -50
  12. data/ext/couchbase/core/impl/cluster.cxx +6 -0
  13. data/ext/couchbase/core/impl/create_bucket.cxx +155 -0
  14. data/ext/couchbase/core/impl/create_query_index.cxx +172 -59
  15. data/ext/couchbase/core/impl/dns_srv_tracker.cxx +2 -1
  16. data/ext/couchbase/core/impl/drop_bucket.cxx +66 -0
  17. data/ext/couchbase/core/impl/drop_query_index.cxx +138 -59
  18. data/ext/couchbase/core/impl/flush_bucket.cxx +66 -0
  19. data/ext/couchbase/core/impl/get_all_buckets.cxx +163 -0
  20. data/ext/couchbase/core/impl/get_all_query_indexes.cxx +67 -37
  21. data/ext/couchbase/core/impl/get_bucket.cxx +153 -0
  22. data/ext/couchbase/core/impl/internal_manager_error_context.cxx +113 -0
  23. data/ext/couchbase/core/impl/internal_manager_error_context.hxx +60 -0
  24. data/ext/couchbase/core/impl/key_value_error_category.cxx +2 -4
  25. data/ext/couchbase/core/impl/key_value_error_context.cxx +98 -0
  26. data/ext/couchbase/core/impl/lookup_in.cxx +1 -0
  27. data/ext/couchbase/core/impl/lookup_in_all_replicas.cxx +176 -0
  28. data/ext/couchbase/core/impl/lookup_in_all_replicas.hxx +80 -0
  29. data/ext/couchbase/core/impl/lookup_in_any_replica.cxx +167 -0
  30. data/ext/couchbase/core/impl/lookup_in_any_replica.hxx +75 -0
  31. data/ext/couchbase/core/impl/lookup_in_replica.cxx +97 -0
  32. data/ext/couchbase/core/impl/lookup_in_replica.hxx +67 -0
  33. data/ext/couchbase/core/impl/manager_error_context.cxx +100 -0
  34. data/ext/couchbase/core/impl/query.cxx +1 -0
  35. data/ext/couchbase/core/impl/query_error_context.cxx +75 -0
  36. data/ext/couchbase/core/impl/update_bucket.cxx +130 -0
  37. data/ext/couchbase/core/impl/watch_query_indexes.cxx +53 -29
  38. data/ext/couchbase/core/io/dns_client.cxx +111 -40
  39. data/ext/couchbase/core/io/dns_config.cxx +5 -4
  40. data/ext/couchbase/core/io/http_session.hxx +24 -1
  41. data/ext/couchbase/core/io/mcbp_command.hxx +9 -2
  42. data/ext/couchbase/core/io/mcbp_session.cxx +80 -43
  43. data/ext/couchbase/core/io/mcbp_session.hxx +4 -3
  44. data/ext/couchbase/core/logger/custom_rotating_file_sink.cxx +1 -1
  45. data/ext/couchbase/core/logger/logger.cxx +80 -20
  46. data/ext/couchbase/core/logger/logger.hxx +31 -0
  47. data/ext/couchbase/core/meta/features.hxx +25 -0
  48. data/ext/couchbase/core/operations/document_lookup_in_all_replicas.hxx +192 -0
  49. data/ext/couchbase/core/operations/document_lookup_in_any_replica.hxx +188 -0
  50. data/ext/couchbase/core/operations/document_query.cxx +11 -0
  51. data/ext/couchbase/core/operations/document_query.hxx +1 -0
  52. data/ext/couchbase/core/operations.hxx +2 -0
  53. data/ext/couchbase/core/origin.cxx +270 -0
  54. data/ext/couchbase/core/origin.hxx +2 -0
  55. data/ext/couchbase/core/protocol/client_response.hxx +1 -0
  56. data/ext/couchbase/core/protocol/cmd_hello.hxx +1 -0
  57. data/ext/couchbase/core/protocol/cmd_lookup_in_replica.cxx +107 -0
  58. data/ext/couchbase/core/protocol/cmd_lookup_in_replica.hxx +137 -0
  59. data/ext/couchbase/core/protocol/hello_feature.hxx +6 -0
  60. data/ext/couchbase/core/protocol/hello_feature_fmt.hxx +3 -0
  61. data/ext/couchbase/core/protocol/status.cxx +2 -2
  62. data/ext/couchbase/core/range_scan_options.cxx +3 -27
  63. data/ext/couchbase/core/range_scan_options.hxx +13 -17
  64. data/ext/couchbase/core/range_scan_orchestrator.cxx +388 -170
  65. data/ext/couchbase/core/range_scan_orchestrator.hxx +13 -2
  66. data/ext/couchbase/core/range_scan_orchestrator_options.hxx +5 -3
  67. data/ext/couchbase/core/scan_options.hxx +0 -19
  68. data/ext/couchbase/core/scan_result.cxx +19 -5
  69. data/ext/couchbase/core/scan_result.hxx +5 -2
  70. data/ext/couchbase/core/timeout_defaults.hxx +2 -3
  71. data/ext/couchbase/core/topology/capabilities.hxx +3 -0
  72. data/ext/couchbase/core/topology/capabilities_fmt.hxx +8 -0
  73. data/ext/couchbase/core/topology/collections_manifest_fmt.hxx +1 -1
  74. data/ext/couchbase/core/topology/configuration.hxx +15 -0
  75. data/ext/couchbase/core/topology/configuration_json.hxx +6 -1
  76. data/ext/couchbase/core/utils/connection_string.cxx +62 -47
  77. data/ext/couchbase/core/utils/connection_string.hxx +1 -0
  78. data/ext/couchbase/couchbase/analytics_error_context.hxx +1 -1
  79. data/ext/couchbase/couchbase/behavior_options.hxx +19 -2
  80. data/ext/couchbase/couchbase/bucket_manager.hxx +135 -0
  81. data/ext/couchbase/couchbase/build_query_index_options.hxx +0 -30
  82. data/ext/couchbase/couchbase/cluster.hxx +14 -0
  83. data/ext/couchbase/couchbase/collection.hxx +111 -0
  84. data/ext/couchbase/couchbase/collection_query_index_manager.hxx +7 -48
  85. data/ext/couchbase/couchbase/create_bucket_options.hxx +41 -0
  86. data/ext/couchbase/couchbase/create_primary_query_index_options.hxx +0 -29
  87. data/ext/couchbase/couchbase/create_query_index_options.hxx +0 -33
  88. data/ext/couchbase/couchbase/drop_bucket_options.hxx +41 -0
  89. data/ext/couchbase/couchbase/drop_primary_query_index_options.hxx +0 -30
  90. data/ext/couchbase/couchbase/drop_query_index_options.hxx +0 -31
  91. data/ext/couchbase/couchbase/error_codes.hxx +1 -2
  92. data/ext/couchbase/couchbase/error_context.hxx +10 -2
  93. data/ext/couchbase/couchbase/flush_bucket_options.hxx +41 -0
  94. data/ext/couchbase/{core/topology/error_map_fmt.hxx → couchbase/fmt/key_value_error_map_attribute.hxx} +21 -21
  95. data/ext/couchbase/couchbase/get_all_buckets_options.hxx +44 -0
  96. data/ext/couchbase/couchbase/get_all_query_indexes_options.hxx +0 -30
  97. data/ext/couchbase/couchbase/get_and_lock_options.hxx +2 -2
  98. data/ext/couchbase/couchbase/get_and_touch_options.hxx +2 -2
  99. data/ext/couchbase/couchbase/get_bucket_options.hxx +43 -0
  100. data/ext/couchbase/couchbase/get_options.hxx +2 -2
  101. data/ext/couchbase/couchbase/insert_options.hxx +3 -3
  102. data/ext/couchbase/couchbase/key_value_error_context.hxx +7 -2
  103. data/ext/couchbase/couchbase/lookup_in_all_replicas_options.hxx +109 -0
  104. data/ext/couchbase/couchbase/lookup_in_any_replica_options.hxx +101 -0
  105. data/ext/couchbase/couchbase/lookup_in_options.hxx +2 -2
  106. data/ext/couchbase/couchbase/lookup_in_replica_result.hxx +74 -0
  107. data/ext/couchbase/couchbase/lookup_in_result.hxx +26 -0
  108. data/ext/couchbase/couchbase/management/bucket_settings.hxx +116 -0
  109. data/ext/couchbase/couchbase/manager_error_context.hxx +29 -53
  110. data/ext/couchbase/couchbase/mutate_in_options.hxx +2 -2
  111. data/ext/couchbase/couchbase/query_error_context.hxx +3 -1
  112. data/ext/couchbase/couchbase/query_index_manager.hxx +16 -83
  113. data/ext/couchbase/couchbase/query_options.hxx +18 -0
  114. data/ext/couchbase/couchbase/remove_options.hxx +2 -2
  115. data/ext/couchbase/couchbase/replace_options.hxx +3 -3
  116. data/ext/couchbase/couchbase/security_options.hxx +15 -0
  117. data/ext/couchbase/couchbase/subdocument_error_context.hxx +4 -2
  118. data/ext/couchbase/couchbase/touch_options.hxx +2 -2
  119. data/ext/couchbase/couchbase/unlock_options.hxx +2 -2
  120. data/ext/couchbase/couchbase/update_bucket_options.hxx +41 -0
  121. data/ext/couchbase/couchbase/upsert_options.hxx +3 -3
  122. data/ext/couchbase/couchbase/watch_query_indexes_options.hxx +0 -31
  123. data/ext/couchbase/test/CMakeLists.txt +1 -0
  124. data/ext/couchbase/test/test_integration_collections.cxx +6 -0
  125. data/ext/couchbase/test/test_integration_crud.cxx +5 -0
  126. data/ext/couchbase/test/test_integration_examples.cxx +137 -1
  127. data/ext/couchbase/test/test_integration_management.cxx +709 -266
  128. data/ext/couchbase/test/test_integration_query.cxx +19 -7
  129. data/ext/couchbase/test/test_integration_range_scan.cxx +351 -112
  130. data/ext/couchbase/test/test_integration_search.cxx +10 -1
  131. data/ext/couchbase/test/test_integration_subdoc.cxx +655 -0
  132. data/ext/couchbase/test/test_transaction_public_async_api.cxx +13 -12
  133. data/ext/couchbase/test/test_transaction_public_blocking_api.cxx +27 -21
  134. data/ext/couchbase/test/test_unit_connection_string.cxx +29 -0
  135. data/ext/couchbase/test/test_unit_query.cxx +75 -0
  136. data/ext/couchbase.cxx +583 -29
  137. data/ext/revisions.rb +3 -3
  138. data/lib/couchbase/cluster.rb +1 -1
  139. data/lib/couchbase/collection.rb +108 -0
  140. data/lib/couchbase/collection_options.rb +100 -0
  141. data/lib/couchbase/errors.rb +5 -0
  142. data/lib/couchbase/key_value_scan.rb +125 -0
  143. data/lib/couchbase/options.rb +151 -0
  144. data/lib/couchbase/scope.rb +1 -1
  145. data/lib/couchbase/utils/time.rb +14 -1
  146. data/lib/couchbase/version.rb +1 -1
  147. metadata +41 -7
  148. data/ext/couchbase/core/impl/collection_query_index_manager.cxx +0 -93
@@ -74,244 +74,358 @@ TEST_CASE("integration: bucket management", "[integration]")
74
74
 
75
75
  SECTION("crud")
76
76
  {
77
- couchbase::core::management::cluster::bucket_settings bucket_settings;
78
- bucket_settings.name = bucket_name;
79
- bucket_settings.ram_quota_mb = 100;
80
- bucket_settings.num_replicas = 1;
81
- bucket_settings.bucket_type = couchbase::core::management::cluster::bucket_type::couchbase;
82
- bucket_settings.eviction_policy = couchbase::core::management::cluster::bucket_eviction_policy::value_only;
83
- bucket_settings.flush_enabled = true;
84
- if (integration.cluster_version().is_enterprise()) {
85
- bucket_settings.max_expiry = 10;
86
- bucket_settings.compression_mode = couchbase::core::management::cluster::bucket_compression::active;
87
- }
88
- bucket_settings.replica_indexes = true;
89
- bucket_settings.conflict_resolution_type = couchbase::core::management::cluster::bucket_conflict_resolution::sequence_number;
90
-
91
- {
92
- couchbase::core::operations::management::bucket_create_request req;
93
- req.bucket = bucket_settings;
94
- auto resp = test::utils::execute(integration.cluster, req);
95
- REQUIRE_SUCCESS(resp.ctx.ec);
96
- }
97
-
98
- {
99
- auto resp = wait_for_bucket_created(integration, bucket_name);
100
- REQUIRE_SUCCESS(resp.ctx.ec);
101
- REQUIRE(bucket_settings.bucket_type == resp.bucket.bucket_type);
102
- REQUIRE(bucket_settings.name == resp.bucket.name);
103
- REQUIRE(Approx(bucket_settings.ram_quota_mb).margin(5) == resp.bucket.ram_quota_mb);
104
- REQUIRE(bucket_settings.num_replicas == resp.bucket.num_replicas);
105
- REQUIRE(bucket_settings.flush_enabled == resp.bucket.flush_enabled);
106
- REQUIRE(bucket_settings.max_expiry == resp.bucket.max_expiry);
107
- REQUIRE(bucket_settings.eviction_policy == resp.bucket.eviction_policy);
108
- REQUIRE(bucket_settings.compression_mode == resp.bucket.compression_mode);
109
- REQUIRE(bucket_settings.replica_indexes == resp.bucket.replica_indexes);
110
- }
111
- std::uint64_t old_quota_mb{ 0 };
112
- {
113
- couchbase::core::operations::management::bucket_get_all_request req{};
114
- auto resp = test::utils::execute(integration.cluster, req);
115
- INFO(resp.ctx.http_body);
116
- REQUIRE_SUCCESS(resp.ctx.ec);
117
- bool found = false;
118
- for (const auto& bucket : resp.buckets) {
119
- if (bucket.name != bucket_name) {
120
- continue;
121
- }
122
- found = true;
123
- REQUIRE(bucket_settings.bucket_type == bucket.bucket_type);
124
- REQUIRE(bucket_settings.name == bucket.name);
125
- REQUIRE(bucket_settings.ram_quota_mb == bucket.ram_quota_mb);
126
- old_quota_mb = bucket_settings.ram_quota_mb;
127
- REQUIRE(bucket_settings.num_replicas == bucket.num_replicas);
128
- REQUIRE(bucket_settings.flush_enabled == bucket.flush_enabled);
129
- REQUIRE(bucket_settings.max_expiry == bucket.max_expiry);
130
- REQUIRE(bucket_settings.eviction_policy == bucket.eviction_policy);
131
- REQUIRE(bucket_settings.compression_mode == bucket.compression_mode);
132
- REQUIRE(bucket_settings.replica_indexes == bucket.replica_indexes);
133
- break;
134
- }
135
- REQUIRE(found);
136
- }
137
-
138
- {
139
- bucket_settings.ram_quota_mb = old_quota_mb + 20;
140
- couchbase::core::operations::management::bucket_update_request req;
141
- req.bucket = bucket_settings;
142
- auto resp = test::utils::execute(integration.cluster, req);
143
- REQUIRE_SUCCESS(resp.ctx.ec);
144
- }
145
-
146
- auto ram_quota_updated = test::utils::wait_until([&integration, &bucket_name, old_quota_mb]() {
147
- couchbase::core::operations::management::bucket_get_request req{ bucket_name };
148
- auto resp = test::utils::execute(integration.cluster, req);
149
- return !resp.ctx.ec && resp.bucket.ram_quota_mb > old_quota_mb;
150
- });
151
- REQUIRE(ram_quota_updated);
152
-
153
- {
154
- couchbase::core::operations::management::bucket_drop_request req{ bucket_name };
155
- auto resp = test::utils::execute(integration.cluster, req);
156
- REQUIRE_SUCCESS(resp.ctx.ec);
157
- }
158
-
159
- {
160
- couchbase::core::operations::management::bucket_get_request req{ bucket_name };
161
- auto resp = retry_on_error(integration, req, {});
162
- REQUIRE(resp.ctx.ec == couchbase::errc::common::bucket_not_found);
163
- }
164
-
165
- {
166
- couchbase::core::operations::management::bucket_get_all_request req;
167
- auto resp = test::utils::execute(integration.cluster, req);
168
- REQUIRE_SUCCESS(resp.ctx.ec);
169
- REQUIRE(!resp.buckets.empty());
170
- auto known_buckets =
171
- std::count_if(resp.buckets.begin(), resp.buckets.end(), [&bucket_name](auto& entry) { return entry.name == bucket_name; });
172
- REQUIRE(known_buckets == 0);
173
- }
174
- }
175
-
176
- SECTION("flush")
177
- {
178
- SECTION("flush item")
77
+ SECTION("core API")
179
78
  {
180
- couchbase::core::document_id id{ bucket_name, "_default", "_default", test::utils::uniq_id("foo") };
181
-
79
+ couchbase::core::management::cluster::bucket_settings bucket_settings;
80
+ bucket_settings.name = bucket_name;
81
+ bucket_settings.ram_quota_mb = 100;
82
+ bucket_settings.num_replicas = 1;
83
+ bucket_settings.bucket_type = couchbase::core::management::cluster::bucket_type::couchbase;
84
+ bucket_settings.eviction_policy = couchbase::core::management::cluster::bucket_eviction_policy::value_only;
85
+ bucket_settings.flush_enabled = true;
86
+ if (integration.cluster_version().is_enterprise()) {
87
+ bucket_settings.max_expiry = 10;
88
+ bucket_settings.compression_mode = couchbase::core::management::cluster::bucket_compression::active;
89
+ }
90
+ bucket_settings.replica_indexes = true;
91
+ bucket_settings.conflict_resolution_type = couchbase::core::management::cluster::bucket_conflict_resolution::sequence_number;
182
92
  {
183
93
  couchbase::core::operations::management::bucket_create_request req;
184
- req.bucket.name = bucket_name;
185
- req.bucket.flush_enabled = true;
94
+ req.bucket = bucket_settings;
186
95
  auto resp = test::utils::execute(integration.cluster, req);
187
96
  REQUIRE_SUCCESS(resp.ctx.ec);
188
97
  }
189
98
 
190
- REQUIRE(test::utils::wait_until_bucket_healthy(integration.cluster, bucket_name));
191
-
192
- test::utils::open_bucket(integration.cluster, bucket_name);
193
-
194
- {
195
- const tao::json::value value = {
196
- { "a", 1.0 },
197
- };
198
- couchbase::core::operations::insert_request req{ id, couchbase::core::utils::json::generate_binary(value) };
199
- auto resp = test::utils::execute(integration.cluster, req);
200
- REQUIRE_SUCCESS(resp.ctx.ec());
201
- }
202
-
203
99
  {
204
- couchbase::core::operations::get_request req{ id };
100
+ auto resp = wait_for_bucket_created(integration, bucket_name);
101
+ REQUIRE_SUCCESS(resp.ctx.ec);
102
+ REQUIRE(bucket_settings.bucket_type == resp.bucket.bucket_type);
103
+ REQUIRE(bucket_settings.name == resp.bucket.name);
104
+ REQUIRE(Approx(bucket_settings.ram_quota_mb).margin(5) == resp.bucket.ram_quota_mb);
105
+ REQUIRE(bucket_settings.num_replicas == resp.bucket.num_replicas);
106
+ REQUIRE(bucket_settings.flush_enabled == resp.bucket.flush_enabled);
107
+ REQUIRE(bucket_settings.max_expiry == resp.bucket.max_expiry);
108
+ REQUIRE(bucket_settings.eviction_policy == resp.bucket.eviction_policy);
109
+ REQUIRE(bucket_settings.compression_mode == resp.bucket.compression_mode);
110
+ REQUIRE(bucket_settings.replica_indexes == resp.bucket.replica_indexes);
111
+ }
112
+ std::uint64_t old_quota_mb{ 0 };
113
+ {
114
+ couchbase::core::operations::management::bucket_get_all_request req{};
205
115
  auto resp = test::utils::execute(integration.cluster, req);
206
- REQUIRE_SUCCESS(resp.ctx.ec());
116
+ INFO(resp.ctx.http_body);
117
+ REQUIRE_SUCCESS(resp.ctx.ec);
118
+ bool found = false;
119
+ for (const auto& bucket : resp.buckets) {
120
+ if (bucket.name != bucket_name) {
121
+ continue;
122
+ }
123
+ found = true;
124
+ REQUIRE(bucket_settings.bucket_type == bucket.bucket_type);
125
+ REQUIRE(bucket_settings.name == bucket.name);
126
+ REQUIRE(bucket_settings.ram_quota_mb == bucket.ram_quota_mb);
127
+ old_quota_mb = bucket_settings.ram_quota_mb;
128
+ REQUIRE(bucket_settings.num_replicas == bucket.num_replicas);
129
+ REQUIRE(bucket_settings.flush_enabled == bucket.flush_enabled);
130
+ REQUIRE(bucket_settings.max_expiry == bucket.max_expiry);
131
+ REQUIRE(bucket_settings.eviction_policy == bucket.eviction_policy);
132
+ REQUIRE(bucket_settings.compression_mode == bucket.compression_mode);
133
+ REQUIRE(bucket_settings.replica_indexes == bucket.replica_indexes);
134
+ break;
135
+ }
136
+ REQUIRE(found);
207
137
  }
208
138
 
209
139
  {
210
- couchbase::core::operations::management::bucket_flush_request req{ bucket_name };
140
+ bucket_settings.ram_quota_mb = old_quota_mb + 20;
141
+ couchbase::core::operations::management::bucket_update_request req;
142
+ req.bucket = bucket_settings;
211
143
  auto resp = test::utils::execute(integration.cluster, req);
212
144
  REQUIRE_SUCCESS(resp.ctx.ec);
213
145
  }
214
146
 
215
- auto flushed = test::utils::wait_until([&integration, id]() {
216
- couchbase::core::operations::get_request req{ id };
147
+ auto ram_quota_updated = test::utils::wait_until([&integration, &bucket_name, old_quota_mb]() {
148
+ couchbase::core::operations::management::bucket_get_request req{ bucket_name };
217
149
  auto resp = test::utils::execute(integration.cluster, req);
218
- return resp.ctx.ec() == couchbase::errc::key_value::document_not_found;
150
+ return !resp.ctx.ec && resp.bucket.ram_quota_mb > old_quota_mb;
219
151
  });
220
- REQUIRE(flushed);
221
- }
222
-
223
- SECTION("no bucket")
224
- {
225
- couchbase::core::operations::management::bucket_flush_request req{ bucket_name };
226
- auto resp = test::utils::execute(integration.cluster, req);
227
- REQUIRE(resp.ctx.ec == couchbase::errc::common::bucket_not_found);
228
- }
152
+ REQUIRE(ram_quota_updated);
229
153
 
230
- SECTION("flush disabled")
231
- {
232
154
  {
233
- couchbase::core::operations::management::bucket_create_request req;
234
- req.bucket.name = bucket_name;
235
- req.bucket.flush_enabled = false;
155
+ couchbase::core::operations::management::bucket_drop_request req{ bucket_name };
236
156
  auto resp = test::utils::execute(integration.cluster, req);
237
157
  REQUIRE_SUCCESS(resp.ctx.ec);
238
158
  }
239
159
 
240
- REQUIRE(test::utils::wait_until_bucket_healthy(integration.cluster, bucket_name));
160
+ {
161
+ couchbase::core::operations::management::bucket_get_request req{ bucket_name };
162
+ auto resp = retry_on_error(integration, req, {});
163
+ REQUIRE(resp.ctx.ec == couchbase::errc::common::bucket_not_found);
164
+ }
241
165
 
242
166
  {
243
- couchbase::core::operations::management::bucket_flush_request req{ bucket_name };
167
+ couchbase::core::operations::management::bucket_get_all_request req;
244
168
  auto resp = test::utils::execute(integration.cluster, req);
245
- REQUIRE(resp.ctx.ec == couchbase::errc::management::bucket_not_flushable);
169
+ REQUIRE_SUCCESS(resp.ctx.ec);
170
+ REQUIRE(!resp.buckets.empty());
171
+ auto known_buckets = std::count_if(
172
+ resp.buckets.begin(), resp.buckets.end(), [&bucket_name](auto& entry) { return entry.name == bucket_name; });
173
+ REQUIRE(known_buckets == 0);
246
174
  }
247
175
  }
248
- }
249
-
250
- if (integration.cluster_version().supports_memcached_buckets()) {
251
- SECTION("memcached")
176
+ SECTION("public API")
252
177
  {
178
+ couchbase::cluster c(integration.cluster);
179
+ couchbase::management::cluster::bucket_settings bucket_settings;
180
+ bucket_settings.name = bucket_name;
181
+ bucket_settings.ram_quota_mb = 100;
182
+ bucket_settings.num_replicas = 1;
183
+ bucket_settings.bucket_type = couchbase::management::cluster::bucket_type::couchbase;
184
+ bucket_settings.eviction_policy = couchbase::management::cluster::bucket_eviction_policy::value_only;
185
+ bucket_settings.flush_enabled = true;
186
+ if (integration.cluster_version().is_enterprise()) {
187
+ bucket_settings.max_expiry = 10;
188
+ bucket_settings.compression_mode = couchbase::management::cluster::bucket_compression::active;
189
+ }
190
+ bucket_settings.replica_indexes = true;
191
+ bucket_settings.conflict_resolution_type = couchbase::management::cluster::bucket_conflict_resolution::sequence_number;
192
+ {
193
+ auto ctx = c.buckets().create_bucket(bucket_settings, {}).get();
194
+ REQUIRE_SUCCESS(ctx.ec());
195
+ }
253
196
  {
254
- couchbase::core::management::cluster::bucket_settings bucket_settings;
255
- bucket_settings.name = bucket_name;
256
- bucket_settings.bucket_type = couchbase::core::management::cluster::bucket_type::memcached;
257
- bucket_settings.num_replicas = 0;
258
- couchbase::core::operations::management::bucket_create_request req{ bucket_settings };
259
- auto resp = test::utils::execute(integration.cluster, req);
260
- REQUIRE_SUCCESS(resp.ctx.ec);
197
+ auto bucket_exists = test::utils::wait_until([&bucket_name, &c]() {
198
+ auto [ctx, bucket] = c.buckets().get_bucket(bucket_name, {}).get();
199
+ return ctx.ec() != couchbase::errc::common::bucket_not_found;
200
+ });
201
+ REQUIRE(bucket_exists);
202
+ auto [ctx, bucket] = c.buckets().get_bucket(bucket_name, {}).get();
203
+ REQUIRE_SUCCESS(ctx.ec());
204
+ REQUIRE(bucket_settings.bucket_type == bucket.bucket_type);
205
+ REQUIRE(bucket_settings.name == bucket.name);
206
+ REQUIRE(Approx(bucket_settings.ram_quota_mb).margin(5) == bucket.ram_quota_mb);
207
+ REQUIRE(bucket_settings.num_replicas == bucket.num_replicas);
208
+ REQUIRE(bucket_settings.flush_enabled == bucket.flush_enabled);
209
+ REQUIRE(bucket_settings.max_expiry == bucket.max_expiry);
210
+ REQUIRE(bucket_settings.eviction_policy == bucket.eviction_policy);
211
+ REQUIRE(bucket_settings.compression_mode == bucket.compression_mode);
212
+ REQUIRE(bucket_settings.replica_indexes == bucket.replica_indexes);
213
+ }
214
+ std::uint64_t old_quota_mb{ 0 };
215
+ {
216
+ auto [ctx, buckets] = c.buckets().get_all_buckets({}).get();
217
+ INFO(ctx.content());
218
+ REQUIRE_SUCCESS(ctx.ec());
219
+ bool found = false;
220
+ for (const auto& bucket : buckets) {
221
+ if (bucket.name != bucket_name) {
222
+ continue;
223
+ }
224
+ found = true;
225
+ REQUIRE(bucket_settings.bucket_type == bucket.bucket_type);
226
+ REQUIRE(bucket_settings.name == bucket.name);
227
+ REQUIRE(bucket_settings.ram_quota_mb == bucket.ram_quota_mb);
228
+ old_quota_mb = bucket_settings.ram_quota_mb;
229
+ REQUIRE(bucket_settings.num_replicas == bucket.num_replicas);
230
+ REQUIRE(bucket_settings.flush_enabled == bucket.flush_enabled);
231
+ REQUIRE(bucket_settings.max_expiry == bucket.max_expiry);
232
+ REQUIRE(bucket_settings.eviction_policy == bucket.eviction_policy);
233
+ REQUIRE(bucket_settings.compression_mode == bucket.compression_mode);
234
+ REQUIRE(bucket_settings.replica_indexes == bucket.replica_indexes);
235
+ break;
236
+ }
237
+ REQUIRE(found);
261
238
  }
262
239
 
263
240
  {
264
- auto resp = wait_for_bucket_created(integration, bucket_name);
265
- REQUIRE_SUCCESS(resp.ctx.ec);
266
- REQUIRE(resp.bucket.bucket_type == couchbase::core::management::cluster::bucket_type::memcached);
241
+ bucket_settings.ram_quota_mb = old_quota_mb + 20;
242
+ auto ctx = c.buckets().update_bucket(bucket_settings, {}).get();
243
+ REQUIRE_SUCCESS(ctx.ec());
244
+ }
245
+ auto ram_quota_updated = test::utils::wait_until([&bucket_name, c, old_quota_mb]() {
246
+ auto [ctx, bucket] = c.buckets().get_bucket(bucket_name, {}).get();
247
+ return !ctx.ec() && bucket.ram_quota_mb > old_quota_mb;
248
+ });
249
+ REQUIRE(ram_quota_updated);
250
+ {
251
+ auto ctx = c.buckets().drop_bucket(bucket_name, {}).get();
252
+ REQUIRE_SUCCESS(ctx.ec());
253
+ }
254
+ {
255
+ auto bucket_not_found = test::utils::wait_until([&bucket_name, c]() {
256
+ auto [ctx, bucket] = c.buckets().get_bucket(bucket_name, {}).get();
257
+ return ctx.ec() == couchbase::errc::common::bucket_not_found;
258
+ });
259
+ REQUIRE(bucket_not_found);
260
+ }
261
+ {
262
+ auto [ctx, buckets] = c.buckets().get_all_buckets({}).get();
263
+ REQUIRE_SUCCESS(ctx.ec());
264
+ REQUIRE(!buckets.empty());
265
+ auto known_buckets =
266
+ std::count_if(buckets.begin(), buckets.end(), [&bucket_name](auto& entry) { return entry.name == bucket_name; });
267
+ REQUIRE(known_buckets == 0);
267
268
  }
268
269
  }
269
270
  }
270
271
 
271
- SECTION("ephemeral")
272
+ SECTION("flush")
272
273
  {
273
- couchbase::core::management::cluster::bucket_settings bucket_settings;
274
- bucket_settings.name = bucket_name;
275
- bucket_settings.bucket_type = couchbase::core::management::cluster::bucket_type::ephemeral;
276
-
277
- SECTION("default eviction")
274
+ SECTION("core api")
278
275
  {
276
+ SECTION("flush item")
277
+ {
278
+ couchbase::core::document_id id{ bucket_name, "_default", "_default", test::utils::uniq_id("foo") };
279
+
280
+ {
281
+ couchbase::core::operations::management::bucket_create_request req;
282
+ req.bucket.name = bucket_name;
283
+ req.bucket.flush_enabled = true;
284
+ auto resp = test::utils::execute(integration.cluster, req);
285
+ REQUIRE_SUCCESS(resp.ctx.ec);
286
+ }
287
+
288
+ REQUIRE(test::utils::wait_until_bucket_healthy(integration.cluster, bucket_name));
289
+
290
+ test::utils::open_bucket(integration.cluster, bucket_name);
291
+
292
+ {
293
+ const tao::json::value value = {
294
+ { "a", 1.0 },
295
+ };
296
+ couchbase::core::operations::insert_request req{ id, couchbase::core::utils::json::generate_binary(value) };
297
+ auto resp = test::utils::execute(integration.cluster, req);
298
+ REQUIRE_SUCCESS(resp.ctx.ec());
299
+ }
300
+
301
+ {
302
+ couchbase::core::operations::get_request req{ id };
303
+ auto resp = test::utils::execute(integration.cluster, req);
304
+ REQUIRE_SUCCESS(resp.ctx.ec());
305
+ }
306
+
307
+ {
308
+ couchbase::core::operations::management::bucket_flush_request req{ bucket_name };
309
+ auto resp = test::utils::execute(integration.cluster, req);
310
+ REQUIRE_SUCCESS(resp.ctx.ec);
311
+ }
312
+
313
+ auto flushed = test::utils::wait_until([&integration, id]() {
314
+ couchbase::core::operations::get_request req{ id };
315
+ auto resp = test::utils::execute(integration.cluster, req);
316
+ return resp.ctx.ec() == couchbase::errc::key_value::document_not_found;
317
+ });
318
+ REQUIRE(flushed);
319
+ }
320
+ SECTION("no bucket")
279
321
  {
280
- couchbase::core::operations::management::bucket_create_request req{ bucket_settings };
322
+ couchbase::core::operations::management::bucket_flush_request req{ bucket_name };
281
323
  auto resp = test::utils::execute(integration.cluster, req);
282
- REQUIRE_SUCCESS(resp.ctx.ec);
324
+ REQUIRE(resp.ctx.ec == couchbase::errc::common::bucket_not_found);
283
325
  }
284
326
 
327
+ SECTION("flush disabled")
285
328
  {
286
- auto resp = wait_for_bucket_created(integration, bucket_name);
287
- REQUIRE_SUCCESS(resp.ctx.ec);
288
- REQUIRE(resp.bucket.bucket_type == couchbase::core::management::cluster::bucket_type::ephemeral);
289
- REQUIRE(resp.bucket.eviction_policy == couchbase::core::management::cluster::bucket_eviction_policy::no_eviction);
329
+ {
330
+ couchbase::core::operations::management::bucket_create_request req;
331
+ req.bucket.name = bucket_name;
332
+ req.bucket.flush_enabled = false;
333
+ auto resp = test::utils::execute(integration.cluster, req);
334
+ REQUIRE_SUCCESS(resp.ctx.ec);
335
+ }
336
+
337
+ REQUIRE(test::utils::wait_until_bucket_healthy(integration.cluster, bucket_name));
338
+
339
+ {
340
+ couchbase::core::operations::management::bucket_flush_request req{ bucket_name };
341
+ auto resp = test::utils::execute(integration.cluster, req);
342
+ REQUIRE(resp.ctx.ec == couchbase::errc::management::bucket_not_flushable);
343
+ }
290
344
  }
291
345
  }
292
-
293
- SECTION("nru eviction")
346
+ SECTION("public API")
294
347
  {
348
+ couchbase::cluster c(integration.cluster);
349
+ SECTION("flush item")
295
350
  {
296
- bucket_settings.eviction_policy = couchbase::core::management::cluster::bucket_eviction_policy::not_recently_used;
297
- couchbase::core::operations::management::bucket_create_request req{ bucket_settings };
298
- auto resp = test::utils::execute(integration.cluster, req);
299
- REQUIRE_SUCCESS(resp.ctx.ec);
351
+ auto id = test::utils::uniq_id("foo");
352
+
353
+ {
354
+ couchbase::management::cluster::bucket_settings bucket_settings;
355
+ bucket_settings.name = bucket_name;
356
+ bucket_settings.flush_enabled = true;
357
+ auto ctx = c.buckets().create_bucket(bucket_settings, {}).get();
358
+ REQUIRE_SUCCESS(ctx.ec());
359
+ }
360
+
361
+ REQUIRE(test::utils::wait_until_bucket_healthy(integration.cluster, bucket_name));
362
+
363
+ test::utils::open_bucket(integration.cluster, bucket_name);
364
+
365
+ auto default_coll = c.bucket(bucket_name).default_collection();
366
+ {
367
+ const tao::json::value value = {
368
+ { "a", 1.0 },
369
+ };
370
+
371
+ auto [ctx, resp] = default_coll.insert(id, value, {}).get();
372
+ REQUIRE_SUCCESS(ctx.ec());
373
+ }
374
+ {
375
+ auto [ctx, resp] = default_coll.get(id, {}).get();
376
+ REQUIRE_SUCCESS(ctx.ec());
377
+ }
378
+ {
379
+ auto ctx = c.buckets().flush_bucket(bucket_name, {}).get();
380
+ REQUIRE_SUCCESS(ctx.ec());
381
+ }
382
+ auto flushed = test::utils::wait_until([id, default_coll]() {
383
+ auto [ctx, resp] = default_coll.get(id, {}).get();
384
+ return ctx.ec() == couchbase::errc::key_value::document_not_found;
385
+ });
386
+ REQUIRE(flushed);
300
387
  }
301
388
 
389
+ SECTION("no bucket")
302
390
  {
303
- auto resp = wait_for_bucket_created(integration, bucket_name);
304
- REQUIRE_SUCCESS(resp.ctx.ec);
305
- REQUIRE(resp.bucket.bucket_type == couchbase::core::management::cluster::bucket_type::ephemeral);
306
- REQUIRE(resp.bucket.eviction_policy == couchbase::core::management::cluster::bucket_eviction_policy::not_recently_used);
391
+ auto ctx = c.buckets().flush_bucket(bucket_name, {}).get();
392
+ REQUIRE(ctx.ec() == couchbase::errc::common::bucket_not_found);
393
+ }
394
+
395
+ SECTION("flush disabled")
396
+ {
397
+ {
398
+ couchbase::management::cluster::bucket_settings bucket_settings;
399
+ bucket_settings.name = bucket_name;
400
+ bucket_settings.flush_enabled = false;
401
+ auto ctx = c.buckets().create_bucket(bucket_settings, {}).get();
402
+ REQUIRE_SUCCESS(ctx.ec());
403
+ }
404
+
405
+ auto bucket_exists = test::utils::wait_until([&bucket_name, c]() {
406
+ auto [ctx, bucket] = c.buckets().get_bucket(bucket_name, {}).get();
407
+ return ctx.ec() != couchbase::errc::common::bucket_not_found;
408
+ });
409
+ REQUIRE(bucket_exists);
410
+
411
+ {
412
+ auto ctx = c.buckets().flush_bucket(bucket_name, {}).get();
413
+ REQUIRE(ctx.ec() == couchbase::errc::management::bucket_not_flushable);
414
+ }
307
415
  }
308
416
  }
417
+ }
309
418
 
310
- if (integration.cluster_version().supports_storage_backend()) {
311
- SECTION("storage backend")
419
+ if (integration.cluster_version().supports_memcached_buckets()) {
420
+ SECTION("memcached")
421
+ {
422
+ SECTION("core api")
312
423
  {
313
424
  {
314
- bucket_settings.storage_backend = couchbase::core::management::cluster::bucket_storage_backend::couchstore;
425
+ couchbase::core::management::cluster::bucket_settings bucket_settings;
426
+ bucket_settings.name = bucket_name;
427
+ bucket_settings.bucket_type = couchbase::core::management::cluster::bucket_type::memcached;
428
+ bucket_settings.num_replicas = 0;
315
429
  couchbase::core::operations::management::bucket_create_request req{ bucket_settings };
316
430
  auto resp = test::utils::execute(integration.cluster, req);
317
431
  REQUIRE_SUCCESS(resp.ctx.ec);
@@ -320,57 +434,78 @@ TEST_CASE("integration: bucket management", "[integration]")
320
434
  {
321
435
  auto resp = wait_for_bucket_created(integration, bucket_name);
322
436
  REQUIRE_SUCCESS(resp.ctx.ec);
323
- REQUIRE(resp.bucket.bucket_type == couchbase::core::management::cluster::bucket_type::ephemeral);
324
- REQUIRE(resp.bucket.storage_backend == couchbase::core::management::cluster::bucket_storage_backend::unknown);
437
+ REQUIRE(resp.bucket.bucket_type == couchbase::core::management::cluster::bucket_type::memcached);
438
+ }
439
+ }
440
+ SECTION("public api")
441
+ {
442
+ couchbase::cluster c(integration.cluster);
443
+ {
444
+ couchbase::management::cluster::bucket_settings bucket_settings;
445
+ bucket_settings.name = bucket_name;
446
+ bucket_settings.bucket_type = couchbase::management::cluster::bucket_type::memcached;
447
+ bucket_settings.num_replicas = 0;
448
+ auto ctx = c.buckets().create_bucket(bucket_settings, {}).get();
449
+ REQUIRE_SUCCESS(ctx.ec());
450
+ }
451
+
452
+ {
453
+ auto bucket_exists = test::utils::wait_until([&bucket_name, &c]() {
454
+ auto [ctx, bucket] = c.buckets().get_bucket(bucket_name, {}).get();
455
+ return ctx.ec() != couchbase::errc::common::bucket_not_found;
456
+ });
457
+ REQUIRE(bucket_exists);
458
+ auto [ctx, bucket] = c.buckets().get_bucket(bucket_name, {}).get();
459
+ REQUIRE_SUCCESS(ctx.ec());
460
+ REQUIRE(bucket.bucket_type == couchbase::management::cluster::bucket_type::memcached);
325
461
  }
326
462
  }
327
463
  }
328
464
  }
329
465
 
330
- SECTION("couchbase")
466
+ SECTION("ephemeral")
331
467
  {
332
- couchbase::core::management::cluster::bucket_settings bucket_settings;
333
- bucket_settings.name = bucket_name;
334
- bucket_settings.bucket_type = couchbase::core::management::cluster::bucket_type::couchbase;
335
-
336
- SECTION("default eviction")
468
+ SECTION("core api")
337
469
  {
338
- {
339
-
340
- couchbase::core::operations::management::bucket_create_request req{ bucket_settings };
341
- auto resp = test::utils::execute(integration.cluster, req);
342
- REQUIRE_SUCCESS(resp.ctx.ec);
343
- }
470
+ couchbase::core::management::cluster::bucket_settings bucket_settings;
471
+ bucket_settings.name = bucket_name;
472
+ bucket_settings.bucket_type = couchbase::core::management::cluster::bucket_type::ephemeral;
344
473
 
474
+ SECTION("default eviction")
345
475
  {
346
- auto resp = wait_for_bucket_created(integration, bucket_name);
347
- REQUIRE_SUCCESS(resp.ctx.ec);
348
- REQUIRE(resp.bucket.bucket_type == couchbase::core::management::cluster::bucket_type::couchbase);
349
- REQUIRE(resp.bucket.eviction_policy == couchbase::core::management::cluster::bucket_eviction_policy::value_only);
350
- }
351
- }
476
+ {
477
+ couchbase::core::operations::management::bucket_create_request req{ bucket_settings };
478
+ auto resp = test::utils::execute(integration.cluster, req);
479
+ REQUIRE_SUCCESS(resp.ctx.ec);
480
+ }
352
481
 
353
- SECTION("full eviction")
354
- {
355
- {
356
- bucket_settings.eviction_policy = couchbase::core::management::cluster::bucket_eviction_policy::full;
357
- couchbase::core::operations::management::bucket_create_request req{ bucket_settings };
358
- auto resp = test::utils::execute(integration.cluster, req);
359
- REQUIRE_SUCCESS(resp.ctx.ec);
482
+ {
483
+ auto resp = wait_for_bucket_created(integration, bucket_name);
484
+ REQUIRE_SUCCESS(resp.ctx.ec);
485
+ REQUIRE(resp.bucket.bucket_type == couchbase::core::management::cluster::bucket_type::ephemeral);
486
+ REQUIRE(resp.bucket.eviction_policy == couchbase::core::management::cluster::bucket_eviction_policy::no_eviction);
487
+ }
360
488
  }
361
489
 
490
+ SECTION("nru eviction")
362
491
  {
363
- auto resp = wait_for_bucket_created(integration, bucket_name);
364
- REQUIRE_SUCCESS(resp.ctx.ec);
365
- REQUIRE(resp.bucket.bucket_type == couchbase::core::management::cluster::bucket_type::couchbase);
366
- REQUIRE(resp.bucket.eviction_policy == couchbase::core::management::cluster::bucket_eviction_policy::full);
492
+ {
493
+ bucket_settings.eviction_policy = couchbase::core::management::cluster::bucket_eviction_policy::not_recently_used;
494
+ couchbase::core::operations::management::bucket_create_request req{ bucket_settings };
495
+ auto resp = test::utils::execute(integration.cluster, req);
496
+ REQUIRE_SUCCESS(resp.ctx.ec);
497
+ }
498
+
499
+ {
500
+ auto resp = wait_for_bucket_created(integration, bucket_name);
501
+ REQUIRE_SUCCESS(resp.ctx.ec);
502
+ REQUIRE(resp.bucket.bucket_type == couchbase::core::management::cluster::bucket_type::ephemeral);
503
+ REQUIRE(resp.bucket.eviction_policy == couchbase::core::management::cluster::bucket_eviction_policy::not_recently_used);
504
+ }
367
505
  }
368
- }
369
506
 
370
- if (integration.cluster_version().supports_storage_backend()) {
371
- SECTION("storage backend")
372
- {
373
- SECTION("couchstore")
507
+ if (integration.cluster_version().supports_storage_backend()) {
508
+ SECTION("storage backend")
374
509
  {
375
510
  {
376
511
  bucket_settings.storage_backend = couchbase::core::management::cluster::bucket_storage_backend::couchstore;
@@ -382,52 +517,112 @@ TEST_CASE("integration: bucket management", "[integration]")
382
517
  {
383
518
  auto resp = wait_for_bucket_created(integration, bucket_name);
384
519
  REQUIRE_SUCCESS(resp.ctx.ec);
385
- REQUIRE(resp.bucket.bucket_type == couchbase::core::management::cluster::bucket_type::couchbase);
386
- REQUIRE(resp.bucket.storage_backend == couchbase::core::management::cluster::bucket_storage_backend::couchstore);
520
+ REQUIRE(resp.bucket.bucket_type == couchbase::core::management::cluster::bucket_type::ephemeral);
521
+ REQUIRE(resp.bucket.storage_backend == couchbase::core::management::cluster::bucket_storage_backend::unknown);
387
522
  }
388
523
  }
524
+ }
525
+ }
526
+ SECTION("public api")
527
+ {
528
+ couchbase::cluster c(integration.cluster);
529
+ couchbase::management::cluster::bucket_settings bucket_settings;
530
+ bucket_settings.name = bucket_name;
531
+ bucket_settings.bucket_type = couchbase::management::cluster::bucket_type::ephemeral;
532
+
533
+ SECTION("default eviction")
534
+ {
535
+ {
536
+ auto ctx = c.buckets().create_bucket(bucket_settings, {}).get();
537
+ REQUIRE_SUCCESS(ctx.ec());
538
+ }
389
539
 
390
- SECTION("magma")
540
+ {
541
+ auto bucket_exists = test::utils::wait_until([&bucket_name, c]() {
542
+ auto [ctx, bucket] = c.buckets().get_bucket(bucket_name, {}).get();
543
+ return ctx.ec() != couchbase::errc::common::bucket_not_found;
544
+ });
545
+ REQUIRE(bucket_exists);
546
+ auto [ctx, bucket] = c.buckets().get_bucket(bucket_name, {}).get();
547
+ REQUIRE_SUCCESS(ctx.ec());
548
+ REQUIRE(bucket.bucket_type == couchbase::management::cluster::bucket_type::ephemeral);
549
+ REQUIRE(bucket.eviction_policy == couchbase::management::cluster::bucket_eviction_policy::no_eviction);
550
+ }
551
+ }
552
+
553
+ SECTION("nru eviction")
554
+ {
555
+ {
556
+ bucket_settings.eviction_policy = couchbase::management::cluster::bucket_eviction_policy::not_recently_used;
557
+ auto ctx = c.buckets().create_bucket(bucket_settings, {}).get();
558
+ REQUIRE_SUCCESS(ctx.ec());
559
+ }
560
+
561
+ {
562
+ auto bucket_exists = test::utils::wait_until([&bucket_name, c]() {
563
+ auto [ctx, bucket] = c.buckets().get_bucket(bucket_name, {}).get();
564
+ return ctx.ec() != couchbase::errc::common::bucket_not_found;
565
+ });
566
+ REQUIRE(bucket_exists);
567
+ auto [ctx, bucket] = c.buckets().get_bucket(bucket_name, {}).get();
568
+ REQUIRE_SUCCESS(ctx.ec());
569
+ REQUIRE(bucket.bucket_type == couchbase::management::cluster::bucket_type::ephemeral);
570
+ REQUIRE(bucket.eviction_policy == couchbase::management::cluster::bucket_eviction_policy::not_recently_used);
571
+ }
572
+ }
573
+ if (integration.cluster_version().supports_storage_backend()) {
574
+ SECTION("storage backend")
391
575
  {
392
576
  {
393
- bucket_settings.ram_quota_mb = integration.cluster_version().is_neo() ? 1'024 : 256;
394
- bucket_settings.storage_backend = couchbase::core::management::cluster::bucket_storage_backend::magma;
395
- couchbase::core::operations::management::bucket_create_request req{ bucket_settings };
396
- auto resp = test::utils::execute(integration.cluster, req);
397
- REQUIRE_SUCCESS(resp.ctx.ec);
577
+ bucket_settings.storage_backend = couchbase::management::cluster::bucket_storage_backend::couchstore;
578
+ auto ctx = c.buckets().create_bucket(bucket_settings, {}).get();
579
+ REQUIRE_SUCCESS(ctx.ec());
398
580
  }
399
581
 
400
582
  {
401
- auto resp = wait_for_bucket_created(integration, bucket_name);
402
- REQUIRE_SUCCESS(resp.ctx.ec);
403
- REQUIRE(resp.bucket.bucket_type == couchbase::core::management::cluster::bucket_type::couchbase);
404
- REQUIRE(resp.bucket.storage_backend == couchbase::core::management::cluster::bucket_storage_backend::magma);
583
+ auto bucket_exists = test::utils::wait_until([&bucket_name, c]() {
584
+ auto [ctx, bucket] = c.buckets().get_bucket(bucket_name, {}).get();
585
+ return ctx.ec() != couchbase::errc::common::bucket_not_found;
586
+ });
587
+ REQUIRE(bucket_exists);
588
+ auto [ctx, bucket] = c.buckets().get_bucket(bucket_name, {}).get();
589
+ REQUIRE_SUCCESS(ctx.ec());
590
+ REQUIRE(bucket.bucket_type == couchbase::management::cluster::bucket_type::ephemeral);
591
+ REQUIRE(bucket.storage_backend == couchbase::management::cluster::bucket_storage_backend::unknown);
405
592
  }
406
593
  }
407
594
  }
408
595
  }
409
596
  }
410
-
411
- SECTION("update no bucket")
597
+ SECTION("couchbase")
412
598
  {
413
-
414
- couchbase::core::management::cluster::bucket_settings bucket_settings;
415
- bucket_settings.name = bucket_name;
416
- couchbase::core::operations::management::bucket_update_request req;
417
- req.bucket = bucket_settings;
418
- auto resp = test::utils::execute(integration.cluster, req);
419
- REQUIRE(resp.ctx.ec == couchbase::errc::common::bucket_not_found);
420
- }
421
-
422
- if (integration.cluster_version().supports_minimum_durability_level()) {
423
- SECTION("minimum durability level")
599
+ SECTION("core api")
424
600
  {
425
601
  couchbase::core::management::cluster::bucket_settings bucket_settings;
426
602
  bucket_settings.name = bucket_name;
603
+ bucket_settings.bucket_type = couchbase::core::management::cluster::bucket_type::couchbase;
427
604
 
428
- SECTION("default")
605
+ SECTION("default eviction")
429
606
  {
430
607
  {
608
+
609
+ couchbase::core::operations::management::bucket_create_request req{ bucket_settings };
610
+ auto resp = test::utils::execute(integration.cluster, req);
611
+ REQUIRE_SUCCESS(resp.ctx.ec);
612
+ }
613
+
614
+ {
615
+ auto resp = wait_for_bucket_created(integration, bucket_name);
616
+ REQUIRE_SUCCESS(resp.ctx.ec);
617
+ REQUIRE(resp.bucket.bucket_type == couchbase::core::management::cluster::bucket_type::couchbase);
618
+ REQUIRE(resp.bucket.eviction_policy == couchbase::core::management::cluster::bucket_eviction_policy::value_only);
619
+ }
620
+ }
621
+
622
+ SECTION("full eviction")
623
+ {
624
+ {
625
+ bucket_settings.eviction_policy = couchbase::core::management::cluster::bucket_eviction_policy::full;
431
626
  couchbase::core::operations::management::bucket_create_request req{ bucket_settings };
432
627
  auto resp = test::utils::execute(integration.cluster, req);
433
628
  REQUIRE_SUCCESS(resp.ctx.ec);
@@ -436,15 +631,182 @@ TEST_CASE("integration: bucket management", "[integration]")
436
631
  {
437
632
  auto resp = wait_for_bucket_created(integration, bucket_name);
438
633
  REQUIRE_SUCCESS(resp.ctx.ec);
439
- REQUIRE(resp.bucket.minimum_durability_level == couchbase::durability_level::none);
634
+ REQUIRE(resp.bucket.bucket_type == couchbase::core::management::cluster::bucket_type::couchbase);
635
+ REQUIRE(resp.bucket.eviction_policy == couchbase::core::management::cluster::bucket_eviction_policy::full);
440
636
  }
441
637
  }
442
638
 
443
- if (integration.number_of_nodes() >= 2) {
444
- SECTION("majority")
639
+ if (integration.cluster_version().supports_storage_backend()) {
640
+ SECTION("storage backend")
641
+ {
642
+ SECTION("couchstore")
643
+ {
644
+ {
645
+ bucket_settings.storage_backend = couchbase::core::management::cluster::bucket_storage_backend::couchstore;
646
+ couchbase::core::operations::management::bucket_create_request req{ bucket_settings };
647
+ auto resp = test::utils::execute(integration.cluster, req);
648
+ REQUIRE_SUCCESS(resp.ctx.ec);
649
+ }
650
+
651
+ {
652
+ auto resp = wait_for_bucket_created(integration, bucket_name);
653
+ REQUIRE_SUCCESS(resp.ctx.ec);
654
+ REQUIRE(resp.bucket.bucket_type == couchbase::core::management::cluster::bucket_type::couchbase);
655
+ REQUIRE(resp.bucket.storage_backend ==
656
+ couchbase::core::management::cluster::bucket_storage_backend::couchstore);
657
+ }
658
+ }
659
+
660
+ SECTION("magma")
661
+ {
662
+ {
663
+ bucket_settings.ram_quota_mb = integration.cluster_version().is_neo() ? 1'024 : 256;
664
+ bucket_settings.storage_backend = couchbase::core::management::cluster::bucket_storage_backend::magma;
665
+ couchbase::core::operations::management::bucket_create_request req{ bucket_settings };
666
+ auto resp = test::utils::execute(integration.cluster, req);
667
+ REQUIRE_SUCCESS(resp.ctx.ec);
668
+ }
669
+
670
+ {
671
+ auto resp = wait_for_bucket_created(integration, bucket_name);
672
+ REQUIRE_SUCCESS(resp.ctx.ec);
673
+ REQUIRE(resp.bucket.bucket_type == couchbase::core::management::cluster::bucket_type::couchbase);
674
+ REQUIRE(resp.bucket.storage_backend == couchbase::core::management::cluster::bucket_storage_backend::magma);
675
+ }
676
+ }
677
+ }
678
+ }
679
+ }
680
+ SECTION("public api")
681
+ {
682
+ couchbase::cluster c(integration.cluster);
683
+ couchbase::management::cluster::bucket_settings bucket_settings;
684
+ bucket_settings.name = bucket_name;
685
+ bucket_settings.bucket_type = couchbase::management::cluster::bucket_type::couchbase;
686
+
687
+ SECTION("default eviction")
688
+ {
689
+ {
690
+ auto ctx = c.buckets().create_bucket(bucket_settings, {}).get();
691
+ REQUIRE_SUCCESS(ctx.ec());
692
+ }
693
+
694
+ {
695
+ auto bucket_exists = test::utils::wait_until([&bucket_name, c]() {
696
+ auto [ctx, bucket] = c.buckets().get_bucket(bucket_name, {}).get();
697
+ return ctx.ec() != couchbase::errc::common::bucket_not_found;
698
+ });
699
+ REQUIRE(bucket_exists);
700
+ auto [ctx, bucket] = c.buckets().get_bucket(bucket_name, {}).get();
701
+ REQUIRE_SUCCESS(ctx.ec());
702
+ REQUIRE(bucket.bucket_type == couchbase::management::cluster::bucket_type::couchbase);
703
+ REQUIRE(bucket.eviction_policy == couchbase::management::cluster::bucket_eviction_policy::value_only);
704
+ }
705
+ }
706
+
707
+ SECTION("full eviction")
708
+ {
709
+ {
710
+ bucket_settings.eviction_policy = couchbase::management::cluster::bucket_eviction_policy::full;
711
+ auto ctx = c.buckets().create_bucket(bucket_settings, {}).get();
712
+ REQUIRE_SUCCESS(ctx.ec());
713
+ }
714
+
715
+ {
716
+ auto bucket_exists = test::utils::wait_until([&bucket_name, c]() {
717
+ auto [ctx, bucket] = c.buckets().get_bucket(bucket_name, {}).get();
718
+ return ctx.ec() != couchbase::errc::common::bucket_not_found;
719
+ });
720
+ REQUIRE(bucket_exists);
721
+ auto [ctx, bucket] = c.buckets().get_bucket(bucket_name, {}).get();
722
+ REQUIRE_SUCCESS(ctx.ec());
723
+ REQUIRE(bucket.bucket_type == couchbase::management::cluster::bucket_type::couchbase);
724
+ REQUIRE(bucket.eviction_policy == couchbase::management::cluster::bucket_eviction_policy::full);
725
+ }
726
+ }
727
+
728
+ if (integration.cluster_version().supports_storage_backend()) {
729
+ SECTION("storage backend")
730
+ {
731
+ SECTION("couchstore")
732
+ {
733
+ {
734
+ bucket_settings.storage_backend = couchbase::management::cluster::bucket_storage_backend::couchstore;
735
+ auto ctx = c.buckets().create_bucket(bucket_settings, {}).get();
736
+ REQUIRE_SUCCESS(ctx.ec());
737
+ }
738
+
739
+ {
740
+ auto bucket_exists = test::utils::wait_until([&bucket_name, c]() {
741
+ auto [ctx, bucket] = c.buckets().get_bucket(bucket_name, {}).get();
742
+ return ctx.ec() != couchbase::errc::common::bucket_not_found;
743
+ });
744
+ REQUIRE(bucket_exists);
745
+ auto [ctx, bucket] = c.buckets().get_bucket(bucket_name, {}).get();
746
+ REQUIRE_SUCCESS(ctx.ec());
747
+ REQUIRE(bucket.bucket_type == couchbase::management::cluster::bucket_type::couchbase);
748
+ REQUIRE(bucket.storage_backend == couchbase::management::cluster::bucket_storage_backend::couchstore);
749
+ }
750
+ }
751
+
752
+ SECTION("magma")
753
+ {
754
+ {
755
+ bucket_settings.ram_quota_mb = integration.cluster_version().is_neo() ? 1'024 : 256;
756
+ bucket_settings.storage_backend = couchbase::management::cluster::bucket_storage_backend::magma;
757
+ auto ctx = c.buckets().create_bucket(bucket_settings, {}).get();
758
+ REQUIRE_SUCCESS(ctx.ec());
759
+ }
760
+
761
+ {
762
+ auto bucket_exists = test::utils::wait_until([&bucket_name, c]() {
763
+ auto [ctx, bucket] = c.buckets().get_bucket(bucket_name, {}).get();
764
+ return ctx.ec() != couchbase::errc::common::bucket_not_found;
765
+ });
766
+ REQUIRE(bucket_exists);
767
+ auto [ctx, bucket] = c.buckets().get_bucket(bucket_name, {}).get();
768
+ REQUIRE_SUCCESS(ctx.ec());
769
+ REQUIRE(bucket.bucket_type == couchbase::management::cluster::bucket_type::couchbase);
770
+ REQUIRE(bucket.storage_backend == couchbase::management::cluster::bucket_storage_backend::magma);
771
+ }
772
+ }
773
+ }
774
+ }
775
+ }
776
+ }
777
+
778
+ SECTION("update no bucket")
779
+ {
780
+ SECTION("core api")
781
+ {
782
+ couchbase::core::management::cluster::bucket_settings bucket_settings;
783
+ bucket_settings.name = bucket_name;
784
+ couchbase::core::operations::management::bucket_update_request req;
785
+ req.bucket = bucket_settings;
786
+ auto resp = test::utils::execute(integration.cluster, req);
787
+ REQUIRE(resp.ctx.ec == couchbase::errc::common::bucket_not_found);
788
+ }
789
+ SECTION("public api")
790
+ {
791
+ couchbase::cluster c(integration.cluster);
792
+ couchbase::management::cluster::bucket_settings bucket_settings;
793
+ bucket_settings.name = bucket_name;
794
+ auto ctx = c.buckets().update_bucket(bucket_settings, {}).get();
795
+ REQUIRE(ctx.ec() == couchbase::errc::common::bucket_not_found);
796
+ }
797
+ }
798
+
799
+ if (integration.cluster_version().supports_minimum_durability_level()) {
800
+ SECTION("minimum durability level")
801
+ {
802
+ SECTION("core api")
803
+ {
804
+ couchbase::core::management::cluster::bucket_settings bucket_settings;
805
+ bucket_settings.name = bucket_name;
806
+
807
+ SECTION("default")
445
808
  {
446
809
  {
447
- bucket_settings.minimum_durability_level = couchbase::durability_level::majority;
448
810
  couchbase::core::operations::management::bucket_create_request req{ bucket_settings };
449
811
  auto resp = test::utils::execute(integration.cluster, req);
450
812
  REQUIRE_SUCCESS(resp.ctx.ec);
@@ -453,7 +815,70 @@ TEST_CASE("integration: bucket management", "[integration]")
453
815
  {
454
816
  auto resp = wait_for_bucket_created(integration, bucket_name);
455
817
  REQUIRE_SUCCESS(resp.ctx.ec);
456
- REQUIRE(resp.bucket.minimum_durability_level == couchbase::durability_level::majority);
818
+ REQUIRE(resp.bucket.minimum_durability_level == couchbase::durability_level::none);
819
+ }
820
+ }
821
+
822
+ if (integration.number_of_nodes() >= 2) {
823
+ SECTION("majority")
824
+ {
825
+ {
826
+ bucket_settings.minimum_durability_level = couchbase::durability_level::majority;
827
+ couchbase::core::operations::management::bucket_create_request req{ bucket_settings };
828
+ auto resp = test::utils::execute(integration.cluster, req);
829
+ REQUIRE_SUCCESS(resp.ctx.ec);
830
+ }
831
+
832
+ {
833
+ auto resp = wait_for_bucket_created(integration, bucket_name);
834
+ REQUIRE_SUCCESS(resp.ctx.ec);
835
+ REQUIRE(resp.bucket.minimum_durability_level == couchbase::durability_level::majority);
836
+ }
837
+ }
838
+ }
839
+ }
840
+ SECTION("public api")
841
+ {
842
+ couchbase::cluster c(integration.cluster);
843
+ couchbase::management::cluster::bucket_settings bucket_settings;
844
+ bucket_settings.name = bucket_name;
845
+
846
+ SECTION("default")
847
+ {
848
+ {
849
+ auto ctx = c.buckets().create_bucket(bucket_settings, {}).get();
850
+ REQUIRE_SUCCESS(ctx.ec());
851
+ }
852
+ {
853
+ auto bucket_exists = test::utils::wait_until([&bucket_name, c]() {
854
+ auto [ctx, bucket] = c.buckets().get_bucket(bucket_name, {}).get();
855
+ return ctx.ec() != couchbase::errc::common::bucket_not_found;
856
+ });
857
+ REQUIRE(bucket_exists);
858
+ auto [ctx, bucket] = c.buckets().get_bucket(bucket_name, {}).get();
859
+ REQUIRE_SUCCESS(ctx.ec());
860
+ REQUIRE(bucket.minimum_durability_level == couchbase::durability_level::none);
861
+ }
862
+ }
863
+ if (integration.number_of_nodes() >= 2) {
864
+ SECTION("majority")
865
+ {
866
+ {
867
+ bucket_settings.minimum_durability_level = couchbase::durability_level::majority;
868
+ auto ctx = c.buckets().create_bucket(bucket_settings, {}).get();
869
+ REQUIRE_SUCCESS(ctx.ec());
870
+ }
871
+
872
+ {
873
+ auto bucket_exists = test::utils::wait_until([&bucket_name, c]() {
874
+ auto [ctx, bucket] = c.buckets().get_bucket(bucket_name, {}).get();
875
+ return ctx.ec() != couchbase::errc::common::bucket_not_found;
876
+ });
877
+ REQUIRE(bucket_exists);
878
+ auto [ctx, bucket] = c.buckets().get_bucket(bucket_name, {}).get();
879
+ REQUIRE_SUCCESS(ctx.ec());
880
+ REQUIRE(bucket.minimum_durability_level == couchbase::durability_level::majority);
881
+ }
457
882
  }
458
883
  }
459
884
  }
@@ -1036,6 +1461,12 @@ TEST_CASE("integration: user management collections roles", "[integration]")
1036
1461
  REQUIRE(resp.user.roles[0].scope == scope_name);
1037
1462
  REQUIRE(resp.user.roles[0].collection == collection_name);
1038
1463
  }
1464
+
1465
+ {
1466
+ couchbase::core::operations::management::scope_drop_request req{ integration.ctx.bucket, scope_name };
1467
+ auto resp = test::utils::execute(integration.cluster, req);
1468
+ REQUIRE_SUCCESS(resp.ctx.ec);
1469
+ }
1039
1470
  }
1040
1471
 
1041
1472
  TEST_CASE("integration: query index management", "[integration]")
@@ -1499,7 +1930,8 @@ TEST_CASE("integration: collections query index management", "[integration]")
1499
1930
  req.collection_name = collection_name;
1500
1931
  req.is_primary = true;
1501
1932
  resp = test::utils::execute(integration.cluster, req);
1502
- return resp.ctx.ec != couchbase::errc::common::bucket_not_found;
1933
+ return resp.ctx.ec != couchbase::errc::common::bucket_not_found &&
1934
+ resp.ctx.ec != couchbase::errc::common::scope_not_found;
1503
1935
  });
1504
1936
  REQUIRE(operation_completed);
1505
1937
  REQUIRE_SUCCESS(resp.ctx.ec);
@@ -1524,7 +1956,7 @@ TEST_CASE("integration: collections query index management", "[integration]")
1524
1956
  bool operation_completed = test::utils::wait_until([&manager, &ec]() {
1525
1957
  auto ctx = manager.create_primary_index({}).get();
1526
1958
  ec = ctx.ec();
1527
- return ctx.ec() != couchbase::errc::common::bucket_not_found;
1959
+ return ec != couchbase::errc::common::bucket_not_found && ec != couchbase::errc::common::scope_not_found;
1528
1960
  });
1529
1961
 
1530
1962
  REQUIRE(operation_completed);
@@ -1554,7 +1986,8 @@ TEST_CASE("integration: collections query index management", "[integration]")
1554
1986
  req.index_name = index_name;
1555
1987
  req.is_primary = true;
1556
1988
  resp = test::utils::execute(integration.cluster, req);
1557
- return resp.ctx.ec != couchbase::errc::common::bucket_not_found;
1989
+ return resp.ctx.ec != couchbase::errc::common::bucket_not_found &&
1990
+ resp.ctx.ec != couchbase::errc::common::scope_not_found;
1558
1991
  });
1559
1992
  REQUIRE(operation_completed);
1560
1993
  REQUIRE_SUCCESS(resp.ctx.ec);
@@ -1628,7 +2061,8 @@ TEST_CASE("integration: collections query index management", "[integration]")
1628
2061
  req.collection_name = collection_name;
1629
2062
  req.fields = { "field" };
1630
2063
  resp = test::utils::execute(integration.cluster, req);
1631
- return resp.ctx.ec != couchbase::errc::common::bucket_not_found;
2064
+ return resp.ctx.ec != couchbase::errc::common::bucket_not_found &&
2065
+ resp.ctx.ec != couchbase::errc::common::scope_not_found;
1632
2066
  });
1633
2067
  REQUIRE(operation_completed);
1634
2068
  REQUIRE_SUCCESS(resp.ctx.ec);
@@ -1781,7 +2215,8 @@ TEST_CASE("integration: collections query index management", "[integration]")
1781
2215
  req.fields = { "field" };
1782
2216
  req.deferred = true;
1783
2217
  resp = test::utils::execute(integration.cluster, req);
1784
- return resp.ctx.ec != couchbase::errc::common::bucket_not_found;
2218
+ return resp.ctx.ec != couchbase::errc::common::bucket_not_found &&
2219
+ resp.ctx.ec != couchbase::errc::common::scope_not_found;
1785
2220
  });
1786
2221
  REQUIRE(operation_completed);
1787
2222
  REQUIRE_SUCCESS(resp.ctx.ec);
@@ -1954,18 +2389,20 @@ TEST_CASE("integration: collections query index management", "[integration]")
1954
2389
  .ec() == couchbase::errc::common::ambiguous_timeout);
1955
2390
  }
1956
2391
  }
1957
- SECTION("watch missing collection")
1958
- {
1959
- SECTION("public API")
1960
- {
1961
- couchbase::cluster c(integration.cluster);
1962
- auto coll = c.bucket(integration.ctx.bucket).scope(scope_name).collection("missing_collection");
1963
- REQUIRE(coll.query_indexes()
1964
- .watch_indexes({ index_name }, couchbase::watch_query_indexes_options().timeout(std::chrono::seconds(5)))
1965
- .get()
1966
- .ec() == couchbase::errc::common::ambiguous_timeout);
1967
- }
1968
- }
2392
+ SECTION("watch missing collection"){ SECTION("public API"){ couchbase::cluster c(integration.cluster);
2393
+ auto coll = c.bucket(integration.ctx.bucket).scope(scope_name).collection("missing_collection");
2394
+ REQUIRE(coll.query_indexes()
2395
+ .watch_indexes({ index_name }, couchbase::watch_query_indexes_options().timeout(std::chrono::seconds(5)))
2396
+ .get()
2397
+ .ec() == couchbase::errc::common::ambiguous_timeout);
2398
+ }
2399
+ }
2400
+
2401
+ {
2402
+ couchbase::core::operations::management::scope_drop_request req{ integration.ctx.bucket, scope_name };
2403
+ auto resp = test::utils::execute(integration.cluster, req);
2404
+ REQUIRE_SUCCESS(resp.ctx.ec);
2405
+ }
1969
2406
  }
1970
2407
 
1971
2408
  TEST_CASE("integration: analytics index management", "[integration]")
@@ -2597,6 +3034,12 @@ TEST_CASE("integration: analytics external link management", "[integration]")
2597
3034
  run_azure_link_test(integration, dataverse_name, link_name);
2598
3035
  }
2599
3036
  }
3037
+
3038
+ {
3039
+ couchbase::core::operations::management::scope_drop_request req{ integration.ctx.bucket, scope_name };
3040
+ auto resp = test::utils::execute(integration.cluster, req);
3041
+ REQUIRE_SUCCESS(resp.ctx.ec);
3042
+ }
2600
3043
  }
2601
3044
  }
2602
3045
  }
@@ -2662,7 +3105,7 @@ TEST_CASE("integration: search index management", "[integration]")
2662
3105
  if (integration.cluster_version().is_serverless_config_profile()) {
2663
3106
  index.plan_params_json = serverless_plan_params;
2664
3107
  }
2665
- index.params_json = R"({ "store": { "indexType": "upside_down", "kvStoreName": "moss" }})";
3108
+ index.params_json = R"({ "store": { "kvStoreName": "moss" }})";
2666
3109
  couchbase::core::operations::management::search_index_upsert_request req{};
2667
3110
  req.index = index;
2668
3111
  auto resp = test::utils::execute(integration.cluster, req);