couchbase 4.2.11 → 4.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/deps/couchbase-cxx-cache/mozilla-ca-bundle.crt +49 -2
  2. package/deps/couchbase-cxx-cache/mozilla-ca-bundle.sha256 +1 -1
  3. package/deps/couchbase-cxx-client/core/impl/cluster.cxx +51 -5
  4. package/deps/couchbase-cxx-client/core/impl/collection.cxx +224 -209
  5. package/deps/couchbase-cxx-client/core/impl/query_error_context.cxx +2 -2
  6. package/deps/couchbase-cxx-client/core/impl/query_index_manager.cxx +1 -0
  7. package/deps/couchbase-cxx-client/core/io/dns_client.cxx +4 -0
  8. package/deps/couchbase-cxx-client/core/io/dns_config.cxx +15 -4
  9. package/deps/couchbase-cxx-client/core/io/dns_config.hxx +1 -1
  10. package/deps/couchbase-cxx-client/core/io/mcbp_session.cxx +84 -53
  11. package/deps/couchbase-cxx-client/core/mcbp/operation_queue.cxx +1 -0
  12. package/deps/couchbase-cxx-client/core/meta/features.hxx +5 -0
  13. package/deps/couchbase-cxx-client/core/operations/document_lookup_in_all_replicas.hxx +116 -105
  14. package/deps/couchbase-cxx-client/core/operations/document_lookup_in_any_replica.hxx +116 -108
  15. package/deps/couchbase-cxx-client/core/operations/document_search.cxx +97 -81
  16. package/deps/couchbase-cxx-client/core/operations/document_search.hxx +5 -0
  17. package/deps/couchbase-cxx-client/core/range_scan_orchestrator_options.hxx +2 -1
  18. package/deps/couchbase-cxx-client/core/transactions/atr_cleanup_entry.cxx +16 -7
  19. package/deps/couchbase-cxx-client/core/transactions/attempt_context_impl.cxx +578 -483
  20. package/deps/couchbase-cxx-client/core/transactions/attempt_context_testing_hooks.cxx +51 -50
  21. package/deps/couchbase-cxx-client/core/transactions/attempt_context_testing_hooks.hxx +4 -2
  22. package/deps/couchbase-cxx-client/core/transactions/cleanup_testing_hooks.cxx +6 -6
  23. package/deps/couchbase-cxx-client/core/transactions/cleanup_testing_hooks.hxx +3 -2
  24. package/deps/couchbase-cxx-client/core/transactions/internal/transactions_cleanup.hxx +2 -0
  25. package/deps/couchbase-cxx-client/core/transactions/internal/utils.hxx +5 -1
  26. package/deps/couchbase-cxx-client/core/transactions/staged_mutation.cxx +222 -179
  27. package/deps/couchbase-cxx-client/core/transactions/staged_mutation.hxx +23 -12
  28. package/deps/couchbase-cxx-client/core/transactions/transactions.cxx +61 -24
  29. package/deps/couchbase-cxx-client/core/transactions/transactions_cleanup.cxx +36 -16
  30. package/deps/couchbase-cxx-client/core/transactions/utils.cxx +9 -0
  31. package/deps/couchbase-cxx-client/core/transactions.hxx +40 -7
  32. package/deps/couchbase-cxx-client/couchbase/cluster.hxx +19 -0
  33. package/deps/couchbase-cxx-client/couchbase/fork_event.hxx +39 -0
  34. package/dist/binding.d.ts +8 -0
  35. package/dist/bindingutilities.d.ts +6 -1
  36. package/dist/bindingutilities.js +15 -1
  37. package/dist/bucketmanager.d.ts +0 -12
  38. package/dist/cluster.d.ts +0 -2
  39. package/dist/cluster.js +0 -2
  40. package/dist/collection.d.ts +3 -3
  41. package/dist/collection.js +3 -1
  42. package/dist/querytypes.d.ts +0 -2
  43. package/dist/rangeScan.d.ts +0 -8
  44. package/dist/rangeScan.js +0 -8
  45. package/dist/scope.d.ts +0 -5
  46. package/dist/scope.js +0 -5
  47. package/dist/scopesearchindexmanager.d.ts +0 -2
  48. package/dist/scopesearchindexmanager.js +0 -2
  49. package/dist/searchexecutor.js +3 -1
  50. package/dist/searchtypes.d.ts +16 -6
  51. package/dist/searchtypes.js +2 -6
  52. package/dist/transactions.d.ts +23 -0
  53. package/dist/transactions.js +16 -10
  54. package/dist/vectorsearch.d.ts +8 -8
  55. package/dist/vectorsearch.js +7 -7
  56. package/package.json +7 -7
  57. package/src/instance.cpp +11 -1
  58. package/src/instance.hpp +1 -0
  59. package/src/jstocbpp_autogen.hpp +8 -0
  60. package/src/jstocbpp_transactions.hpp +40 -3
  61. package/src/transactions.cpp +12 -1
  62. package/tools/gen-bindings-json.py +0 -1
