couchbase 4.2.1 → 4.2.2
Sign up to get free protection for your applications and to get access to all the features.
- package/CMakeLists.txt +1 -0
- package/deps/couchbase-cxx-client/.gitmodules +3 -0
- package/deps/couchbase-cxx-client/.idea/misc.xml +1 -0
- package/deps/couchbase-cxx-client/.idea/vcs.xml +1 -0
- package/deps/couchbase-cxx-client/CMakeLists.txt +11 -1
- package/deps/couchbase-cxx-client/README.md +3 -3
- package/deps/couchbase-cxx-client/cmake/CompilerWarnings.cmake +4 -1
- package/deps/couchbase-cxx-client/cmake/VersionInfo.cmake +13 -1
- package/deps/couchbase-cxx-client/cmake/build_version.hxx.in +1 -0
- package/deps/couchbase-cxx-client/core/cluster.hxx +15 -5
- package/deps/couchbase-cxx-client/core/impl/build_deferred_query_indexes.cxx +17 -6
- package/deps/couchbase-cxx-client/core/impl/cluster.cxx +1 -1
- package/deps/couchbase-cxx-client/core/impl/collection_query_index_manager.cxx +93 -0
- package/deps/couchbase-cxx-client/core/impl/configuration_profiles_registry.cxx +11 -0
- package/deps/couchbase-cxx-client/core/impl/create_query_index.cxx +119 -0
- package/deps/couchbase-cxx-client/core/impl/drop_query_index.cxx +108 -0
- package/deps/couchbase-cxx-client/core/impl/get.cxx +1 -1
- package/deps/couchbase-cxx-client/core/impl/get_all_query_indexes.cxx +76 -0
- package/deps/couchbase-cxx-client/core/impl/query.cxx +5 -7
- package/deps/couchbase-cxx-client/core/impl/watch_query_indexes.cxx +168 -0
- package/deps/couchbase-cxx-client/core/io/mcbp_session.cxx +15 -1
- package/deps/couchbase-cxx-client/core/logger/configuration.hxx +3 -0
- package/deps/couchbase-cxx-client/core/logger/level.hxx +21 -0
- package/deps/couchbase-cxx-client/core/logger/logger.hxx +4 -6
- package/deps/couchbase-cxx-client/core/meta/CMakeLists.txt +4 -2
- package/deps/couchbase-cxx-client/core/meta/features.hxx +31 -0
- package/deps/couchbase-cxx-client/core/meta/version.cxx +67 -5
- package/deps/couchbase-cxx-client/core/meta/version.hxx +12 -1
- package/deps/couchbase-cxx-client/core/metrics/CMakeLists.txt +4 -1
- package/deps/couchbase-cxx-client/core/metrics/logging_meter.cxx +46 -5
- package/deps/couchbase-cxx-client/core/metrics/logging_meter.hxx +10 -26
- package/deps/couchbase-cxx-client/core/operations/document_get_projected.cxx +3 -2
- package/deps/couchbase-cxx-client/core/operations/document_query.cxx +10 -12
- package/deps/couchbase-cxx-client/core/operations/document_query.hxx +1 -3
- package/deps/couchbase-cxx-client/core/operations/management/query_index_build.cxx +8 -14
- package/deps/couchbase-cxx-client/core/operations/management/query_index_build.hxx +2 -1
- package/deps/couchbase-cxx-client/core/operations/management/query_index_build_deferred.hxx +15 -8
- package/deps/couchbase-cxx-client/core/operations/management/query_index_create.cxx +7 -14
- package/deps/couchbase-cxx-client/core/operations/management/query_index_create.hxx +2 -0
- package/deps/couchbase-cxx-client/core/operations/management/query_index_drop.cxx +11 -16
- package/deps/couchbase-cxx-client/core/operations/management/query_index_drop.hxx +2 -0
- package/deps/couchbase-cxx-client/core/operations/management/query_index_get_all.cxx +8 -12
- package/deps/couchbase-cxx-client/core/operations/management/query_index_get_all.hxx +4 -3
- package/deps/couchbase-cxx-client/core/operations/management/query_index_get_all_deferred.cxx +21 -12
- package/deps/couchbase-cxx-client/core/operations/management/query_index_get_all_deferred.hxx +3 -2
- package/deps/couchbase-cxx-client/core/origin.hxx +1 -1
- package/deps/couchbase-cxx-client/core/platform/uuid.cc +1 -2
- package/deps/couchbase-cxx-client/core/protocol/cmd_hello.hxx +5 -1
- package/deps/couchbase-cxx-client/core/query_context.hxx +79 -0
- package/deps/couchbase-cxx-client/core/tracing/CMakeLists.txt +3 -1
- package/deps/couchbase-cxx-client/core/tracing/threshold_logging_tracer.cxx +19 -4
- package/deps/couchbase-cxx-client/core/tracing/threshold_logging_tracer.hxx +2 -2
- package/deps/couchbase-cxx-client/core/transactions/async_attempt_context.hxx +10 -4
- package/deps/couchbase-cxx-client/core/transactions/atr_cleanup_entry.cxx +52 -63
- package/deps/couchbase-cxx-client/core/transactions/attempt_context.hxx +8 -3
- package/deps/couchbase-cxx-client/core/transactions/attempt_context_impl.cxx +163 -126
- package/deps/couchbase-cxx-client/core/transactions/attempt_context_impl.hxx +24 -37
- package/deps/couchbase-cxx-client/core/transactions/forward_compat.hxx +4 -4
- package/deps/couchbase-cxx-client/core/transactions/internal/atr_cleanup_entry.hxx +51 -13
- package/deps/couchbase-cxx-client/core/transactions/internal/client_record.hxx +26 -1
- package/deps/couchbase-cxx-client/core/transactions/internal/doc_record.hxx +21 -0
- package/deps/couchbase-cxx-client/core/transactions/internal/logging.hxx +40 -18
- package/deps/couchbase-cxx-client/core/transactions/internal/transaction_context.hxx +5 -0
- package/deps/couchbase-cxx-client/core/transactions/result.hxx +26 -0
- package/deps/couchbase-cxx-client/core/transactions/staged_mutation.cxx +48 -47
- package/deps/couchbase-cxx-client/core/transactions/staged_mutation.hxx +6 -6
- package/deps/couchbase-cxx-client/core/transactions/transaction_context.cxx +33 -19
- package/deps/couchbase-cxx-client/core/transactions/transaction_get_result.hxx +18 -2
- package/deps/couchbase-cxx-client/core/transactions/transaction_links.hxx +25 -2
- package/deps/couchbase-cxx-client/core/transactions/transactions.cxx +4 -4
- package/deps/couchbase-cxx-client/core/transactions/transactions_cleanup.cxx +49 -56
- package/deps/couchbase-cxx-client/core/transactions/waitable_op_list.hxx +7 -7
- package/deps/couchbase-cxx-client/core/transactions.hxx +0 -12
- package/deps/couchbase-cxx-client/core/utils/binary.hxx +1 -1
- package/deps/couchbase-cxx-client/core/utils/keyspace.hxx +55 -0
- package/deps/couchbase-cxx-client/couchbase/build_query_index_options.hxx +12 -45
- package/deps/couchbase-cxx-client/couchbase/cluster.hxx +1 -1
- package/deps/couchbase-cxx-client/couchbase/cluster_options.hxx +6 -7
- package/deps/couchbase-cxx-client/couchbase/collection.hxx +8 -0
- package/deps/couchbase-cxx-client/couchbase/collection_query_index_manager.hxx +218 -0
- package/deps/couchbase-cxx-client/couchbase/configuration_profiles_registry.hxx +3 -0
- package/deps/couchbase-cxx-client/couchbase/create_primary_query_index_options.hxx +166 -0
- package/deps/couchbase-cxx-client/couchbase/create_query_index_options.hxx +172 -0
- package/deps/couchbase-cxx-client/couchbase/drop_primary_query_index_options.hxx +129 -0
- package/deps/couchbase-cxx-client/couchbase/drop_query_index_options.hxx +116 -0
- package/deps/couchbase-cxx-client/couchbase/fmt/cas.hxx +1 -1
- package/deps/couchbase-cxx-client/couchbase/fmt/query_scan_consistency.hxx +46 -0
- package/deps/couchbase-cxx-client/couchbase/fmt/query_status.hxx +70 -0
- package/deps/couchbase-cxx-client/couchbase/fmt/tls_verify_mode.hxx +46 -0
- package/deps/couchbase-cxx-client/couchbase/get_all_query_indexes_options.hxx +100 -0
- package/deps/couchbase-cxx-client/{core → couchbase}/management/query_index.hxx +2 -2
- package/deps/couchbase-cxx-client/couchbase/metrics/meter.hxx +16 -0
- package/deps/couchbase-cxx-client/couchbase/query_index_manager.hxx +178 -6
- package/deps/couchbase-cxx-client/couchbase/query_options.hxx +1 -18
- package/deps/couchbase-cxx-client/couchbase/scope.hxx +5 -2
- package/deps/couchbase-cxx-client/couchbase/tracing/request_tracer.hxx +16 -0
- package/deps/couchbase-cxx-client/couchbase/transactions/async_attempt_context.hxx +11 -4
- package/deps/couchbase-cxx-client/couchbase/transactions/attempt_context.hxx +5 -3
- package/deps/couchbase-cxx-client/couchbase/transactions/transaction_keyspace.hxx +16 -0
- package/deps/couchbase-cxx-client/couchbase/transactions/transaction_query_options.hxx +0 -6
- package/deps/couchbase-cxx-client/couchbase/watch_query_indexes_options.hxx +115 -0
- package/deps/couchbase-cxx-client/examples/minimal.cxx +3 -1
- package/deps/couchbase-cxx-client/test/test_integration_crud.cxx +72 -0
- package/deps/couchbase-cxx-client/test/test_integration_management.cxx +727 -310
- package/deps/couchbase-cxx-client/test/test_integration_query.cxx +4 -8
- package/deps/couchbase-cxx-client/test/test_integration_transcoders.cxx +14 -0
- package/deps/couchbase-cxx-client/test/test_transaction_transaction_public_blocking_api.cxx +34 -19
- package/deps/couchbase-cxx-client/test/test_unit_transaction_logging.cxx +66 -22
- package/deps/couchbase-cxx-client/test/test_unit_utils.cxx +51 -0
- package/deps/couchbase-cxx-client/test/tools/tool_kv_loader.cxx +2 -2
- package/deps/couchbase-cxx-client/test/utils/integration_test_guard.cxx +2 -0
- package/deps/couchbase-cxx-client/test/utils/wait_until.cxx +4 -4
- package/deps/couchbase-cxx-client/third_party/docopt/.travis.yml +103 -0
- package/deps/couchbase-cxx-client/third_party/docopt/CMakeLists.txt +129 -0
- package/deps/couchbase-cxx-client/third_party/docopt/LICENSE-Boost-1.0 +23 -0
- package/deps/couchbase-cxx-client/third_party/docopt/LICENSE-MIT +23 -0
- package/deps/couchbase-cxx-client/third_party/docopt/README.rst +479 -0
- package/deps/couchbase-cxx-client/third_party/docopt/docopt-config.cmake +1 -0
- package/deps/couchbase-cxx-client/third_party/docopt/docopt.cpp +687 -0
- package/deps/couchbase-cxx-client/third_party/docopt/docopt.h +98 -0
- package/deps/couchbase-cxx-client/third_party/docopt/docopt.pc.in +9 -0
- package/deps/couchbase-cxx-client/third_party/docopt/docopt_private.h +676 -0
- package/deps/couchbase-cxx-client/third_party/docopt/docopt_util.h +122 -0
- package/deps/couchbase-cxx-client/third_party/docopt/docopt_value.h +341 -0
- package/deps/couchbase-cxx-client/third_party/docopt/examples/naval_fate.cpp +36 -0
- package/deps/couchbase-cxx-client/third_party/docopt/main.cpp +16 -0
- package/deps/couchbase-cxx-client/third_party/docopt/run_testcase.cpp +40 -0
- package/deps/couchbase-cxx-client/third_party/docopt/run_tests.py +72 -0
- package/deps/couchbase-cxx-client/third_party/docopt/testcases.docopt +957 -0
- package/deps/couchbase-cxx-client/tools/CMakeLists.txt +14 -0
- package/deps/couchbase-cxx-client/tools/cbc.cxx +65 -0
- package/deps/couchbase-cxx-client/tools/command.hxx +31 -0
- package/deps/couchbase-cxx-client/tools/command_registry.cxx +43 -0
- package/deps/couchbase-cxx-client/tools/command_registry.hxx +39 -0
- package/deps/couchbase-cxx-client/tools/get.cxx +267 -0
- package/deps/couchbase-cxx-client/tools/get.hxx +26 -0
- package/deps/couchbase-cxx-client/tools/query.cxx +441 -0
- package/deps/couchbase-cxx-client/tools/query.hxx +26 -0
- package/deps/couchbase-cxx-client/tools/utils.cxx +418 -0
- package/deps/couchbase-cxx-client/tools/utils.hxx +150 -0
- package/deps/couchbase-cxx-client/tools/version.cxx +82 -0
- package/deps/couchbase-cxx-client/tools/version.hxx +26 -0
- package/dist/authenticators.d.ts +2 -2
- package/dist/authenticators.js +1 -2
- package/dist/binding.d.ts +32 -16
- package/dist/cluster.js +14 -7
- package/dist/collection.d.ts +6 -0
- package/dist/collection.js +8 -0
- package/dist/queryexecutor.js +1 -1
- package/dist/queryindexmanager.d.ts +100 -4
- package/dist/queryindexmanager.js +344 -118
- package/dist/transactions.js +0 -2
- package/package.json +1 -1
- package/src/connection.cpp +2 -0
- package/src/connection.hpp +1 -0
- package/src/connection_autogen.cpp +16 -0
- package/src/jstocbpp_autogen.hpp +93 -23
- package/src/jstocbpp_basic.hpp +24 -0
- package/src/jstocbpp_transactions.hpp +0 -8
- package/tools/gen-bindings-js.js +1 -0
- package/tools/gen-bindings-json.py +4 -2
- package/deps/couchbase-cxx-client/core/transactions/logging.cxx +0 -107
@@ -64,9 +64,8 @@ transactions_cleanup::transactions_cleanup(std::shared_ptr<core::cluster> cluste
|
|
64
64
|
static uint64_t
|
65
65
|
byteswap64(uint64_t val)
|
66
66
|
{
|
67
|
-
std::size_t ii;
|
68
67
|
uint64_t ret = 0;
|
69
|
-
for (ii = 0; ii < sizeof(uint64_t); ii++) {
|
68
|
+
for (std::size_t ii = 0; ii < sizeof(uint64_t); ii++) {
|
70
69
|
ret <<= 8ull;
|
71
70
|
ret |= val & 0xffull;
|
72
71
|
val >>= 8ull;
|
@@ -130,12 +129,11 @@ transactions_cleanup::clean_collection(const couchbase::transactions::transactio
|
|
130
129
|
{
|
131
130
|
std::lock_guard<std::mutex> lock(mutex_);
|
132
131
|
if (collections_.end() == std::find(collections_.begin(), collections_.end(), keyspace)) {
|
133
|
-
|
134
|
-
"{} cleanup for {} ending, no longer in collection cleanup list", static_cast<void*>(this), keyspace);
|
132
|
+
CB_LOST_ATTEMPT_CLEANUP_LOG_DEBUG("cleanup for {} ending, no longer in collection cleanup list", keyspace);
|
135
133
|
return;
|
136
134
|
}
|
137
135
|
}
|
138
|
-
|
136
|
+
CB_LOST_ATTEMPT_CLEANUP_LOG_INFO("cleanup for {} starting", keyspace);
|
139
137
|
// we are running, and collection is in the list, so lets clean it.
|
140
138
|
try {
|
141
139
|
auto details = get_active_clients(keyspace, client_uuid_);
|
@@ -145,11 +143,10 @@ transactions_cleanup::clean_collection(const couchbase::transactions::transactio
|
|
145
143
|
std::chrono::microseconds cleanup_window =
|
146
144
|
std::chrono::duration_cast<std::chrono::microseconds>(config_.cleanup_config.cleanup_window);
|
147
145
|
auto start = std::chrono::steady_clock::now();
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
config_.cleanup_config.cleanup_window.count());
|
146
|
+
CB_LOST_ATTEMPT_CLEANUP_LOG_INFO("{} active clients (including this one), {} ATRs to check in {}ms",
|
147
|
+
details.num_active_clients,
|
148
|
+
all_atrs.size(),
|
149
|
+
config_.cleanup_config.cleanup_window.count());
|
153
150
|
|
154
151
|
for (auto it = all_atrs.begin() + details.index_of_this_client; it < all_atrs.end(); it += details.num_active_clients) {
|
155
152
|
auto atrs_left_for_this_client =
|
@@ -162,15 +159,14 @@ transactions_cleanup::clean_collection(const couchbase::transactions::transactio
|
|
162
159
|
// clean the ATR entry
|
163
160
|
std::string atr_id = *it;
|
164
161
|
if (!running_.load()) {
|
165
|
-
|
162
|
+
CB_LOST_ATTEMPT_CLEANUP_LOG_DEBUG("cleanup of {} complete", keyspace);
|
166
163
|
return;
|
167
164
|
}
|
168
165
|
|
169
166
|
try {
|
170
167
|
handle_atr_cleanup({ keyspace.bucket, keyspace.scope, keyspace.collection, atr_id });
|
171
168
|
} catch (const std::exception& e) {
|
172
|
-
|
173
|
-
"{} cleanup of atr {} failed with {}, moving on", static_cast<void*>(this), atr_id, e.what());
|
169
|
+
CB_LOST_ATTEMPT_CLEANUP_LOG_ERROR("cleanup of atr {} failed with {}, moving on", atr_id, e.what());
|
174
170
|
}
|
175
171
|
|
176
172
|
auto atr_end = std::chrono::steady_clock::now();
|
@@ -178,7 +174,7 @@ transactions_cleanup::clean_collection(const couchbase::transactions::transactio
|
|
178
174
|
std::chrono::microseconds atr_left = budget_for_this_atr - atr_used;
|
179
175
|
|
180
176
|
// Too verbose to log, but leaving here commented as it may be useful later for internal debugging
|
181
|
-
/*
|
177
|
+
/*CB_LOST_ATTEMPT_CLEANUP_LOG_INFO("{} {} atrs_left_for_this_client={} elapsed_in_cleanup_window={}us "
|
182
178
|
"remaining_in_cleanup_window={}us budget_for_this_atr={}us atr_used={}us atr_left={}us",
|
183
179
|
bucket_name,
|
184
180
|
atr_id,
|
@@ -194,7 +190,7 @@ transactions_cleanup::clean_collection(const couchbase::transactions::transactio
|
|
194
190
|
}
|
195
191
|
}
|
196
192
|
} catch (const std::exception& ex) {
|
197
|
-
|
193
|
+
CB_LOST_ATTEMPT_CLEANUP_LOG_ERROR("cleanup failed with {}, trying again in 3 sec...", ex.what());
|
198
194
|
// we must have gotten an exception trying to get the client records. Let's wait 3 sec and try again
|
199
195
|
std::this_thread::sleep_for(std::chrono::seconds(3));
|
200
196
|
}
|
@@ -219,13 +215,12 @@ transactions_cleanup::handle_atr_cleanup(const core::document_id& atr_id, std::v
|
|
219
215
|
if (results) {
|
220
216
|
results->emplace_back(cleanup_entry);
|
221
217
|
}
|
222
|
-
cleanup_entry.clean(
|
218
|
+
cleanup_entry.clean(results ? &results->back() : nullptr);
|
223
219
|
if (results) {
|
224
220
|
results->back().success(true);
|
225
221
|
}
|
226
222
|
} catch (const std::exception& e) {
|
227
|
-
|
228
|
-
"{} cleanup of {} failed: {}, moving on", static_cast<void*>(this), cleanup_entry, e.what());
|
223
|
+
CB_LOST_ATTEMPT_CLEANUP_LOG_ERROR("cleanup of {} failed: {}, moving on", cleanup_entry, e.what());
|
229
224
|
if (results) {
|
230
225
|
results->back().success(false);
|
231
226
|
}
|
@@ -263,11 +258,11 @@ transactions_cleanup::create_client_record(const couchbase::transactions::transa
|
|
263
258
|
wrap_operation_future(f);
|
264
259
|
|
265
260
|
} catch (const client_error& e) {
|
266
|
-
|
261
|
+
CB_LOST_ATTEMPT_CLEANUP_LOG_TRACE("create_client_record got error {}", e.what());
|
267
262
|
auto ec = e.ec();
|
268
263
|
switch (ec) {
|
269
264
|
case FAIL_DOC_ALREADY_EXISTS:
|
270
|
-
|
265
|
+
CB_LOST_ATTEMPT_CLEANUP_LOG_TRACE("client record already exists, moving on");
|
271
266
|
return;
|
272
267
|
default:
|
273
268
|
throw;
|
@@ -313,7 +308,7 @@ transactions_cleanup::get_active_clients(const couchbase::transactions::transact
|
|
313
308
|
details.override_expires = 0;
|
314
309
|
if (res.values[0].status == subdoc_result::status_type::success) {
|
315
310
|
auto records = res.values[0].content_as();
|
316
|
-
|
311
|
+
CB_LOST_ATTEMPT_CLEANUP_LOG_TRACE("client records: {}", core::utils::json::generate(records));
|
317
312
|
for (const auto& [key, value] : records.get_object()) {
|
318
313
|
if (key == FIELD_OVERRIDE) {
|
319
314
|
for (const auto& [override, param] : value.get_object()) {
|
@@ -352,9 +347,9 @@ transactions_cleanup::get_active_clients(const couchbase::transactions::transact
|
|
352
347
|
details.client_uuid = uuid;
|
353
348
|
details.cas_now_nanos = now_ms * 1000000;
|
354
349
|
details.override_active = (details.override_enabled && details.override_expires > details.cas_now_nanos);
|
355
|
-
|
350
|
+
CB_LOST_ATTEMPT_CLEANUP_LOG_TRACE("client details {}", details);
|
356
351
|
if (details.override_active) {
|
357
|
-
|
352
|
+
CB_LOST_ATTEMPT_CLEANUP_LOG_TRACE("override enabled, will not update record");
|
358
353
|
return details;
|
359
354
|
}
|
360
355
|
|
@@ -373,8 +368,8 @@ transactions_cleanup::get_active_clients(const couchbase::transactions::transact
|
|
373
368
|
.create_path(),
|
374
369
|
};
|
375
370
|
for (std::size_t idx = 0; idx < std::min(details.expired_client_ids.size(), static_cast<std::size_t>(12)); idx++) {
|
376
|
-
|
377
|
-
|
371
|
+
CB_LOST_ATTEMPT_CLEANUP_LOG_TRACE("adding {} to list of clients to be removed when updating this client",
|
372
|
+
details.expired_client_ids[idx]);
|
378
373
|
mut_specs.push_back(couchbase::mutate_in_specs::remove(FIELD_CLIENTS + "." + details.expired_client_ids[idx]).xattr());
|
379
374
|
}
|
380
375
|
mutate_req.specs = mut_specs.specs();
|
@@ -385,7 +380,7 @@ transactions_cleanup::get_active_clients(const couchbase::transactions::transact
|
|
385
380
|
wrap_durable_request(mutate_req, config_);
|
386
381
|
auto mutate_barrier = std::make_shared<std::promise<result>>();
|
387
382
|
auto mutate_f = mutate_barrier->get_future();
|
388
|
-
|
383
|
+
CB_LOST_ATTEMPT_CLEANUP_LOG_TRACE("updating record");
|
389
384
|
cluster_->execute(mutate_req, [mutate_barrier](core::operations::mutate_in_response resp) {
|
390
385
|
mutate_barrier->set_value(result::create_from_subdoc_response(resp));
|
391
386
|
});
|
@@ -393,17 +388,17 @@ transactions_cleanup::get_active_clients(const couchbase::transactions::transact
|
|
393
388
|
|
394
389
|
// just update the cas, and return the details
|
395
390
|
details.cas_now_nanos = res.cas;
|
396
|
-
|
391
|
+
CB_LOST_ATTEMPT_CLEANUP_LOG_DEBUG("get_active_clients found {}", details);
|
397
392
|
return details;
|
398
393
|
} catch (const client_error& e) {
|
399
394
|
auto ec = e.ec();
|
400
395
|
switch (ec) {
|
401
396
|
case FAIL_DOC_NOT_FOUND:
|
402
|
-
|
397
|
+
CB_LOST_ATTEMPT_CLEANUP_LOG_DEBUG("client record not found, creating new one");
|
403
398
|
create_client_record(keyspace);
|
404
399
|
throw retry_operation("Client record didn't exist. Creating and retrying");
|
405
400
|
default:
|
406
|
-
throw;
|
401
|
+
throw;
|
407
402
|
}
|
408
403
|
}
|
409
404
|
});
|
@@ -438,17 +433,16 @@ transactions_cleanup::remove_client_record_from_all_buckets(const std::string& u
|
|
438
433
|
barrier->set_value(result::create_from_subdoc_response(resp));
|
439
434
|
});
|
440
435
|
wrap_operation_future(f);
|
441
|
-
|
436
|
+
CB_LOST_ATTEMPT_CLEANUP_LOG_DEBUG("removed {} from {}", uuid, keyspace);
|
442
437
|
} catch (const client_error& e) {
|
443
|
-
|
438
|
+
CB_LOST_ATTEMPT_CLEANUP_LOG_DEBUG("error removing client records {}", e.what());
|
444
439
|
auto ec = e.ec();
|
445
440
|
switch (ec) {
|
446
441
|
case FAIL_DOC_NOT_FOUND:
|
447
|
-
|
442
|
+
CB_LOST_ATTEMPT_CLEANUP_LOG_DEBUG("no client record in {}, ignoring", keyspace);
|
448
443
|
return;
|
449
444
|
case FAIL_PATH_NOT_FOUND:
|
450
|
-
|
451
|
-
"{} client {} not in client record for {}, ignoring", static_cast<void*>(this), uuid, keyspace);
|
445
|
+
CB_LOST_ATTEMPT_CLEANUP_LOG_DEBUG("client {} not in client record for {}, ignoring", uuid, keyspace);
|
452
446
|
return;
|
453
447
|
default:
|
454
448
|
throw retry_operation("retry remove until timeout");
|
@@ -456,8 +450,7 @@ transactions_cleanup::remove_client_record_from_all_buckets(const std::string& u
|
|
456
450
|
}
|
457
451
|
});
|
458
452
|
} catch (const std::exception& e) {
|
459
|
-
|
460
|
-
"{} Error removing client record {} from {}: {}", static_cast<void*>(this), uuid, keyspace, e.what());
|
453
|
+
CB_LOST_ATTEMPT_CLEANUP_LOG_ERROR("Error removing client record {} from {}: {}", uuid, keyspace, e.what());
|
461
454
|
}
|
462
455
|
}
|
463
456
|
}
|
@@ -465,7 +458,7 @@ transactions_cleanup::remove_client_record_from_all_buckets(const std::string& u
|
|
465
458
|
const atr_cleanup_stats
|
466
459
|
transactions_cleanup::force_cleanup_atr(const core::document_id& atr_id, std::vector<transactions_cleanup_attempt>& results)
|
467
460
|
{
|
468
|
-
|
461
|
+
CB_LOST_ATTEMPT_CLEANUP_LOG_TRACE("starting force_cleanup_atr: atr_id {}", atr_id);
|
469
462
|
return handle_atr_cleanup(atr_id, &results);
|
470
463
|
}
|
471
464
|
|
@@ -473,11 +466,11 @@ void
|
|
473
466
|
transactions_cleanup::force_cleanup_entry(atr_cleanup_entry& entry, transactions_cleanup_attempt& attempt)
|
474
467
|
{
|
475
468
|
try {
|
476
|
-
entry.clean(
|
469
|
+
entry.clean(&attempt);
|
477
470
|
attempt.success(true);
|
478
471
|
|
479
472
|
} catch (const std::runtime_error& e) {
|
480
|
-
|
473
|
+
CB_ATTEMPT_CLEANUP_LOG_ERROR("error attempting to clean {}: {}", entry, e.what());
|
481
474
|
attempt.success(false);
|
482
475
|
}
|
483
476
|
}
|
@@ -485,16 +478,16 @@ transactions_cleanup::force_cleanup_entry(atr_cleanup_entry& entry, transactions
|
|
485
478
|
void
|
486
479
|
transactions_cleanup::force_cleanup_attempts(std::vector<transactions_cleanup_attempt>& results)
|
487
480
|
{
|
488
|
-
|
481
|
+
CB_ATTEMPT_CLEANUP_LOG_TRACE("starting force_cleanup_attempts");
|
489
482
|
while (atr_queue_.size() > 0) {
|
490
483
|
auto entry = atr_queue_.pop(false);
|
491
484
|
if (!entry) {
|
492
|
-
|
485
|
+
CB_ATTEMPT_CLEANUP_LOG_ERROR("pop failed to return entry, but queue size {}", atr_queue_.size());
|
493
486
|
return;
|
494
487
|
}
|
495
488
|
results.emplace_back(*entry);
|
496
489
|
try {
|
497
|
-
entry->clean(
|
490
|
+
entry->clean(&results.back());
|
498
491
|
results.back().success(true);
|
499
492
|
} catch (std::runtime_error&) {
|
500
493
|
results.back().success(false);
|
@@ -506,27 +499,27 @@ void
|
|
506
499
|
transactions_cleanup::attempts_loop()
|
507
500
|
{
|
508
501
|
try {
|
509
|
-
|
502
|
+
CB_ATTEMPT_CLEANUP_LOG_DEBUG("cleanup attempts loop starting...");
|
510
503
|
while (interruptable_wait(cleanup_loop_delay_)) {
|
511
504
|
while (auto entry = atr_queue_.pop()) {
|
512
505
|
if (!running_.load()) {
|
513
|
-
|
506
|
+
CB_ATTEMPT_CLEANUP_LOG_DEBUG("loop stopping - {} entries on queue", atr_queue_.size());
|
514
507
|
return;
|
515
508
|
}
|
516
509
|
if (entry) {
|
517
|
-
|
510
|
+
CB_ATTEMPT_CLEANUP_LOG_TRACE("beginning cleanup on {}", *entry);
|
518
511
|
try {
|
519
|
-
entry->clean(
|
512
|
+
entry->clean();
|
520
513
|
} catch (...) {
|
521
514
|
// catch everything as we don't want to raise out of this thread
|
522
|
-
|
515
|
+
CB_ATTEMPT_CLEANUP_LOG_DEBUG("got error cleaning {}, leaving for lost txn cleanup", entry.value());
|
523
516
|
}
|
524
517
|
}
|
525
518
|
}
|
526
519
|
}
|
527
|
-
|
520
|
+
CB_ATTEMPT_CLEANUP_LOG_DEBUG("stopping - {} entries on queue", atr_queue_.size());
|
528
521
|
} catch (const std::runtime_error& e) {
|
529
|
-
|
522
|
+
CB_ATTEMPT_CLEANUP_LOG_ERROR("got error \"{}\" in attempts_loop", e.what());
|
530
523
|
}
|
531
524
|
}
|
532
525
|
|
@@ -538,14 +531,14 @@ transactions_cleanup::add_attempt(attempt_context& ctx)
|
|
538
531
|
case attempt_state::NOT_STARTED:
|
539
532
|
case attempt_state::COMPLETED:
|
540
533
|
case attempt_state::ROLLED_BACK:
|
541
|
-
|
534
|
+
CB_ATTEMPT_CLEANUP_LOG_TRACE("attempt in state {}, not adding to cleanup", attempt_state_name(ctx_impl.state()));
|
542
535
|
return;
|
543
536
|
default:
|
544
537
|
if (config_.cleanup_config.cleanup_client_attempts) {
|
545
|
-
|
538
|
+
CB_ATTEMPT_CLEANUP_LOG_DEBUG("adding attempt {} to cleanup queue", ctx_impl.id());
|
546
539
|
atr_queue_.push(ctx);
|
547
540
|
} else {
|
548
|
-
|
541
|
+
CB_ATTEMPT_CLEANUP_LOG_TRACE("not cleaning client attempts, ignoring {}", ctx_impl.id());
|
549
542
|
}
|
550
543
|
}
|
551
544
|
}
|
@@ -564,7 +557,7 @@ transactions_cleanup::add_collection(couchbase::transactions::transaction_keyspa
|
|
564
557
|
lost_attempt_cleanup_workers_.emplace_back([this, keyspace = collections_.back()]() { this->clean_collection(keyspace); });
|
565
558
|
}
|
566
559
|
lock.unlock();
|
567
|
-
|
560
|
+
CB_ATTEMPT_CLEANUP_LOG_DEBUG("added {} to lost transaction cleanup", keyspace);
|
568
561
|
}
|
569
562
|
}
|
570
563
|
|
@@ -578,15 +571,15 @@ transactions_cleanup::close()
|
|
578
571
|
}
|
579
572
|
if (cleanup_thr_.joinable()) {
|
580
573
|
cleanup_thr_.join();
|
581
|
-
|
574
|
+
CB_ATTEMPT_CLEANUP_LOG_DEBUG("cleanup attempt thread closed");
|
582
575
|
}
|
583
576
|
for (auto& t : lost_attempt_cleanup_workers_) {
|
584
|
-
|
577
|
+
CB_LOST_ATTEMPT_CLEANUP_LOG_DEBUG("shutting down all lost attempt threads...");
|
585
578
|
if (t.joinable()) {
|
586
579
|
t.join();
|
587
580
|
}
|
588
581
|
}
|
589
|
-
|
582
|
+
CB_LOST_ATTEMPT_CLEANUP_LOG_DEBUG("all lost attempt cleanup threads closed");
|
590
583
|
if (true) {
|
591
584
|
remove_client_record_from_all_buckets(client_uuid_);
|
592
585
|
}
|
@@ -98,11 +98,11 @@ class waitable_op_list
|
|
98
98
|
in_flight_--;
|
99
99
|
if (mode_.mode == attempt_mode::modes::KV) {
|
100
100
|
// wait until all in_flight ops are done
|
101
|
-
|
101
|
+
CB_TXN_LOG_TRACE("set_query_mode: waiting for in_flight ops to go to 0...");
|
102
102
|
cv_in_flight_.wait(lock, [this]() { return (0 == in_flight_); });
|
103
103
|
// ok, now no outstanding ops(apart from the query that called this), and I have the lock, so...
|
104
104
|
if (mode_.mode == attempt_mode::modes::KV) {
|
105
|
-
|
105
|
+
CB_TXN_LOG_TRACE("set_query_mode: in_flight ops = 0, we were kv, setting mode to query");
|
106
106
|
// still kv, so now (while blocking) set the mode
|
107
107
|
mode_.mode = attempt_mode::modes::QUERY;
|
108
108
|
// ok to unlock now, as any racing set_query_mode will wait for
|
@@ -117,10 +117,10 @@ class waitable_op_list
|
|
117
117
|
}
|
118
118
|
// you make it here, and someone else is currently setting the node (a byproduct of
|
119
119
|
// calling the callback). So wait for that.
|
120
|
-
|
120
|
+
CB_TXN_LOG_TRACE("set_query_mode: mode already query, waiting for node to be set...");
|
121
121
|
cv_query_.wait(lock, [this]() { return !mode_.query_node.empty(); });
|
122
122
|
in_flight_++;
|
123
|
-
|
123
|
+
CB_TXN_LOG_TRACE("set_query_mode: node set, continuing...");
|
124
124
|
lock.unlock();
|
125
125
|
cb();
|
126
126
|
}
|
@@ -145,7 +145,7 @@ class waitable_op_list
|
|
145
145
|
{
|
146
146
|
std::lock_guard<std::mutex> lock(mutex_);
|
147
147
|
in_flight_--;
|
148
|
-
|
148
|
+
CB_TXN_LOG_TRACE("in_flight decremented to {}", in_flight_);
|
149
149
|
assert(in_flight_ >= 0);
|
150
150
|
if (0 == in_flight_) {
|
151
151
|
cv_in_flight_.notify_all();
|
@@ -161,7 +161,7 @@ class waitable_op_list
|
|
161
161
|
if (val > 0) {
|
162
162
|
in_flight_ += val;
|
163
163
|
}
|
164
|
-
|
164
|
+
CB_TXN_LOG_TRACE("op count changed by {} to {}, {} in_flight", val, count_, in_flight_);
|
165
165
|
assert(count_ >= 0);
|
166
166
|
assert(in_flight_ >= 0);
|
167
167
|
if (0 == count_) {
|
@@ -171,7 +171,7 @@ class waitable_op_list
|
|
171
171
|
cv_in_flight_.notify_all();
|
172
172
|
}
|
173
173
|
} else {
|
174
|
-
|
174
|
+
CB_TXN_LOG_ERROR("operation attempted after commit/rollback");
|
175
175
|
throw async_operation_conflict("Operation attempted after commit or rollback");
|
176
176
|
}
|
177
177
|
}
|
@@ -61,18 +61,6 @@ using async_logic = std::function<void(async_attempt_context&)>;
|
|
61
61
|
using txn_complete_callback =
|
62
62
|
std::function<void(std::optional<transaction_exception>, std::optional<::couchbase::transactions::transaction_result>)>;
|
63
63
|
|
64
|
-
/**
|
65
|
-
* @brief set log level for transactions
|
66
|
-
*/
|
67
|
-
void
|
68
|
-
set_transactions_log_level(core::logger::level level);
|
69
|
-
|
70
|
-
/**
|
71
|
-
* @brief create the loggers, using a custom spdlog::sink, if desired.
|
72
|
-
*/
|
73
|
-
void
|
74
|
-
create_loggers(core::logger::level level = core::logger::level::off, spdlog::sink_ptr = nullptr);
|
75
|
-
|
76
64
|
/**
|
77
65
|
* @mainpage
|
78
66
|
* A transaction consists of a lambda containing all the operations you wish to perform within a transaction.
|
@@ -34,7 +34,7 @@ to_binary(const T* data, const std::size_t size) noexcept
|
|
34
34
|
static_assert(sizeof(T) == 1);
|
35
35
|
binary copy;
|
36
36
|
copy.reserve(size);
|
37
|
-
|
37
|
+
copy.insert(copy.end(), reinterpret_cast<const std::byte*>(data), reinterpret_cast<const std::byte*>(data + size));
|
38
38
|
return copy;
|
39
39
|
}
|
40
40
|
|
@@ -0,0 +1,55 @@
|
|
1
|
+
/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
2
|
+
/*
|
3
|
+
* Copyright 2020-2021 Couchbase, Inc.
|
4
|
+
*
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
* you may not use this file except in compliance with the License.
|
7
|
+
* You may obtain a copy of the License at
|
8
|
+
*
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
*
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
* See the License for the specific language governing permissions and
|
15
|
+
* limitations under the License.
|
16
|
+
*/
|
17
|
+
|
18
|
+
#pragma once
|
19
|
+
|
20
|
+
#include <fmt/format.h>
|
21
|
+
#include <string>
|
22
|
+
|
23
|
+
namespace couchbase::core::utils
|
24
|
+
{
|
25
|
+
template<typename Request>
|
26
|
+
static bool
|
27
|
+
check_query_management_request(const Request& req)
|
28
|
+
{
|
29
|
+
// if there is a query_context, then bucket, scope should not be specified, but collection should be.
|
30
|
+
// collection should be.
|
31
|
+
if (req.query_ctx.has_value()) {
|
32
|
+
return !req.collection_name.empty() && req.bucket_name.empty() && req.scope_name.empty();
|
33
|
+
}
|
34
|
+
// otherwise, both scope and collection must be specified, if one is
|
35
|
+
// and bucket _must_ be there as well.
|
36
|
+
return !req.bucket_name.empty() &&
|
37
|
+
((req.scope_name.empty() && req.collection_name.empty()) || (!req.scope_name.empty() && !req.collection_name.empty()));
|
38
|
+
}
|
39
|
+
|
40
|
+
template<typename Request>
|
41
|
+
static std::string
|
42
|
+
build_keyspace(const Request& req)
|
43
|
+
{
|
44
|
+
// keyspace is just the collection if we have a query_context.
|
45
|
+
if (req.query_ctx.has_value()) {
|
46
|
+
return fmt::format("{}.`{}`", req.query_ctx.value(), req.collection_name);
|
47
|
+
}
|
48
|
+
// otherwise, build from the bucket, scope and collection names in request...
|
49
|
+
if (req.scope_name.empty() && req.collection_name.empty()) {
|
50
|
+
return fmt::format("{}:`{}`", req.namespace_id, req.bucket_name);
|
51
|
+
}
|
52
|
+
return fmt::format("{}:`{}`.`{}`.`{}`", req.namespace_id, req.bucket_name, req.scope_name, req.collection_name);
|
53
|
+
}
|
54
|
+
|
55
|
+
} // namespace couchbase::core::utils
|
@@ -18,6 +18,7 @@
|
|
18
18
|
#pragma once
|
19
19
|
|
20
20
|
#include <couchbase/common_options.hxx>
|
21
|
+
#include <couchbase/error_codes.hxx>
|
21
22
|
#include <couchbase/manager_error_context.hxx>
|
22
23
|
|
23
24
|
#include <functional>
|
@@ -36,40 +37,6 @@ namespace couchbase
|
|
36
37
|
class build_query_index_options : public common_options<build_query_index_options>
|
37
38
|
{
|
38
39
|
public:
|
39
|
-
/**
|
40
|
-
* Sets the scope name for this query management operation.
|
41
|
-
*
|
42
|
-
* Please note that if the scope name is set, the {@link #collection_name} must also be set.
|
43
|
-
*
|
44
|
-
* @since 1.0.0
|
45
|
-
* @committed
|
46
|
-
*/
|
47
|
-
auto scope_name(std::string scope_name) -> build_query_index_options&
|
48
|
-
{
|
49
|
-
scope_name_.emplace(std::move(scope_name));
|
50
|
-
return self();
|
51
|
-
}
|
52
|
-
|
53
|
-
/**
|
54
|
-
* Sets the collection name for this query management operation.
|
55
|
-
*
|
56
|
-
* Please note that if the collection name is set, the {@link #scope_name} must also be set.
|
57
|
-
*
|
58
|
-
* @since 1.0.0
|
59
|
-
* @committed
|
60
|
-
*/
|
61
|
-
auto collection_name(std::string collection_name) -> build_query_index_options&
|
62
|
-
{
|
63
|
-
collection_name_.emplace(std::move(collection_name));
|
64
|
-
return self();
|
65
|
-
}
|
66
|
-
|
67
|
-
/**
|
68
|
-
* Immutable value object representing consistent options.
|
69
|
-
*
|
70
|
-
* @since 1.0.0
|
71
|
-
* @internal
|
72
|
-
*/
|
73
40
|
struct built : public common_options<build_query_index_options>::built {
|
74
41
|
const std::optional<std::string> scope_name{};
|
75
42
|
const std::optional<std::string> collection_name{};
|
@@ -87,18 +54,9 @@ class build_query_index_options : public common_options<build_query_index_option
|
|
87
54
|
*/
|
88
55
|
[[nodiscard]] auto build() const -> built
|
89
56
|
{
|
90
|
-
if (scope_name_.has_value() && !collection_name_.has_value()) {
|
91
|
-
throw std::system_error(errc::common::invalid_argument, "if a scope_name is provided, a collection_name must also be provided");
|
92
|
-
}
|
93
|
-
if (!scope_name_.has_value() && collection_name_.has_value()) {
|
94
|
-
throw std::system_error(errc::common::invalid_argument, "if a collection_name is provided, a scope_name must also be provided");
|
95
|
-
}
|
96
|
-
return { build_common_options(), scope_name_, collection_name_ };
|
97
|
-
}
|
98
57
|
|
99
|
-
|
100
|
-
|
101
|
-
std::optional<std::string> collection_name_{};
|
58
|
+
return { build_common_options() };
|
59
|
+
}
|
102
60
|
};
|
103
61
|
|
104
62
|
/**
|
@@ -113,6 +71,7 @@ using build_deferred_query_indexes_handler = std::function<void(couchbase::manag
|
|
113
71
|
namespace core
|
114
72
|
{
|
115
73
|
class cluster;
|
74
|
+
class query_context;
|
116
75
|
namespace impl
|
117
76
|
{
|
118
77
|
|
@@ -121,6 +80,14 @@ namespace impl
|
|
121
80
|
* @internal
|
122
81
|
*/
|
123
82
|
void
|
83
|
+
initiate_build_deferred_indexes(std::shared_ptr<couchbase::core::cluster> resp1,
|
84
|
+
std::string bucket_name,
|
85
|
+
build_query_index_options::built options,
|
86
|
+
query_context query_ctx,
|
87
|
+
std::string collection_name,
|
88
|
+
build_deferred_query_indexes_handler&& handler);
|
89
|
+
|
90
|
+
void
|
124
91
|
initiate_build_deferred_indexes(std::shared_ptr<couchbase::core::cluster> resp1,
|
125
92
|
std::string bucket_name,
|
126
93
|
build_query_index_options::built options,
|
@@ -141,7 +141,7 @@ class cluster
|
|
141
141
|
template<typename Handler>
|
142
142
|
void query(std::string statement, const query_options& options, Handler&& handler) const
|
143
143
|
{
|
144
|
-
return core::impl::initiate_query_operation(core_, std::move(statement), {},
|
144
|
+
return core::impl::initiate_query_operation(core_, std::move(statement), {}, options.build(), std::forward<Handler>(handler));
|
145
145
|
}
|
146
146
|
|
147
147
|
/**
|
@@ -72,8 +72,10 @@ class cluster_options
|
|
72
72
|
explicit cluster_options(password_authenticator authenticator)
|
73
73
|
: username_{ std::move(authenticator.username_) }
|
74
74
|
, password_{ std::move(authenticator.password_) }
|
75
|
-
, ldap_compatible_{ authenticator.ldap_compatible_ }
|
76
75
|
{
|
76
|
+
if (authenticator.ldap_compatible_) {
|
77
|
+
sasl_mechanisms_ = { { "PLAIN" } };
|
78
|
+
}
|
77
79
|
}
|
78
80
|
|
79
81
|
/**
|
@@ -246,7 +248,7 @@ class cluster_options
|
|
246
248
|
std::string password;
|
247
249
|
std::string certificate_path;
|
248
250
|
std::string key_path;
|
249
|
-
std::vector<std::string
|
251
|
+
std::optional<std::vector<std::string>> allowed_sasl_mechanisms;
|
250
252
|
compression_options::built compression;
|
251
253
|
timeout_options::built timeouts;
|
252
254
|
dns_options::built dns;
|
@@ -261,15 +263,12 @@ class cluster_options
|
|
261
263
|
|
262
264
|
[[nodiscard]] auto build() const -> built
|
263
265
|
{
|
264
|
-
static const std::vector<std::string> default_sasl_mechanisms{ "SCRAM-SHA512", "SCRAM-SHA256", "SCRAM-SHA1" };
|
265
|
-
static const std::vector<std::string> ldap_sasl_mechanisms{ "PLAIN" };
|
266
|
-
|
267
266
|
return {
|
268
267
|
username_,
|
269
268
|
password_,
|
270
269
|
certificate_path_,
|
271
270
|
key_path_,
|
272
|
-
|
271
|
+
sasl_mechanisms_,
|
273
272
|
compression_.build(),
|
274
273
|
timeouts_.build(),
|
275
274
|
dns_.build(),
|
@@ -288,7 +287,7 @@ class cluster_options
|
|
288
287
|
std::string password_{};
|
289
288
|
std::string certificate_path_{};
|
290
289
|
std::string key_path_{};
|
291
|
-
|
290
|
+
std::optional<std::vector<std::string>> sasl_mechanisms_{};
|
292
291
|
|
293
292
|
compression_options compression_{};
|
294
293
|
timeout_options timeouts_{};
|
@@ -19,6 +19,7 @@
|
|
19
19
|
|
20
20
|
#include <couchbase/binary_collection.hxx>
|
21
21
|
#include <couchbase/codec/default_json_transcoder.hxx>
|
22
|
+
#include <couchbase/collection_query_index_manager.hxx>
|
22
23
|
#include <couchbase/exists_options.hxx>
|
23
24
|
#include <couchbase/expiry.hxx>
|
24
25
|
#include <couchbase/get_all_replicas_options.hxx>
|
@@ -31,12 +32,14 @@
|
|
31
32
|
#include <couchbase/lookup_in_specs.hxx>
|
32
33
|
#include <couchbase/mutate_in_options.hxx>
|
33
34
|
#include <couchbase/mutate_in_specs.hxx>
|
35
|
+
#include <couchbase/query_options.hxx>
|
34
36
|
#include <couchbase/remove_options.hxx>
|
35
37
|
#include <couchbase/replace_options.hxx>
|
36
38
|
#include <couchbase/touch_options.hxx>
|
37
39
|
#include <couchbase/unlock_options.hxx>
|
38
40
|
#include <couchbase/upsert_options.hxx>
|
39
41
|
|
42
|
+
#include <fmt/format.h>
|
40
43
|
#include <future>
|
41
44
|
#include <memory>
|
42
45
|
|
@@ -991,6 +994,11 @@ class collection
|
|
991
994
|
return future;
|
992
995
|
}
|
993
996
|
|
997
|
+
[[nodiscard]] auto query_indexes() const -> collection_query_index_manager
|
998
|
+
{
|
999
|
+
return collection_query_index_manager(core_, bucket_name_, scope_name_, name_);
|
1000
|
+
}
|
1001
|
+
|
994
1002
|
private:
|
995
1003
|
friend class bucket;
|
996
1004
|
friend class scope;
|