couchbase 4.2.11-rc.1 → 4.3.0
Sign up to get free protection for your applications and to get access to all the features.
- package/deps/couchbase-cxx-cache/mozilla-ca-bundle.crt +49 -2
- package/deps/couchbase-cxx-cache/mozilla-ca-bundle.sha256 +1 -1
- package/deps/couchbase-cxx-client/CMakeLists.txt +1 -0
- package/deps/couchbase-cxx-client/cmake/ThirdPartyDependencies.cmake +2 -0
- package/deps/couchbase-cxx-client/core/bucket.cxx +2 -2
- package/deps/couchbase-cxx-client/core/impl/cluster.cxx +51 -5
- package/deps/couchbase-cxx-client/core/impl/collection.cxx +224 -209
- package/deps/couchbase-cxx-client/core/impl/query_error_context.cxx +2 -2
- package/deps/couchbase-cxx-client/core/impl/query_index_manager.cxx +1 -0
- package/deps/couchbase-cxx-client/core/io/dns_client.cxx +4 -0
- package/deps/couchbase-cxx-client/core/io/dns_config.cxx +15 -4
- package/deps/couchbase-cxx-client/core/io/dns_config.hxx +1 -1
- package/deps/couchbase-cxx-client/core/io/mcbp_session.cxx +95 -53
- package/deps/couchbase-cxx-client/core/io/mcbp_session.hxx +1 -0
- package/deps/couchbase-cxx-client/core/mcbp/operation_queue.cxx +1 -0
- package/deps/couchbase-cxx-client/core/meta/features.hxx +5 -0
- package/deps/couchbase-cxx-client/core/operations/document_lookup_in_all_replicas.hxx +116 -105
- package/deps/couchbase-cxx-client/core/operations/document_lookup_in_any_replica.hxx +116 -108
- package/deps/couchbase-cxx-client/core/operations/document_search.cxx +97 -81
- package/deps/couchbase-cxx-client/core/operations/document_search.hxx +5 -0
- package/deps/couchbase-cxx-client/core/range_scan_load_balancer.cxx +141 -0
- package/deps/couchbase-cxx-client/core/range_scan_load_balancer.hxx +64 -0
- package/deps/couchbase-cxx-client/core/range_scan_orchestrator.cxx +224 -336
- package/deps/couchbase-cxx-client/core/range_scan_orchestrator.hxx +5 -6
- package/deps/couchbase-cxx-client/core/range_scan_orchestrator_options.hxx +8 -5
- package/deps/couchbase-cxx-client/core/scan_result.hxx +1 -11
- package/deps/couchbase-cxx-client/core/transactions/atr_cleanup_entry.cxx +16 -7
- package/deps/couchbase-cxx-client/core/transactions/attempt_context_impl.cxx +578 -483
- package/deps/couchbase-cxx-client/core/transactions/attempt_context_testing_hooks.cxx +51 -50
- package/deps/couchbase-cxx-client/core/transactions/attempt_context_testing_hooks.hxx +4 -2
- package/deps/couchbase-cxx-client/core/transactions/cleanup_testing_hooks.cxx +6 -6
- package/deps/couchbase-cxx-client/core/transactions/cleanup_testing_hooks.hxx +3 -2
- package/deps/couchbase-cxx-client/core/transactions/internal/transactions_cleanup.hxx +2 -0
- package/deps/couchbase-cxx-client/core/transactions/internal/utils.hxx +5 -1
- package/deps/couchbase-cxx-client/core/transactions/staged_mutation.cxx +222 -179
- package/deps/couchbase-cxx-client/core/transactions/staged_mutation.hxx +23 -12
- package/deps/couchbase-cxx-client/core/transactions/transactions.cxx +61 -24
- package/deps/couchbase-cxx-client/core/transactions/transactions_cleanup.cxx +36 -16
- package/deps/couchbase-cxx-client/core/transactions/utils.cxx +9 -0
- package/deps/couchbase-cxx-client/core/transactions.hxx +40 -7
- package/deps/couchbase-cxx-client/couchbase/bucket.hxx +2 -2
- package/deps/couchbase-cxx-client/couchbase/cluster.hxx +20 -1
- package/deps/couchbase-cxx-client/couchbase/collection.hxx +1 -0
- package/deps/couchbase-cxx-client/couchbase/collection_query_index_manager.hxx +1 -1
- package/deps/couchbase-cxx-client/couchbase/error_context.hxx +1 -0
- package/deps/couchbase-cxx-client/couchbase/fork_event.hxx +39 -0
- package/deps/couchbase-cxx-client/couchbase/get_links_analytics_options.hxx +2 -2
- package/deps/couchbase-cxx-client/couchbase/scope.hxx +1 -1
- package/deps/couchbase-cxx-client/couchbase/search_options.hxx +2 -2
- package/deps/couchbase-cxx-client/couchbase/search_result.hxx +1 -1
- package/deps/couchbase-cxx-client/couchbase/subdocument_error_context.hxx +1 -0
- package/deps/couchbase-cxx-client/couchbase/transactions/transaction_options.hxx +1 -1
- package/deps/couchbase-cxx-client/couchbase-sdk-cxx-black-duck-manifest.yaml +1 -0
- package/dist/binding.d.ts +8 -0
- package/dist/bindingutilities.d.ts +6 -1
- package/dist/bindingutilities.js +15 -1
- package/dist/bucketmanager.d.ts +0 -12
- package/dist/cluster.d.ts +0 -2
- package/dist/cluster.js +0 -2
- package/dist/collection.d.ts +3 -3
- package/dist/collection.js +3 -1
- package/dist/querytypes.d.ts +0 -2
- package/dist/rangeScan.d.ts +0 -8
- package/dist/rangeScan.js +0 -8
- package/dist/scope.d.ts +0 -5
- package/dist/scope.js +0 -5
- package/dist/scopesearchindexmanager.d.ts +0 -2
- package/dist/scopesearchindexmanager.js +0 -2
- package/dist/searchexecutor.js +3 -1
- package/dist/searchtypes.d.ts +16 -6
- package/dist/searchtypes.js +2 -6
- package/dist/transactions.d.ts +23 -0
- package/dist/transactions.js +16 -10
- package/dist/vectorsearch.d.ts +8 -8
- package/dist/vectorsearch.js +7 -7
- package/package.json +7 -7
- package/src/instance.cpp +11 -1
- package/src/instance.hpp +1 -0
- package/src/jstocbpp_autogen.hpp +8 -1
- package/src/jstocbpp_transactions.hpp +40 -3
- package/src/transactions.cpp +12 -1
- package/tools/gen-bindings-json.py +0 -1
- package/deps/couchbase-cxx-client/core/scan_options.hxx +0 -44
@@ -210,6 +210,7 @@ class mcbp_session_impl
|
|
210
210
|
std::shared_ptr<mcbp_session_impl> session_;
|
211
211
|
sasl::ClientContext sasl_;
|
212
212
|
std::atomic_bool stopped_{ false };
|
213
|
+
std::string last_error_message_;
|
213
214
|
|
214
215
|
public:
|
215
216
|
~bootstrap_handler()
|
@@ -234,6 +235,16 @@ class mcbp_session_impl
|
|
234
235
|
return { "SCRAM-SHA512", "SCRAM-SHA256", "SCRAM-SHA1" };
|
235
236
|
}
|
236
237
|
|
238
|
+
std::string last_error_message() &&
|
239
|
+
{
|
240
|
+
return std::move(last_error_message_);
|
241
|
+
}
|
242
|
+
|
243
|
+
[[nodiscard]] const std::string& last_error_message() const&
|
244
|
+
{
|
245
|
+
return last_error_message_;
|
246
|
+
}
|
247
|
+
|
237
248
|
explicit bootstrap_handler(std::shared_ptr<mcbp_session_impl> session)
|
238
249
|
: session_(std::move(session))
|
239
250
|
, sasl_([origin = session_->origin_]() { return origin.username(); },
|
@@ -322,21 +333,21 @@ class mcbp_session_impl
|
|
322
333
|
case key_value_status_code::rate_limited_max_connections:
|
323
334
|
case key_value_status_code::rate_limited_network_egress:
|
324
335
|
case key_value_status_code::rate_limited_network_ingress:
|
325
|
-
|
326
|
-
"
|
327
|
-
session_->log_prefix_,
|
336
|
+
last_error_message_ = fmt::format(
|
337
|
+
"unable to bootstrap MCBP session (bucket={}, opcode={}, status={}), the user has reached rate limit",
|
328
338
|
session_->bucket_name_.value_or(""),
|
329
339
|
protocol::client_opcode(msg.header.opcode),
|
330
340
|
status);
|
341
|
+
CB_LOG_DEBUG("{} {}", session_->log_prefix_, last_error_message_);
|
331
342
|
return complete(errc::common::rate_limited);
|
332
343
|
|
333
344
|
case key_value_status_code::scope_size_limit_exceeded:
|
334
|
-
|
335
|
-
"
|
336
|
-
session_->log_prefix_,
|
345
|
+
last_error_message_ = fmt::format(
|
346
|
+
"unable to bootstrap MCBP session (bucket={}, opcode={}, status={}), the user has reached quota limit",
|
337
347
|
session_->bucket_name_.value_or(""),
|
338
348
|
protocol::client_opcode(msg.header.opcode),
|
339
349
|
status);
|
350
|
+
CB_LOG_DEBUG("{} {}", session_->log_prefix_, last_error_message_);
|
340
351
|
return complete(errc::common::quota_limited);
|
341
352
|
|
342
353
|
default:
|
@@ -356,20 +367,18 @@ class mcbp_session_impl
|
|
356
367
|
return auth_success();
|
357
368
|
}
|
358
369
|
} else {
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
resp.opaque());
|
370
|
+
last_error_message_ = fmt::format(
|
371
|
+
"unexpected message status during bootstrap: {} (opaque={})", resp.error_message(), resp.opaque());
|
372
|
+
CB_LOG_WARNING("{} {}", session_->log_prefix_, last_error_message_);
|
363
373
|
return complete(errc::network::handshake_failure);
|
364
374
|
}
|
365
375
|
} break;
|
366
376
|
case protocol::client_opcode::sasl_list_mechs: {
|
367
377
|
protocol::client_response<protocol::sasl_list_mechs_response_body> resp(std::move(msg));
|
368
378
|
if (resp.status() != key_value_status_code::success) {
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
resp.opaque());
|
379
|
+
last_error_message_ = fmt::format(
|
380
|
+
"unexpected message status during bootstrap: {} (opaque={})", resp.error_message(), resp.opaque());
|
381
|
+
CB_LOG_WARNING("{} {}", session_->log_prefix_, last_error_message_);
|
373
382
|
return complete(errc::common::authentication_failure);
|
374
383
|
}
|
375
384
|
} break;
|
@@ -390,17 +399,17 @@ class mcbp_session_impl
|
|
390
399
|
req.body().sasl_data(sasl_payload);
|
391
400
|
session_->write_and_flush(req.data());
|
392
401
|
} else {
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
resp.opaque());
|
402
|
+
last_error_message_ =
|
403
|
+
fmt::format("unable to authenticate: (sasl_code={}, opaque={})", sasl_code, resp.opaque());
|
404
|
+
CB_LOG_ERROR("{} {}", session_->log_prefix_, last_error_message_);
|
397
405
|
return complete(errc::common::authentication_failure);
|
398
406
|
}
|
399
407
|
} else {
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
408
|
+
last_error_message_ = fmt::format("{} unexpected message status during bootstrap: {} (opaque={})",
|
409
|
+
session_->log_prefix_,
|
410
|
+
resp.error_message(),
|
411
|
+
resp.opaque());
|
412
|
+
CB_LOG_WARNING("{} {}", session_->log_prefix_, last_error_message_);
|
404
413
|
return complete(errc::common::authentication_failure);
|
405
414
|
}
|
406
415
|
} break;
|
@@ -409,6 +418,9 @@ class mcbp_session_impl
|
|
409
418
|
if (resp.status() == key_value_status_code::success) {
|
410
419
|
return auth_success();
|
411
420
|
}
|
421
|
+
last_error_message_ =
|
422
|
+
fmt::format("unable to authenticate (opcode={}, status={}, opaque={})", opcode, resp.status(), resp.opaque());
|
423
|
+
CB_LOG_ERROR("{} {}", session_->log_prefix_, last_error_message_);
|
412
424
|
return complete(errc::common::authentication_failure);
|
413
425
|
}
|
414
426
|
case protocol::client_opcode::get_error_map: {
|
@@ -416,11 +428,11 @@ class mcbp_session_impl
|
|
416
428
|
if (resp.status() == key_value_status_code::success) {
|
417
429
|
session_->error_map_.emplace(resp.body().errmap());
|
418
430
|
} else {
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
431
|
+
last_error_message_ = fmt::format("unexpected message status during bootstrap: {} (opaque={}, {:n})",
|
432
|
+
resp.error_message(),
|
433
|
+
resp.opaque(),
|
434
|
+
spdlog::to_hex(resp.header()));
|
435
|
+
CB_LOG_WARNING("{} {}", session_->log_prefix_, last_error_message_);
|
424
436
|
return complete(errc::network::protocol_error);
|
425
437
|
}
|
426
438
|
} break;
|
@@ -430,25 +442,25 @@ class mcbp_session_impl
|
|
430
442
|
CB_LOG_DEBUG("{} selected bucket: {}", session_->log_prefix_, session_->bucket_name_.value_or(""));
|
431
443
|
session_->bucket_selected_ = true;
|
432
444
|
} else if (resp.status() == key_value_status_code::not_found) {
|
433
|
-
|
434
|
-
"
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
445
|
+
last_error_message_ =
|
446
|
+
fmt::format("kv_engine node does not have configuration propagated yet (opcode={}, status={}, opaque={})",
|
447
|
+
opcode,
|
448
|
+
resp.status(),
|
449
|
+
resp.opaque());
|
450
|
+
CB_LOG_DEBUG("{} {}", session_->log_prefix_, last_error_message_);
|
439
451
|
return complete(errc::network::configuration_not_available);
|
440
452
|
} else if (resp.status() == key_value_status_code::no_access) {
|
441
|
-
|
442
|
-
|
443
|
-
|
453
|
+
last_error_message_ = fmt::format("unable to select bucket: {}, probably the bucket does not exist",
|
454
|
+
session_->bucket_name_.value_or(""));
|
455
|
+
CB_LOG_DEBUG("{} {}", session_->log_prefix_, last_error_message_);
|
444
456
|
session_->bucket_selected_ = false;
|
445
457
|
return complete(errc::common::bucket_not_found);
|
446
458
|
} else {
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
459
|
+
last_error_message_ = fmt::format("unexpected message status during bootstrap: {} (opaque={}, {:n})",
|
460
|
+
resp.error_message(),
|
461
|
+
resp.opaque(),
|
462
|
+
spdlog::to_hex(resp.header()));
|
463
|
+
CB_LOG_WARNING("{} {}", session_->log_prefix_, last_error_message_);
|
452
464
|
return complete(errc::common::bucket_not_found);
|
453
465
|
}
|
454
466
|
} break;
|
@@ -470,12 +482,12 @@ class mcbp_session_impl
|
|
470
482
|
session_->update_configuration(resp.body().config());
|
471
483
|
complete({});
|
472
484
|
} else if (resp.status() == key_value_status_code::not_found) {
|
473
|
-
|
474
|
-
"
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
485
|
+
last_error_message_ =
|
486
|
+
fmt::format("kv_engine node does not have configuration propagated yet (opcode={}, status={}, opaque={})",
|
487
|
+
opcode,
|
488
|
+
resp.status(),
|
489
|
+
resp.opaque());
|
490
|
+
CB_LOG_DEBUG("{} {}", session_->log_prefix_, last_error_message_);
|
479
491
|
return complete(errc::network::configuration_not_available);
|
480
492
|
} else if (resp.status() == key_value_status_code::no_bucket && !session_->bucket_name_) {
|
481
493
|
// bucket-less session, but the server wants bucket
|
@@ -486,16 +498,17 @@ class mcbp_session_impl
|
|
486
498
|
session_->connection_endpoints_.remote_address, session_->connection_endpoints_.remote.port(), 0));
|
487
499
|
complete({});
|
488
500
|
} else {
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
501
|
+
last_error_message_ = fmt::format("unexpected message status during bootstrap: {} (opaque={}, {:n})",
|
502
|
+
resp.error_message(),
|
503
|
+
resp.opaque(),
|
504
|
+
spdlog::to_hex(resp.header()));
|
505
|
+
CB_LOG_WARNING("{} {}", session_->log_prefix_, last_error_message_);
|
494
506
|
return complete(errc::network::protocol_error);
|
495
507
|
}
|
496
508
|
} break;
|
497
509
|
default:
|
498
|
-
|
510
|
+
last_error_message_ = fmt::format("unexpected message during bootstrap: {}", opcode);
|
511
|
+
CB_LOG_WARNING("{} {}", session_->log_prefix_, last_error_message_);
|
499
512
|
return complete(errc::network::protocol_error);
|
500
513
|
}
|
501
514
|
break;
|
@@ -796,6 +809,20 @@ class mcbp_session_impl
|
|
796
809
|
|
797
810
|
void ping(std::shared_ptr<diag::ping_reporter> handler, std::optional<std::chrono::milliseconds> timeout)
|
798
811
|
{
|
812
|
+
if (!bootstrapped_) {
|
813
|
+
handler->report({
|
814
|
+
service_type::key_value,
|
815
|
+
id_,
|
816
|
+
std::chrono::microseconds(0),
|
817
|
+
remote_address(),
|
818
|
+
local_address(),
|
819
|
+
diag::ping_state::error,
|
820
|
+
bucket_name_,
|
821
|
+
last_bootstrap_error_message_.has_value() ? last_bootstrap_error_message_.value()
|
822
|
+
: "Bootstrap incomplete, cannot perform ping.",
|
823
|
+
});
|
824
|
+
return;
|
825
|
+
}
|
799
826
|
protocol::client_request<protocol::mcbp_noop_request_body> req;
|
800
827
|
req.opaque(next_opaque());
|
801
828
|
write_and_subscribe(req.opaque(),
|
@@ -871,6 +898,9 @@ class mcbp_session_impl
|
|
871
898
|
return;
|
872
899
|
}
|
873
900
|
bootstrapped_ = false;
|
901
|
+
if (bootstrap_handler_) {
|
902
|
+
last_bootstrap_error_message_ = std::move(bootstrap_handler_)->last_error_message();
|
903
|
+
}
|
874
904
|
bootstrap_handler_ = nullptr;
|
875
905
|
state_ = diag::endpoint_state::connecting;
|
876
906
|
if (stream_->is_open()) {
|
@@ -920,6 +950,11 @@ class mcbp_session_impl
|
|
920
950
|
return stopped_;
|
921
951
|
}
|
922
952
|
|
953
|
+
[[nodiscard]] bool is_bootstrapped() const
|
954
|
+
{
|
955
|
+
return bootstrapped_;
|
956
|
+
}
|
957
|
+
|
923
958
|
void on_stop(utils::movable_function<void()> handler)
|
924
959
|
{
|
925
960
|
on_stop_handler_ = std::move(handler);
|
@@ -1639,6 +1674,7 @@ class mcbp_session_impl
|
|
1639
1674
|
std::optional<std::string> bucket_name_;
|
1640
1675
|
mcbp_parser parser_;
|
1641
1676
|
std::shared_ptr<bootstrap_handler> bootstrap_handler_{ nullptr };
|
1677
|
+
std::optional<std::string> last_bootstrap_error_message_;
|
1642
1678
|
std::shared_ptr<message_handler> handler_{ nullptr };
|
1643
1679
|
utils::movable_function<void(std::error_code, const topology::configuration&)> bootstrap_callback_{};
|
1644
1680
|
std::mutex command_handlers_mutex_{};
|
@@ -1739,6 +1775,12 @@ mcbp_session::is_stopped() const
|
|
1739
1775
|
return impl_->is_stopped();
|
1740
1776
|
}
|
1741
1777
|
|
1778
|
+
bool
|
1779
|
+
mcbp_session::is_bootstrapped() const
|
1780
|
+
{
|
1781
|
+
return impl_->is_bootstrapped();
|
1782
|
+
}
|
1783
|
+
|
1742
1784
|
std::uint32_t
|
1743
1785
|
mcbp_session::next_opaque()
|
1744
1786
|
{
|
@@ -97,6 +97,7 @@ class mcbp_session
|
|
97
97
|
[[nodiscard]] const std::string& log_prefix() const;
|
98
98
|
[[nodiscard]] bool cancel(std::uint32_t opaque, std::error_code ec, retry_reason reason);
|
99
99
|
[[nodiscard]] bool is_stopped() const;
|
100
|
+
[[nodiscard]] bool is_bootstrapped() const;
|
100
101
|
[[nodiscard]] std::uint32_t next_opaque();
|
101
102
|
[[nodiscard]] std::optional<std::uint32_t> get_collection_uid(const std::string& collection_path);
|
102
103
|
[[nodiscard]] mcbp_context context() const;
|
@@ -126,3 +126,8 @@
|
|
126
126
|
* Transaction's transaction_operation_failed has a public getter for its final_error
|
127
127
|
*/
|
128
128
|
#define COUCHBASE_CXX_CLIENT_TRANSACTIONS_CAN_FETCH_TO_RAISE 1
|
129
|
+
|
130
|
+
/**
|
131
|
+
* Hooks in the transactions core are asynchronous (they have a callback parameter)
|
132
|
+
*/
|
133
|
+
#define COUCHBASE_CXX_CLIENT_TRANSACTIONS_CORE_ASYNC_HOOKS
|
@@ -65,123 +65,134 @@ struct lookup_in_all_replicas_request {
|
|
65
65
|
template<typename Core, typename Handler>
|
66
66
|
void execute(Core core, Handler handler)
|
67
67
|
{
|
68
|
-
core->
|
68
|
+
core->open_bucket(
|
69
69
|
id.bucket(),
|
70
70
|
[core, id = id, timeout = timeout, specs = specs, parent_span = parent_span, h = std::forward<Handler>(handler)](
|
71
|
-
std::error_code ec
|
72
|
-
if (!config.capabilities.supports_subdoc_read_replica()) {
|
73
|
-
ec = errc::common::feature_not_available;
|
74
|
-
}
|
75
|
-
|
71
|
+
std::error_code ec) mutable {
|
76
72
|
if (ec) {
|
77
73
|
std::optional<std::string> first_error_path{};
|
78
74
|
std::optional<std::size_t> first_error_index{};
|
79
75
|
return h(response_type{
|
80
76
|
make_subdocument_error_context(make_key_value_error_context(ec, id), ec, first_error_path, first_error_index, false) });
|
81
77
|
}
|
82
|
-
|
78
|
+
core->with_bucket_configuration(
|
79
|
+
id.bucket(),
|
80
|
+
[core, id = id, timeout = timeout, specs = specs, parent_span = parent_span, h = std::forward<Handler>(h)](
|
81
|
+
std::error_code ec, const topology::configuration& config) mutable {
|
82
|
+
if (!config.capabilities.supports_subdoc_read_replica()) {
|
83
|
+
ec = errc::common::feature_not_available;
|
84
|
+
}
|
83
85
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
86
|
+
if (ec) {
|
87
|
+
std::optional<std::string> first_error_path{};
|
88
|
+
std::optional<std::size_t> first_error_index{};
|
89
|
+
return h(response_type{ make_subdocument_error_context(
|
90
|
+
make_key_value_error_context(ec, id), ec, first_error_path, first_error_index, false) });
|
91
|
+
}
|
92
|
+
using handler_type = utils::movable_function<void(response_type)>;
|
90
93
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
auto ctx = std::make_shared<replica_context>(std::move(h), config.num_replicas.value_or(0U) + 1U);
|
94
|
+
struct replica_context {
|
95
|
+
replica_context(handler_type handler, std::uint32_t expected_responses)
|
96
|
+
: handler_(std::move(handler))
|
97
|
+
, expected_responses_(expected_responses)
|
98
|
+
{
|
99
|
+
}
|
98
100
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
101
|
+
handler_type handler_;
|
102
|
+
std::uint32_t expected_responses_;
|
103
|
+
bool done_{ false };
|
104
|
+
std::mutex mutex_{};
|
105
|
+
std::vector<lookup_in_all_replicas_response::entry> result_{};
|
106
|
+
};
|
107
|
+
auto ctx = std::make_shared<replica_context>(std::move(h), config.num_replicas.value_or(0U) + 1U);
|
108
|
+
|
109
|
+
for (std::size_t idx = 1U; idx <= config.num_replicas.value_or(0U); ++idx) {
|
110
|
+
document_id replica_id{ id };
|
111
|
+
replica_id.node_index(idx);
|
112
|
+
core->execute(impl::lookup_in_replica_request{ std::move(replica_id), specs, timeout, parent_span },
|
113
|
+
[ctx](impl::lookup_in_replica_response&& resp) {
|
114
|
+
handler_type local_handler{};
|
115
|
+
{
|
116
|
+
std::scoped_lock lock(ctx->mutex_);
|
117
|
+
if (ctx->done_) {
|
118
|
+
return;
|
119
|
+
}
|
120
|
+
--ctx->expected_responses_;
|
121
|
+
if (resp.ctx.ec()) {
|
122
|
+
if (ctx->expected_responses_ > 0) {
|
123
|
+
// just ignore the response
|
124
|
+
return;
|
125
|
+
}
|
126
|
+
} else {
|
127
|
+
lookup_in_all_replicas_response::entry top_entry{};
|
128
|
+
top_entry.cas = resp.cas;
|
129
|
+
top_entry.deleted = resp.deleted;
|
130
|
+
top_entry.is_replica = true;
|
131
|
+
for (auto& field : resp.fields) {
|
132
|
+
lookup_in_all_replicas_response::entry::lookup_in_entry lookup_in_entry{};
|
133
|
+
lookup_in_entry.path = field.path;
|
134
|
+
lookup_in_entry.value = field.value;
|
135
|
+
lookup_in_entry.status = field.status;
|
136
|
+
lookup_in_entry.ec = field.ec;
|
137
|
+
lookup_in_entry.exists = field.exists;
|
138
|
+
lookup_in_entry.original_index = field.original_index;
|
139
|
+
lookup_in_entry.opcode = field.opcode;
|
140
|
+
top_entry.fields.emplace_back(lookup_in_entry);
|
141
|
+
}
|
142
|
+
ctx->result_.emplace_back(lookup_in_all_replicas_response::entry{ top_entry });
|
143
|
+
}
|
144
|
+
if (ctx->expected_responses_ == 0) {
|
145
|
+
ctx->done_ = true;
|
146
|
+
std::swap(local_handler, ctx->handler_);
|
147
|
+
}
|
148
|
+
}
|
149
|
+
if (local_handler) {
|
150
|
+
return local_handler({ std::move(resp.ctx), std::move(ctx->result_) });
|
151
|
+
}
|
152
|
+
});
|
153
|
+
}
|
144
154
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
155
|
+
core->execute(lookup_in_request{ document_id{ id }, {}, {}, false, specs, timeout }, [ctx](lookup_in_response&& resp) {
|
156
|
+
handler_type local_handler{};
|
157
|
+
{
|
158
|
+
std::scoped_lock lock(ctx->mutex_);
|
159
|
+
if (ctx->done_) {
|
160
|
+
return;
|
161
|
+
}
|
162
|
+
--ctx->expected_responses_;
|
163
|
+
if (resp.ctx.ec()) {
|
164
|
+
if (ctx->expected_responses_ > 0) {
|
165
|
+
// just ignore the response
|
166
|
+
return;
|
167
|
+
}
|
168
|
+
} else {
|
169
|
+
lookup_in_all_replicas_response::entry top_entry{};
|
170
|
+
top_entry.cas = resp.cas;
|
171
|
+
top_entry.deleted = resp.deleted;
|
172
|
+
top_entry.is_replica = false;
|
173
|
+
for (auto& field : resp.fields) {
|
174
|
+
lookup_in_all_replicas_response::entry::lookup_in_entry lookup_in_entry{};
|
175
|
+
lookup_in_entry.path = field.path;
|
176
|
+
lookup_in_entry.value = field.value;
|
177
|
+
lookup_in_entry.status = field.status;
|
178
|
+
lookup_in_entry.ec = field.ec;
|
179
|
+
lookup_in_entry.exists = field.exists;
|
180
|
+
lookup_in_entry.original_index = field.original_index;
|
181
|
+
lookup_in_entry.opcode = field.opcode;
|
182
|
+
top_entry.fields.emplace_back(lookup_in_entry);
|
183
|
+
}
|
184
|
+
ctx->result_.emplace_back(lookup_in_all_replicas_response::entry{ top_entry });
|
185
|
+
}
|
186
|
+
if (ctx->expected_responses_ == 0) {
|
187
|
+
ctx->done_ = true;
|
188
|
+
std::swap(local_handler, ctx->handler_);
|
189
|
+
}
|
190
|
+
}
|
191
|
+
if (local_handler) {
|
192
|
+
return local_handler({ std::move(resp.ctx), std::move(ctx->result_) });
|
193
|
+
}
|
194
|
+
});
|
195
|
+
});
|
185
196
|
});
|
186
197
|
}
|
187
198
|
};
|