@@ -1,7 +1,7 @@
1
1
  ##
2
2
  ## Bundle of CA Root Certificates
3
3
  ##
4
- ## Certificate data from Mozilla as of: Tue Dec 12 04:12:04 2023 GMT
4
+ ## Certificate data from Mozilla as of: Mon Mar 11 15:25:27 2024 GMT
5
5
  ##
6
6
  ## This is a bundle of X.509 certificates of public Certificate Authorities
7
7
  ## (CA). These were automatically extracted from Mozilla's root certificates
@@ -14,7 +14,7 @@
14
14
  ## Just configure this file as the SSLCACertificateFile.
15
15
  ##
16
16
  ## Conversion done with mk-ca-bundle.pl version 1.29.
17
- ## SHA256: 1970dd65858925d68498d2356aea6d03f764422523c5887deca8ce3ba9e1f845
17
+ ## SHA256: 4d96bd539f4719e9ace493757afbe4a23ee8579de1c97fbebc50bba3c12e8c1e
18
18
  ##
19
19
 
20
20
 
@@ -3532,3 +3532,50 @@ dVwPaFsdZcJfMw8eD/A7hvWwTruc9+olBdytoptLFwG+Qt81IR2tq670v64fG9PiO/yzcnMcmyiQ
3532
3532
  iRM9HcEARwmWmjgb3bHPDcK0RPOWlc4yOo80nOAXx17Org3bhzjlP1v9mxnhMUF6cKojawHhRUzN
3533
3533
  lM47ni3niAIi9G7oyOzWPPO5std3eqx7
3534
3534
  -----END CERTIFICATE-----
3535
+
3536
+ Telekom Security TLS ECC Root 2020
3537
+ ==================================
3538
+ -----BEGIN CERTIFICATE-----
3539
+ MIICQjCCAcmgAwIBAgIQNjqWjMlcsljN0AFdxeVXADAKBggqhkjOPQQDAzBjMQswCQYDVQQGEwJE
3540
+ RTEnMCUGA1UECgweRGV1dHNjaGUgVGVsZWtvbSBTZWN1cml0eSBHbWJIMSswKQYDVQQDDCJUZWxl
3541
+ a29tIFNlY3VyaXR5IFRMUyBFQ0MgUm9vdCAyMDIwMB4XDTIwMDgyNTA3NDgyMFoXDTQ1MDgyNTIz
3542
+ NTk1OVowYzELMAkGA1UEBhMCREUxJzAlBgNVBAoMHkRldXRzY2hlIFRlbGVrb20gU2VjdXJpdHkg
3543
+ R21iSDErMCkGA1UEAwwiVGVsZWtvbSBTZWN1cml0eSBUTFMgRUNDIFJvb3QgMjAyMDB2MBAGByqG
3544
+ SM49AgEGBSuBBAAiA2IABM6//leov9Wq9xCazbzREaK9Z0LMkOsVGJDZos0MKiXrPk/OtdKPD/M1
3545
+ 2kOLAoC+b1EkHQ9rK8qfwm9QMuU3ILYg/4gND21Ju9sGpIeQkpT0CdDPf8iAC8GXs7s1J8nCG6NC
3546
+ MEAwHQYDVR0OBBYEFONyzG6VmUex5rNhTNHLq+O6zd6fMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P
3547
+ AQH/BAQDAgEGMAoGCCqGSM49BAMDA2cAMGQCMHVSi7ekEE+uShCLsoRbQuHmKjYC2qBuGT8lv9pZ
3548
+ Mo7k+5Dck2TOrbRBR2Diz6fLHgIwN0GMZt9Ba9aDAEH9L1r3ULRn0SyocddDypwnJJGDSA3PzfdU
3549
+ ga/sf+Rn27iQ7t0l
3550
+ -----END CERTIFICATE-----
3551
+
3552
+ Telekom Security TLS RSA Root 2023
3553
+ ==================================
3554
+ -----BEGIN CERTIFICATE-----
3555
+ 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
3581
+ -----END CERTIFICATE-----
@@ -1 +1 @@
1
- ccbdfc2fe1a0d7bbbb9cc15710271acf1bb1afe4c8f1725fe95c4c7733fcbe5a cacert.pem
1
+ 1794c1d4f7055b7d02c2170337b61b48a2ef6c90d77e95444fd2596f4cac609f cacert.pem
@@ -157,10 +157,30 @@ class cluster_impl : public std::enable_shared_from_this<cluster_impl>
157
157
  public:
158
158
  explicit cluster_impl(couchbase::core::cluster core)
159
159
  : core_{ std::move(core) }
160
- , transactions_{ std::make_shared<couchbase::core::transactions::transactions>(core_, core_.origin().second.options().transactions) }
161
160
  {
162
161
  }
163
162
 
163
+ explicit cluster_impl(couchbase::core::cluster core, std::shared_ptr<couchbase::core::transactions::transactions> transactions)
164
+ : core_{ std::move(core) }
165
+ , transactions_{ transactions }
166
+ {
167
+ }
168
+
169
+ void initialize_transactions(std::function<void(std::error_code)>&& handler)
170
+ {
171
+ return core::transactions::transactions::create(
172
+ core_,
173
+ core_.origin().second.options().transactions,
174
+ [self = shared_from_this(), handler = std::move(handler)](auto ec, auto txns) mutable {
175
+ if (ec) {
176
+ return handler(ec);
177
+ }
178
+
179
+ self->transactions_ = txns;
180
+ handler({});
181
+ });
182
+ }
183
+
164
184
  void query(std::string statement, query_options::built options, query_handler&& handler) const
165
185
  {
166
186
  return core_.execute(
@@ -214,6 +234,13 @@ class cluster_impl : public std::enable_shared_from_this<cluster_impl>
214
234
  });
215
235
  }
216
236
 
237
+ void notify_fork(fork_event event)
238
+ {
239
+ if (transactions_) {
240
+ transactions_->notify_fork(event);
241
+ }
242
+ }
243
+
217
244
  void close(core::utils::movable_function<void()> handler)
218
245
  {
219
246
  if (transactions_) {
@@ -258,6 +285,11 @@ cluster::cluster(core::cluster core)
258
285
  {
259
286
  }
260
287
 
288
+ cluster::cluster(core::cluster core, std::shared_ptr<core::transactions::transactions> transactions)
289
+ : impl_{ std::make_shared<cluster_impl>(std::move(core), transactions) }
290
+ {
291
+ }
292
+
261
293
  void
262
294
  cluster::query(std::string statement, const query_options& options, query_handler&& handler) const
263
295
  {
@@ -361,9 +393,8 @@ cluster::connect(asio::io_context& io, const std::string& connection_string, con
361
393
  -> std::future<std::pair<cluster, std::error_code>>
362
394
  {
363
395
  auto barrier = std::make_shared<std::promise<std::pair<cluster, std::error_code>>>();
364
- auto future = barrier->get_future();
365
- connect(io, connection_string, options, [barrier](auto c, auto ec) { barrier->set_value({ std::move(c), ec }); });
366
- return future;
396
+ connect(io, connection_string, options, [barrier](auto c, auto ec) mutable { barrier->set_value({ std::move(c), ec }); });
397
+ return barrier->get_future();
367
398
  }
368
399
 
369
400
  void
@@ -378,10 +409,25 @@ cluster::connect(asio::io_context& io,
378
409
  if (ec) {
379
410
  return handler({}, ec);
380
411
  }
381
- handler(couchbase::cluster(std::move(core)), {});
412
+ auto cluster = couchbase::cluster(std::move(core));
413
+ return cluster.impl_->initialize_transactions([cluster, handler = std::move(handler)](std::error_code ec) mutable {
414
+ if (ec) {
415
+ return cluster.impl_->close([ec, handler = std::move(handler)]() mutable { return handler({}, ec); });
416
+ }
417
+ return handler(cluster, ec);
418
+ });
382
419
  });
383
420
  }
384
421
 
422
+ auto
423
+ cluster::notify_fork(fork_event event) -> void
424
+ {
425
+ if (!impl_) {
426
+ return;
427
+ }
428
+ return impl_->notify_fork(event);
429
+ }
430
+
385
431
  auto
386
432
  cluster::close() const -> void
387
433
  {
@@ -475,120 +475,129 @@ class collection_impl : public std::enable_shared_from_this<collection_impl>
475
475
  {
476
476
  auto request = std::make_shared<couchbase::core::impl::lookup_in_all_replicas_request>(
477
477
  bucket_name_, scope_name_, name_, std::move(document_key), specs, options.timeout);
478
- core_.with_bucket_configuration(
478
+ core_.open_bucket(
479
479
  bucket_name_,
480
- [core = core_, r = std::move(request), h = std::move(handler)](std::error_code ec,
481
- const core::topology::configuration& config) mutable {
482
- if (!config.capabilities.supports_subdoc_read_replica()) {
483
- ec = errc::common::feature_not_available;
484
- }
485
-
480
+ [core = core_, bucket_name = bucket_name_, r = std::move(request), h = std::move(handler)](std::error_code ec) mutable {
486
481
  if (ec) {
487
- return h(core::make_subdocument_error_context(make_key_value_error_context(ec, r->id()), ec, {}, {}, false),
488
- lookup_in_all_replicas_result{});
482
+ h(core::make_subdocument_error_context(make_key_value_error_context(ec, r->id()), ec, {}, {}, false),
483
+ lookup_in_all_replicas_result{});
484
+ return;
489
485
  }
490
- struct replica_context {
491
- replica_context(core::impl::movable_lookup_in_all_replicas_handler handler, std::uint32_t expected_responses)
492
- : handler_(std::move(handler))
493
- , expected_responses_(expected_responses)
494
- {
495
- }
496
486
 
497
- core::impl::movable_lookup_in_all_replicas_handler handler_;
498
- std::uint32_t expected_responses_;
499
- bool done_{ false };
500
- std::mutex mutex_{};
501
- lookup_in_all_replicas_result result_{};
502
- };
503
- auto ctx = std::make_shared<replica_context>(std::move(h), config.num_replicas.value_or(0U) + 1U);
487
+ return core.with_bucket_configuration(
488
+ bucket_name,
489
+ [core = core, r = std::move(r), h = std::move(h)](std::error_code ec, const core::topology::configuration& config) mutable {
490
+ if (!config.capabilities.supports_subdoc_read_replica()) {
491
+ ec = errc::common::feature_not_available;
492
+ }
504
493
 
505
- for (std::size_t idx = 1U; idx <= config.num_replicas.value_or(0U); ++idx) {
506
- core::document_id replica_id{ r->id() };
507
- replica_id.node_index(idx);
508
- core.execute(core::impl::lookup_in_replica_request{ std::move(replica_id), r->specs(), r->timeout() },
509
- [ctx](core::impl::lookup_in_replica_response&& resp) {
510
- core::impl::movable_lookup_in_all_replicas_handler local_handler{};
511
- {
512
- const std::scoped_lock lock(ctx->mutex_);
513
- if (ctx->done_) {
514
- return;
515
- }
516
- --ctx->expected_responses_;
517
- if (resp.ctx.ec()) {
518
- if (ctx->expected_responses_ > 0) {
519
- // just ignore the response
520
- return;
521
- }
522
- } else {
523
- std::vector<lookup_in_replica_result::entry> entries{};
524
- for (const auto& field : resp.fields) {
525
- lookup_in_replica_result::entry lookup_in_entry{};
526
- lookup_in_entry.path = field.path;
527
- lookup_in_entry.value = field.value;
528
- lookup_in_entry.exists = field.exists;
529
- lookup_in_entry.original_index = field.original_index;
530
- lookup_in_entry.ec = field.ec;
531
- entries.emplace_back(lookup_in_entry);
532
- }
533
- ctx->result_.emplace_back(resp.cas, entries, resp.deleted, true /* replica */);
534
- }
535
- if (ctx->expected_responses_ == 0) {
536
- ctx->done_ = true;
537
- std::swap(local_handler, ctx->handler_);
538
- }
539
- }
540
- if (local_handler) {
541
- if (!ctx->result_.empty()) {
542
- resp.ctx.override_ec({});
543
- }
544
- return local_handler(std::move(resp.ctx), std::move(ctx->result_));
545
- }
546
- });
547
- }
494
+ if (ec) {
495
+ return h(core::make_subdocument_error_context(make_key_value_error_context(ec, r->id()), ec, {}, {}, false),
496
+ lookup_in_all_replicas_result{});
497
+ }
498
+ struct replica_context {
499
+ replica_context(core::impl::movable_lookup_in_all_replicas_handler handler, std::uint32_t expected_responses)
500
+ : handler_(std::move(handler))
501
+ , expected_responses_(expected_responses)
502
+ {
503
+ }
504
+
505
+ core::impl::movable_lookup_in_all_replicas_handler handler_;
506
+ std::uint32_t expected_responses_;
507
+ bool done_{ false };
508
+ std::mutex mutex_{};
509
+ lookup_in_all_replicas_result result_{};
510
+ };
511
+ auto ctx = std::make_shared<replica_context>(std::move(h), config.num_replicas.value_or(0U) + 1U);
512
+
513
+ for (std::size_t idx = 1U; idx <= config.num_replicas.value_or(0U); ++idx) {
514
+ core::document_id replica_id{ r->id() };
515
+ replica_id.node_index(idx);
516
+ core.execute(core::impl::lookup_in_replica_request{ std::move(replica_id), r->specs(), r->timeout() },
517
+ [ctx](core::impl::lookup_in_replica_response&& resp) {
518
+ core::impl::movable_lookup_in_all_replicas_handler local_handler{};
519
+ {
520
+ const std::scoped_lock lock(ctx->mutex_);
521
+ if (ctx->done_) {
522
+ return;
523
+ }
524
+ --ctx->expected_responses_;
525
+ if (resp.ctx.ec()) {
526
+ if (ctx->expected_responses_ > 0) {
527
+ // just ignore the response
528
+ return;
529
+ }
530
+ } else {
531
+ std::vector<lookup_in_replica_result::entry> entries{};
532
+ for (const auto& field : resp.fields) {
533
+ lookup_in_replica_result::entry lookup_in_entry{};
534
+ lookup_in_entry.path = field.path;
535
+ lookup_in_entry.value = field.value;
536
+ lookup_in_entry.exists = field.exists;
537
+ lookup_in_entry.original_index = field.original_index;
538
+ lookup_in_entry.ec = field.ec;
539
+ entries.emplace_back(lookup_in_entry);
540
+ }
541
+ ctx->result_.emplace_back(resp.cas, entries, resp.deleted, true /* replica */);
542
+ }
543
+ if (ctx->expected_responses_ == 0) {
544
+ ctx->done_ = true;
545
+ std::swap(local_handler, ctx->handler_);
546
+ }
547
+ }
548
+ if (local_handler) {
549
+ if (!ctx->result_.empty()) {
550
+ resp.ctx.override_ec({});
551
+ }
552
+ return local_handler(std::move(resp.ctx), std::move(ctx->result_));
553
+ }
554
+ });
555
+ }
548
556
 
549
- core::operations::lookup_in_request active{ core::document_id{ r->id() } };
550
- active.specs = r->specs();
551
- active.timeout = r->timeout();
552
- core.execute(active, [ctx](core::operations::lookup_in_response&& resp) {
553
- core::impl::movable_lookup_in_all_replicas_handler local_handler{};
554
- {
555
- const std::scoped_lock lock(ctx->mutex_);
556
- if (ctx->done_) {
557
- return;
558
- }
559
- --ctx->expected_responses_;
560
- if (resp.ctx.ec()) {
561
- if (ctx->expected_responses_ > 0) {
562
- // just ignore the response
563
- return;
564
- }
565
- } else {
566
- std::vector<lookup_in_replica_result::entry> entries{};
567
- for (const auto& field : resp.fields) {
568
- lookup_in_replica_result::entry lookup_in_entry{};
569
- lookup_in_entry.path = field.path;
570
- lookup_in_entry.value = field.value;
571
- lookup_in_entry.exists = field.exists;
572
- lookup_in_entry.original_index = field.original_index;
573
- lookup_in_entry.ec = field.ec;
574
- entries.emplace_back(lookup_in_entry);
575
- }
576
- ctx->result_.emplace_back(resp.cas, entries, resp.deleted, false /* active */);
577
- }
578
- if (ctx->expected_responses_ == 0) {
579
- ctx->done_ = true;
580
- std::swap(local_handler, ctx->handler_);
581
- }
582
- }
583
- if (local_handler) {
584
- if (!ctx->result_.empty()) {
585
- resp.ctx.override_ec({});
586
- }
587
- return local_handler(std::move(resp.ctx), std::move(ctx->result_));
588
- }
589
- });
557
+ core::operations::lookup_in_request active{ core::document_id{ r->id() } };
558
+ active.specs = r->specs();
559
+ active.timeout = r->timeout();
560
+ core.execute(active, [ctx](core::operations::lookup_in_response&& resp) {
561
+ core::impl::movable_lookup_in_all_replicas_handler local_handler{};
562
+ {
563
+ const std::scoped_lock lock(ctx->mutex_);
564
+ if (ctx->done_) {
565
+ return;
566
+ }
567
+ --ctx->expected_responses_;
568
+ if (resp.ctx.ec()) {
569
+ if (ctx->expected_responses_ > 0) {
570
+ // just ignore the response
571
+ return;
572
+ }
573
+ } else {
574
+ std::vector<lookup_in_replica_result::entry> entries{};
575
+ for (const auto& field : resp.fields) {
576
+ lookup_in_replica_result::entry lookup_in_entry{};
577
+ lookup_in_entry.path = field.path;
578
+ lookup_in_entry.value = field.value;
579
+ lookup_in_entry.exists = field.exists;
580
+ lookup_in_entry.original_index = field.original_index;
581
+ lookup_in_entry.ec = field.ec;
582
+ entries.emplace_back(lookup_in_entry);
583
+ }
584
+ ctx->result_.emplace_back(resp.cas, entries, resp.deleted, false /* active */);
585
+ }
586
+ if (ctx->expected_responses_ == 0) {
587
+ ctx->done_ = true;
588
+ std::swap(local_handler, ctx->handler_);
589
+ }
590
+ }
591
+ if (local_handler) {
592
+ if (!ctx->result_.empty()) {
593
+ resp.ctx.override_ec({});
594
+ }
595
+ return local_handler(std::move(resp.ctx), std::move(ctx->result_));
596
+ }
597
+ });
598
+ });
590
599
  });
591
- }
600
+ };
592
601
 
593
602
  void lookup_in_any_replica(std::string document_key,
594
603
  const std::vector<core::impl::subdoc::command>& specs,
@@ -597,114 +606,120 @@ class collection_impl : public std::enable_shared_from_this<collection_impl>
597
606
  {
598
607
  auto request = std::make_shared<couchbase::core::impl::lookup_in_any_replica_request>(
599
608
  bucket_name_, scope_name_, name_, std::move(document_key), specs, options.timeout);
600
- core_.with_bucket_configuration(
609
+ core_.open_bucket(
601
610
  bucket_name_,
602
- [core = core_, r = std::move(request), h = std::move(handler)](std::error_code ec,
603
- const core::topology::configuration& config) mutable {
604
- if (!config.capabilities.supports_subdoc_read_replica()) {
605
- ec = errc::common::feature_not_available;
606
- }
607
- if (r->specs().size() > 16) {
608
- ec = errc::common::invalid_argument;
609
- }
611
+ [core = core_, bucket_name = bucket_name_, r = std::move(request), h = std::move(handler)](std::error_code ec) mutable {
610
612
  if (ec) {
611
- return h(core::make_subdocument_error_context(make_key_value_error_context(ec, r->id()), ec, {}, {}, false),
612
- lookup_in_replica_result{});
613
+ h(core::make_subdocument_error_context(make_key_value_error_context(ec, r->id()), ec, {}, {}, false),
614
+ lookup_in_replica_result{});
615
+ return;
613
616
  }
614
- struct replica_context {
615
- replica_context(core::impl::movable_lookup_in_any_replica_handler handler, std::uint32_t expected_responses)
616
- : handler_(std::move(handler))
617
- , expected_responses_(expected_responses)
618
- {
619
- }
620
617
 
621
- core::impl::movable_lookup_in_any_replica_handler handler_;
622
- std::uint32_t expected_responses_;
623
- bool done_{ false };
624
- std::mutex mutex_{};
625
- };
626
- auto ctx = std::make_shared<replica_context>(std::move(h), config.num_replicas.value_or(0U) + 1U);
627
-
628
- for (std::size_t idx = 1U; idx <= config.num_replicas.value_or(0U); ++idx) {
629
- core::document_id replica_id{ r->id() };
630
- replica_id.node_index(idx);
631
- core.execute(core::impl::lookup_in_replica_request{ std::move(replica_id), r->specs(), r->timeout() },
632
- [ctx](core::impl::lookup_in_replica_response&& resp) {
633
- core::impl::movable_lookup_in_any_replica_handler local_handler;
634
- {
635
- const std::scoped_lock lock(ctx->mutex_);
636
- if (ctx->done_) {
637
- return;
638
- }
639
- --ctx->expected_responses_;
640
- if (resp.ctx.ec()) {
641
- if (ctx->expected_responses_ > 0) {
642
- // just ignore the response
643
- return;
644
- }
645
- // consider document irretrievable and give up
646
- resp.ctx.override_ec(errc::key_value::document_irretrievable);
647
- }
648
- ctx->done_ = true;
649
- std::swap(local_handler, ctx->handler_);
650
- }
651
- if (local_handler) {
652
- std::vector<lookup_in_replica_result::entry> entries;
653
- for (const auto& field : resp.fields) {
654
- lookup_in_replica_result::entry entry{};
655
- entry.path = field.path;
656
- entry.original_index = field.original_index;
657
- entry.exists = field.exists;
658
- entry.value = field.value;
659
- entry.ec = field.ec;
660
- entries.emplace_back(entry);
661
- }
662
- return local_handler(
663
- std::move(resp.ctx),
664
- lookup_in_replica_result{ resp.cas, entries, resp.deleted, true /* replica */ });
665
- }
666
- });
667
- }
618
+ return core.with_bucket_configuration(
619
+ bucket_name,
620
+ [core = core, r = std::move(r), h = std::move(h)](std::error_code ec, const core::topology::configuration& config) mutable {
621
+ if (!config.capabilities.supports_subdoc_read_replica()) {
622
+ ec = errc::common::feature_not_available;
623
+ }
624
+ if (ec) {
625
+ return h(core::make_subdocument_error_context(make_key_value_error_context(ec, r->id()), ec, {}, {}, false),
626
+ lookup_in_replica_result{});
627
+ }
628
+ struct replica_context {
629
+ replica_context(core::impl::movable_lookup_in_any_replica_handler handler, std::uint32_t expected_responses)
630
+ : handler_(std::move(handler))
631
+ , expected_responses_(expected_responses)
632
+ {
633
+ }
634
+
635
+ core::impl::movable_lookup_in_any_replica_handler handler_;
636
+ std::uint32_t expected_responses_;
637
+ bool done_{ false };
638
+ std::mutex mutex_{};
639
+ };
640
+ auto ctx = std::make_shared<replica_context>(std::move(h), config.num_replicas.value_or(0U) + 1U);
641
+
642
+ for (std::size_t idx = 1U; idx <= config.num_replicas.value_or(0U); ++idx) {
643
+ core::document_id replica_id{ r->id() };
644
+ replica_id.node_index(idx);
645
+ core.execute(core::impl::lookup_in_replica_request{ std::move(replica_id), r->specs(), r->timeout() },
646
+ [ctx](core::impl::lookup_in_replica_response&& resp) {
647
+ core::impl::movable_lookup_in_any_replica_handler local_handler;
648
+ {
649
+ const std::scoped_lock lock(ctx->mutex_);
650
+ if (ctx->done_) {
651
+ return;
652
+ }
653
+ --ctx->expected_responses_;
654
+ if (resp.ctx.ec()) {
655
+ if (ctx->expected_responses_ > 0) {
656
+ // just ignore the response
657
+ return;
658
+ }
659
+ // consider document irretrievable and give up
660
+ resp.ctx.override_ec(errc::key_value::document_irretrievable);
661
+ }
662
+ ctx->done_ = true;
663
+ std::swap(local_handler, ctx->handler_);
664
+ }
665
+ if (local_handler) {
666
+ std::vector<lookup_in_replica_result::entry> entries;
667
+ for (const auto& field : resp.fields) {
668
+ lookup_in_replica_result::entry entry{};
669
+ entry.path = field.path;
670
+ entry.original_index = field.original_index;
671
+ entry.exists = field.exists;
672
+ entry.value = field.value;
673
+ entry.ec = field.ec;
674
+ entries.emplace_back(entry);
675
+ }
676
+ return local_handler(
677
+ std::move(resp.ctx),
678
+ lookup_in_replica_result{ resp.cas, entries, resp.deleted, true /* replica */ });
679
+ }
680
+ });
681
+ }
668
682
 
669
- core::operations::lookup_in_request active{ core::document_id{ r->id() } };
670
- active.specs = r->specs();
671
- active.timeout = r->timeout();
672
- core.execute(active, [ctx](core::operations::lookup_in_response&& resp) {
673
- core::impl::movable_lookup_in_any_replica_handler local_handler{};
674
- {
675
- const std::scoped_lock lock(ctx->mutex_);
676
- if (ctx->done_) {
677
- return;
678
- }
679
- --ctx->expected_responses_;
680
- if (resp.ctx.ec()) {
681
- if (ctx->expected_responses_ > 0) {
682
- // just ignore the response
683
- return;
684
- }
685
- // consider document irretrievable and give up
686
- resp.ctx.override_ec(errc::key_value::document_irretrievable);
687
- }
688
- ctx->done_ = true;
689
- std::swap(local_handler, ctx->handler_);
690
- }
691
- if (local_handler) {
692
- std::vector<lookup_in_replica_result::entry> entries;
693
- for (const auto& field : resp.fields) {
694
- lookup_in_replica_result::entry entry{};
695
- entry.path = field.path;
696
- entry.original_index = field.original_index;
697
- entry.exists = field.exists;
698
- entry.value = field.value;
699
- entry.ec = field.ec;
700
- entries.emplace_back(entry);
701
- }
702
- return local_handler(std::move(resp.ctx),
703
- lookup_in_replica_result{ resp.cas, entries, resp.deleted, false /* active */ });
704
- }
705
- });
683
+ core::operations::lookup_in_request active{ core::document_id{ r->id() } };
684
+ active.specs = r->specs();
685
+ active.timeout = r->timeout();
686
+ core.execute(active, [ctx](core::operations::lookup_in_response&& resp) {
687
+ core::impl::movable_lookup_in_any_replica_handler local_handler{};
688
+ {
689
+ const std::scoped_lock lock(ctx->mutex_);
690
+ if (ctx->done_) {
691
+ return;
692
+ }
693
+ --ctx->expected_responses_;
694
+ if (resp.ctx.ec()) {
695
+ if (ctx->expected_responses_ > 0) {
696
+ // just ignore the response
697
+ return;
698
+ }
699
+ // consider document irretrievable and give up
700
+ resp.ctx.override_ec(errc::key_value::document_irretrievable);
701
+ }
702
+ ctx->done_ = true;
703
+ std::swap(local_handler, ctx->handler_);
704
+ }
705
+ if (local_handler) {
706
+ std::vector<lookup_in_replica_result::entry> entries;
707
+ for (const auto& field : resp.fields) {
708
+ lookup_in_replica_result::entry entry{};
709
+ entry.path = field.path;
710
+ entry.original_index = field.original_index;
711
+ entry.exists = field.exists;
712
+ entry.value = field.value;
713
+ entry.ec = field.ec;
714
+ entries.emplace_back(entry);
715
+ }
716
+ return local_handler(std::move(resp.ctx),
717
+ lookup_in_replica_result{ resp.cas, entries, resp.deleted, false /* active */ });
718
+ }
719
+ });
720
+ });
706
721
  });
707
- }
722
+ };
708
723
 
709
724
  void mutate_in(std::string document_key,
710
725
  const std::vector<core::impl::subdoc::command>& specs,