couchbase 4.5.0 → 4.5.1

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 (24) hide show
  1. package/deps/couchbase-cxx-cache/mozilla-ca-bundle.crt +78 -2
  2. package/deps/couchbase-cxx-cache/mozilla-ca-bundle.sha256 +1 -1
  3. package/deps/couchbase-cxx-client/CMakeLists.txt +3 -3
  4. package/deps/couchbase-cxx-client/README.md +2 -2
  5. package/deps/couchbase-cxx-client/core/app_telemetry_meter.cxx +46 -8
  6. package/deps/couchbase-cxx-client/core/app_telemetry_meter.hxx +4 -2
  7. package/deps/couchbase-cxx-client/core/cluster.cxx +2 -1
  8. package/deps/couchbase-cxx-client/core/cluster_options.hxx +1 -0
  9. package/deps/couchbase-cxx-client/core/impl/cluster.cxx +1 -0
  10. package/deps/couchbase-cxx-client/core/impl/error.cxx +21 -6
  11. package/deps/couchbase-cxx-client/core/impl/error.hxx +1 -1
  12. package/deps/couchbase-cxx-client/core/io/http_session_manager.hxx +4 -1
  13. package/deps/couchbase-cxx-client/core/operations/management/search_index_get_all.cxx +3 -2
  14. package/deps/couchbase-cxx-client/core/origin.cxx +25 -0
  15. package/deps/couchbase-cxx-client/core/origin.hxx +16 -13
  16. package/deps/couchbase-cxx-client/core/transactions/attempt_context_impl.cxx +37 -9
  17. package/deps/couchbase-cxx-client/core/transactions/transaction_get_multi_replicas_from_preferred_server_group_result.hxx +2 -1
  18. package/deps/couchbase-cxx-client/core/transactions/transaction_get_multi_result.hxx +2 -1
  19. package/deps/couchbase-cxx-client/core/utils/connection_string.cxx +3 -0
  20. package/deps/couchbase-cxx-client/core/utils/connection_string.hxx +1 -0
  21. package/deps/couchbase-cxx-client/couchbase/behavior_options.hxx +9 -0
  22. package/deps/couchbase-cxx-client/couchbase/transactions/transaction_get_multi_replicas_from_preferred_server_group_result.hxx +4 -1
  23. package/deps/couchbase-cxx-client/couchbase/transactions/transaction_get_multi_result.hxx +4 -1
  24. package/package.json +8 -8
@@ -1,7 +1,7 @@
1
1
  ##
2
2
  ## Bundle of CA Root Certificates
3
3
  ##
4
- ## Certificate data from Mozilla as of: Tue May 20 03:12:02 2025 GMT
4
+ ## Certificate data from Mozilla as of: Tue Sep 9 03:12:01 2025 GMT
5
5
  ##
6
6
  ## Find updated versions here: https://curl.se/docs/caextract.html
7
7
  ##
@@ -16,7 +16,7 @@
16
16
  ## Just configure this file as the SSLCACertificateFile.
17
17
  ##
18
18
  ## Conversion done with mk-ca-bundle.pl version 1.29.
19
- ## SHA256: 8944ec6b572b577daee4fc681a425881f841ec2660e4cb5f0eee727f84620697
19
+ ## SHA256: 0078e6bdd280fd89e1b883174387aae84b3eae2ee263416a5f8a14ee7f179ae9
20
20
  ##
21
21
 
22
22
 
@@ -3448,6 +3448,51 @@ WoC9EV2Ta/vH5mQ/u2kc6d0li690yVRAysuTEwrt+2aSEcr1wPrYg1UDfNPFIkZ1cGt5SAYqgpq/
3448
3448
  n/mtd+ArY0+ew+43u3gJhJ65bvspmZDogNOfJA==
3449
3449
  -----END CERTIFICATE-----
3450
3450
 
3451
+ TrustAsia TLS ECC Root CA
3452
+ =========================
3453
+ -----BEGIN CERTIFICATE-----
3454
+ MIICMTCCAbegAwIBAgIUNnThTXxlE8msg1UloD5Sfi9QaMcwCgYIKoZIzj0EAwMwWDELMAkGA1UE
3455
+ BhMCQ04xJTAjBgNVBAoTHFRydXN0QXNpYSBUZWNobm9sb2dpZXMsIEluYy4xIjAgBgNVBAMTGVRy
3456
+ dXN0QXNpYSBUTFMgRUNDIFJvb3QgQ0EwHhcNMjQwNTE1MDU0MTU2WhcNNDQwNTE1MDU0MTU1WjBY
3457
+ MQswCQYDVQQGEwJDTjElMCMGA1UEChMcVHJ1c3RBc2lhIFRlY2hub2xvZ2llcywgSW5jLjEiMCAG
3458
+ A1UEAxMZVHJ1c3RBc2lhIFRMUyBFQ0MgUm9vdCBDQTB2MBAGByqGSM49AgEGBSuBBAAiA2IABLh/
3459
+ pVs/AT598IhtrimY4ZtcU5nb9wj/1WrgjstEpvDBjL1P1M7UiFPoXlfXTr4sP/MSpwDpguMqWzJ8
3460
+ S5sUKZ74LYO1644xST0mYekdcouJtgq7nDM1D9rs3qlKH8kzsaNCMEAwDwYDVR0TAQH/BAUwAwEB
3461
+ /zAdBgNVHQ4EFgQULIVTu7FDzTLqnqOH/qKYqKaT6RAwDgYDVR0PAQH/BAQDAgEGMAoGCCqGSM49
3462
+ BAMDA2gAMGUCMFRH18MtYYZI9HlaVQ01L18N9mdsd0AaRuf4aFtOJx24mH1/k78ITcTaRTChD15K
3463
+ eAIxAKORh/IRM4PDwYqROkwrULG9IpRdNYlzg8WbGf60oenUoWa2AaU2+dhoYSi3dOGiMQ==
3464
+ -----END CERTIFICATE-----
3465
+
3466
+ TrustAsia TLS RSA Root CA
3467
+ =========================
3468
+ -----BEGIN CERTIFICATE-----
3469
+ MIIFgDCCA2igAwIBAgIUHBjYz+VTPyI1RlNUJDxsR9FcSpwwDQYJKoZIhvcNAQEMBQAwWDELMAkG
3470
+ A1UEBhMCQ04xJTAjBgNVBAoTHFRydXN0QXNpYSBUZWNobm9sb2dpZXMsIEluYy4xIjAgBgNVBAMT
3471
+ GVRydXN0QXNpYSBUTFMgUlNBIFJvb3QgQ0EwHhcNMjQwNTE1MDU0MTU3WhcNNDQwNTE1MDU0MTU2
3472
+ WjBYMQswCQYDVQQGEwJDTjElMCMGA1UEChMcVHJ1c3RBc2lhIFRlY2hub2xvZ2llcywgSW5jLjEi
3473
+ MCAGA1UEAxMZVHJ1c3RBc2lhIFRMUyBSU0EgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
3474
+ ADCCAgoCggIBAMMWuBtqpERz5dZO9LnPWwvB0ZqB9WOwj0PBuwhaGnrhB3YmH49pVr7+NmDQDIPN
3475
+ lOrnxS1cLwUWAp4KqC/lYCZUlviYQB2srp10Zy9U+5RjmOMmSoPGlbYJQ1DNDX3eRA5gEk9bNb2/
3476
+ mThtfWza4mhzH/kxpRkQcwUqwzIZheo0qt1CHjCNP561HmHVb70AcnKtEj+qpklz8oYVlQwQX1Fk
3477
+ zv93uMltrOXVmPGZLmzjyUT5tUMnCE32ft5EebuyjBza00tsLtbDeLdM1aTk2tyKjg7/D8OmYCYo
3478
+ zza/+lcK7Fs/6TAWe8TbxNRkoDD75f0dcZLdKY9BWN4ArTr9PXwaqLEX8E40eFgl1oUh63kd0Nyr
3479
+ z2I8sMeXi9bQn9P+PN7F4/w6g3CEIR0JwqH8uyghZVNgepBtljhb//HXeltt08lwSUq6HTrQUNoy
3480
+ IBnkiz/r1RYmNzz7dZ6wB3C4FGB33PYPXFIKvF1tjVEK2sUYyJtt3LCDs3+jTnhMmCWr8n4uIF6C
3481
+ FabW2I+s5c0yhsj55NqJ4js+k8UTav/H9xj8Z7XvGCxUq0DTbE3txci3OE9kxJRMT6DNrqXGJyV1
3482
+ J23G2pyOsAWZ1SgRxSHUuPzHlqtKZFlhaxP8S8ySpg+kUb8OWJDZgoM5pl+z+m6Ss80zDoWo8SnT
3483
+ q1mt1tve1CuBAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFLgHkXlcBvRG/XtZ
3484
+ ylomkadFK/hTMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQwFAAOCAgEAIZtqBSBdGBanEqT3
3485
+ Rz/NyjuujsCCztxIJXgXbODgcMTWltnZ9r96nBO7U5WS/8+S4PPFJzVXqDuiGev4iqME3mmL5Dw8
3486
+ veWv0BIb5Ylrc5tvJQJLkIKvQMKtuppgJFqBTQUYo+IzeXoLH5Pt7DlK9RME7I10nYEKqG/odv6L
3487
+ TytpEoYKNDbdgptvT+Bz3Ul/KD7JO6NXBNiT2Twp2xIQaOHEibgGIOcberyxk2GaGUARtWqFVwHx
3488
+ tlotJnMnlvm5P1vQiJ3koP26TpUJg3933FEFlJ0gcXax7PqJtZwuhfG5WyRasQmr2soaB82G39tp
3489
+ 27RIGAAtvKLEiUUjpQ7hRGU+isFqMB3iYPg6qocJQrmBktwliJiJ8Xw18WLK7nn4GS/+X/jbh87q
3490
+ qA8MpugLoDzga5SYnH+tBuYc6kIQX+ImFTw3OffXvO645e8D7r0i+yiGNFjEWn9hongPXvPKnbwb
3491
+ PKfILfanIhHKA9jnZwqKDss1jjQ52MjqjZ9k4DewbNfFj8GQYSbbJIweSsCI3zWQzj8C9GRh3sfI
3492
+ B5XeMhg6j6JCQCTl1jNdfK7vsU1P1FeQNWrcrgSXSYk0ly4wBOeY99sLAZDBHwo/+ML+TvrbmnNz
3493
+ FrwFuHnYWa8G5z9nODmxfKuU4CkUpijy323imttUQ/hHWKNddBWcwauwxzQ=
3494
+ -----END CERTIFICATE-----
3495
+
3451
3496
  D-TRUST EV Root CA 2 2023
3452
3497
  =========================
3453
3498
  -----BEGIN CERTIFICATE-----
@@ -3478,3 +3523,34 @@ S5THaJQXfuKOKD62xur1NGyfN4gHONuGcfrNlUhDbqNPgofXNJhuS5N5YHVpD/Aa1VP6IQzCP+k/
3478
3523
  HxiMkl14p3ZnGbuy6n/pcAlWVqOwDAstNl7F6cTVg8uGF5csbBNvh1qvSaYd2804BC5f4ko1Di1L
3479
3524
  +KIkBI3Y4WNeApI02phhXBxvWHZks/wCuPWdCg==
3480
3525
  -----END CERTIFICATE-----
3526
+
3527
+ SwissSign RSA TLS Root CA 2022 - 1
3528
+ ==================================
3529
+ -----BEGIN CERTIFICATE-----
3530
+ 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
3555
+ tnu64ZzZ
3556
+ -----END CERTIFICATE-----
@@ -1 +1 @@
1
- ab3ee3651977a4178a702b0b828a4ee7b2bbb9127235b0ab740e2e15974bf5db cacert.pem
1
+ f290e6acaf904a4121424ca3ebdd70652780707e28e8af999221786b86bb1975 cacert.pem
@@ -21,7 +21,7 @@ endif()
21
21
 
22
22
  project(
23
23
  couchbase_cxx_client
24
- VERSION "1.1.0"
24
+ VERSION "1.1.1"
25
25
  LANGUAGES CXX C)
26
26
  message(STATUS "Couchbase C++ client ${couchbase_cxx_client_VERSION} build ${couchbase_cxx_client_BUILD_NUMBER}, master: ${COUCHBASE_CXX_CLIENT_MASTER_PROJECT}")
27
27
  message(STATUS "System: ${CMAKE_SYSTEM_NAME}, ${CMAKE_SYSTEM_VERSION}, ${CMAKE_SYSTEM_PROCESSOR}")
@@ -510,14 +510,14 @@ foreach(TARGET ${couchbase_cxx_client_LIBRARIES})
510
510
  set_target_properties(${TARGET} PROPERTIES POSITION_INDEPENDENT_CODE ON)
511
511
 
512
512
  target_include_directories(
513
- ${TARGET} PRIVATE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>
514
- $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/generated>
513
+ ${TARGET} PRIVATE $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/generated>
515
514
  $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/generated_$<CONFIG>>)
516
515
 
517
516
  target_include_directories(
518
517
  ${TARGET} SYSTEM PRIVATE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/third_party/cxx_function>
519
518
  $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/third_party/expected/include>)
520
519
 
520
+ target_include_directories(${TARGET} PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>)
521
521
  target_include_directories(${TARGET} PUBLIC $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
522
522
 
523
523
  enable_sanitizers(${TARGET})
@@ -21,9 +21,9 @@ CPMAddPackage(
21
21
  NAME
22
22
  couchbase_cxx_client
23
23
  GIT_TAG
24
- 1.1.0
24
+ 1.1.1
25
25
  VERSION
26
- 1.1.0
26
+ 1.1.1
27
27
  GITHUB_REPOSITORY
28
28
  "couchbase/couchbase-cxx-client"
29
29
  OPTIONS
@@ -34,17 +34,24 @@
34
34
 
35
35
  namespace couchbase::core
36
36
  {
37
+ struct node_labels {
38
+ std::string node;
39
+ std::optional<std::string> alt_node;
40
+ };
41
+
37
42
  class app_telemetry_meter_impl
38
43
  {
39
44
  public:
40
45
  app_telemetry_meter_impl() = default;
41
- app_telemetry_meter_impl(app_telemetry_meter_impl&&) = default;
46
+ app_telemetry_meter_impl(app_telemetry_meter_impl&&) = delete;
42
47
  app_telemetry_meter_impl(const app_telemetry_meter_impl&) = delete;
43
- auto operator=(app_telemetry_meter_impl&&) -> app_telemetry_meter_impl& = default;
48
+ auto operator=(app_telemetry_meter_impl&&) -> app_telemetry_meter_impl& = delete;
44
49
  auto operator=(const app_telemetry_meter_impl&) -> app_telemetry_meter_impl& = delete;
45
50
  virtual ~app_telemetry_meter_impl() = default;
46
51
 
47
52
  virtual auto enabled() -> bool = 0;
53
+ [[nodiscard]] virtual auto current_node_labels() const -> std::map<std::string, node_labels> = 0;
54
+ virtual void set_node_labels_cache(std::map<std::string, node_labels>) = 0;
48
55
  virtual auto nothing_to_report() -> bool = 0;
49
56
  virtual void update_config(const topology::configuration& config) = 0;
50
57
  virtual auto value_recorder(const std::string& node_uuid, const std::string& bucket_name)
@@ -101,11 +108,6 @@ namespace couchbase::core
101
108
  {
102
109
  namespace
103
110
  {
104
- struct node_labels {
105
- std::string node;
106
- std::optional<std::string> alt_node;
107
- };
108
-
109
111
  struct kv_non_durable_histogram {
110
112
  const char* name;
111
113
  std::atomic_uint64_t le_1ms{};
@@ -349,6 +351,16 @@ public:
349
351
  {
350
352
  /* do nothing */
351
353
  }
354
+
355
+ [[nodiscard]] auto current_node_labels() const -> std::map<std::string, node_labels> override
356
+ {
357
+ return {};
358
+ }
359
+
360
+ void set_node_labels_cache(std::map<std::string, node_labels>) override
361
+ {
362
+ /* do nothing */
363
+ }
352
364
  };
353
365
 
354
366
  class default_app_telemetry_value_recorder : public app_telemetry_value_recorder
@@ -600,6 +612,7 @@ public:
600
612
 
601
613
  void update_config(const topology::configuration& config) override
602
614
  {
615
+ node_uuids_in_last_config_.clear();
603
616
  for (const auto& node : config.nodes) {
604
617
  std::optional<std::string> alt_node{};
605
618
  if (auto it = node.alt.find("external"); it != node.alt.end()) {
@@ -611,6 +624,7 @@ public:
611
624
  node.hostname,
612
625
  alt_node,
613
626
  };
627
+ node_uuids_in_last_config_.push_back(node.node_uuid);
614
628
  }
615
629
  }
616
630
 
@@ -625,6 +639,23 @@ public:
625
639
  return recorders_.empty();
626
640
  }
627
641
 
642
+ [[nodiscard]] auto current_node_labels() const -> std::map<std::string, node_labels> override
643
+ {
644
+ std::map<std::string, node_labels> labels{};
645
+ for (const auto& node_uuid : node_uuids_in_last_config_) {
646
+ labels[node_uuid] = labels_cache_.at(node_uuid);
647
+ }
648
+ return labels;
649
+ }
650
+
651
+ void set_node_labels_cache(std::map<std::string, node_labels> labels) override
652
+ {
653
+ for (const auto& [node_uuid, _] : labels) {
654
+ node_uuids_in_last_config_.push_back(node_uuid);
655
+ }
656
+ labels_cache_ = std::move(labels);
657
+ }
658
+
628
659
  void generate_to(std::vector<std::byte>& buffer, const std::string& agent) override
629
660
  {
630
661
  auto now = std::chrono::duration_cast<std::chrono::milliseconds>(
@@ -677,6 +708,7 @@ private:
677
708
  std::map<std::string, std::shared_ptr<default_app_telemetry_value_recorder>>>
678
709
  recorders_{};
679
710
  std::map<std::string, node_labels> labels_cache_{};
711
+ std::vector<std::string> node_uuids_in_last_config_{};
680
712
  };
681
713
 
682
714
  auto
@@ -699,6 +731,7 @@ app_telemetry_meter::app_telemetry_meter()
699
731
  void
700
732
  app_telemetry_meter::disable()
701
733
  {
734
+ const std::scoped_lock lock{ impl_mutex_ };
702
735
  if (!impl_->enabled()) {
703
736
  return;
704
737
  }
@@ -712,6 +745,7 @@ app_telemetry_meter::disable()
712
745
  void
713
746
  app_telemetry_meter::enable()
714
747
  {
748
+ const std::scoped_lock lock{ impl_mutex_ };
715
749
  if (impl_->enabled()) {
716
750
  return;
717
751
  }
@@ -730,6 +764,7 @@ app_telemetry_meter::~app_telemetry_meter() = default;
730
764
  void
731
765
  app_telemetry_meter::update_config(const topology::configuration& config)
732
766
  {
767
+ const std::shared_lock lock{ impl_mutex_ };
733
768
  return impl_->update_config(config);
734
769
  }
735
770
 
@@ -737,17 +772,20 @@ auto
737
772
  app_telemetry_meter::value_recorder(const std::string& node_uuid, const std::string& bucket_name)
738
773
  -> std::shared_ptr<app_telemetry_value_recorder>
739
774
  {
775
+ const std::shared_lock lock{ impl_mutex_ };
740
776
  return impl_->value_recorder(node_uuid, bucket_name);
741
777
  }
742
778
 
743
779
  void
744
780
  app_telemetry_meter::generate_report(std::vector<std::byte>& output_buffer)
745
781
  {
782
+ const std::scoped_lock lock{ impl_mutex_ };
746
783
  if (impl_->nothing_to_report()) {
747
784
  return;
748
785
  }
749
- auto old_impl = std::move(impl_);
786
+ const auto old_impl = std::move(impl_);
750
787
  impl_ = std::make_unique<default_app_telemetry_meter_impl>();
788
+ impl_->set_node_labels_cache(old_impl->current_node_labels());
751
789
  old_impl->generate_to(output_buffer, agent_);
752
790
  }
753
791
  } // namespace couchbase::core
@@ -20,6 +20,7 @@
20
20
  #include <chrono>
21
21
  #include <cstdint>
22
22
  #include <memory>
23
+ #include <shared_mutex>
23
24
  #include <string>
24
25
  #include <vector>
25
26
 
@@ -175,9 +176,9 @@ class app_telemetry_meter
175
176
  {
176
177
  public:
177
178
  app_telemetry_meter();
178
- app_telemetry_meter(app_telemetry_meter&&) = default;
179
+ app_telemetry_meter(app_telemetry_meter&&) = delete;
179
180
  app_telemetry_meter(const app_telemetry_meter&) = delete;
180
- auto operator=(app_telemetry_meter&&) -> app_telemetry_meter& = default;
181
+ auto operator=(app_telemetry_meter&&) -> app_telemetry_meter& = delete;
181
182
  auto operator=(const app_telemetry_meter&) -> app_telemetry_meter& = delete;
182
183
  ~app_telemetry_meter();
183
184
 
@@ -193,6 +194,7 @@ public:
193
194
  private:
194
195
  std::string agent_;
195
196
  std::unique_ptr<app_telemetry_meter_impl> impl_;
197
+ std::shared_mutex impl_mutex_{};
196
198
  };
197
199
 
198
200
  } // namespace couchbase::core
@@ -350,9 +350,10 @@ public:
350
350
  }
351
351
 
352
352
  origin_ = std::move(origin);
353
- CB_LOG_DEBUG(R"(open cluster, id: "{}", core version: "{}", {})",
353
+ CB_LOG_DEBUG(R"(open cluster, id: "{}", core version: "{}", connection string: {}, {})",
354
354
  id_,
355
355
  couchbase::core::meta::sdk_semver(),
356
+ origin_.connection_string(),
356
357
  origin_.to_json());
357
358
  setup_observability();
358
359
  if (origin_.options().enable_dns_srv) {
@@ -107,6 +107,7 @@ public:
107
107
  std::chrono::milliseconds app_telemetry_backoff_interval{
108
108
  timeout_defaults::app_telemetry_backoff_interval
109
109
  };
110
+ bool preserve_bootstrap_nodes_order{ false };
110
111
  };
111
112
 
112
113
  } // namespace couchbase::core
@@ -140,6 +140,7 @@ options_to_origin(const std::string& connection_string, const couchbase::cluster
140
140
  user_options.enable_mutation_tokens = opts.behavior.enable_mutation_tokens;
141
141
  user_options.enable_unordered_execution = opts.behavior.enable_unordered_execution;
142
142
  user_options.user_agent_extra = opts.behavior.user_agent_extra;
143
+ user_options.preserve_bootstrap_nodes_order = opts.behavior.preserve_bootstrap_nodes_order;
143
144
 
144
145
  user_options.server_group = opts.network.server_group;
145
146
  user_options.enable_tcp_keep_alive = opts.network.enable_tcp_keep_alive;
@@ -185,15 +185,30 @@ make_error(const couchbase::core::transaction_error_context& ctx) -> error
185
185
  }
186
186
 
187
187
  auto
188
- make_error(const couchbase::core::transaction_op_error_context& ctx) -> error
188
+ make_error(const core::transactions::op_exception& exc) -> error
189
189
  {
190
- if (std::holds_alternative<key_value_error_context>(ctx.cause())) {
191
- return { ctx.ec(), {}, {}, make_error(std::get<key_value_error_context>(ctx.cause())) };
190
+ std::optional<error> cause;
191
+ if (std::holds_alternative<key_value_error_context>(exc.ctx().cause())) {
192
+ cause = make_error(std::get<key_value_error_context>(exc.ctx().cause()));
192
193
  }
193
- if (std::holds_alternative<query_error_context>(ctx.cause())) {
194
- return { ctx.ec(), {}, {}, make_error(std::get<query_error_context>(ctx.cause())) };
194
+ if (std::holds_alternative<query_error_context>(exc.ctx().cause())) {
195
+ cause = make_error(std::get<query_error_context>(exc.ctx().cause()));
195
196
  }
196
- return ctx.ec();
197
+
198
+ if (cause.has_value()) {
199
+ return error{
200
+ transaction_op_errc_from_external_exception(exc.cause()),
201
+ exc.what(),
202
+ {},
203
+ cause.value(),
204
+ };
205
+ }
206
+
207
+ return error{
208
+ transaction_op_errc_from_external_exception(exc.cause()),
209
+ exc.what(),
210
+ {},
211
+ };
197
212
  }
198
213
 
199
214
  auto
@@ -57,7 +57,7 @@ auto
57
57
  make_error(const couchbase::core::transaction_error_context& core_ctx) -> error;
58
58
 
59
59
  auto
60
- make_error(const couchbase::core::transaction_op_error_context& core_ctx) -> error;
60
+ make_error(const couchbase::core::transactions::op_exception& exc) -> error;
61
61
 
62
62
  auto
63
63
  make_error(const couchbase::core::transactions::transaction_operation_failed& core_tof) -> error;
@@ -114,8 +114,11 @@ public:
114
114
  void update_config(topology::configuration config) override
115
115
  {
116
116
  {
117
- std::scoped_lock config_lock(config_mutex_, sessions_mutex_);
117
+ std::scoped_lock config_lock(config_mutex_, sessions_mutex_, next_index_mutex_);
118
118
  config_ = std::move(config);
119
+ if (!config_.nodes.empty() && next_index_ >= config_.nodes.size()) {
120
+ next_index_ = 0;
121
+ }
119
122
  for (auto& [type, sessions] : idle_sessions_) {
120
123
  sessions.remove_if([&opts = options_, &cfg = config_](const auto& session) {
121
124
  return session && !cfg.has_node(opts.network,
@@ -71,9 +71,10 @@ search_index_get_all_request::make_response(error_context::http&& ctx,
71
71
  for (const auto& [name, index] : indexes->get_object()) {
72
72
  response.indexes.emplace_back(index.as<couchbase::core::management::search::index>());
73
73
  }
74
- return response;
75
74
  }
76
- } else if (encoded.status_code == 404) {
75
+ return response;
76
+ }
77
+ if (encoded.status_code == 404) {
77
78
  tao::json::value payload{};
78
79
  try {
79
80
  payload = utils::json::parse(encoded.body.data());
@@ -25,6 +25,8 @@
25
25
  #include <spdlog/fmt/bundled/core.h>
26
26
 
27
27
  #include <tao/json.hpp>
28
+
29
+ #include <random>
28
30
  #include <utility>
29
31
 
30
32
  namespace tao::json
@@ -338,6 +340,7 @@ couchbase::core::origin::origin(couchbase::core::cluster_credentials auth,
338
340
  const couchbase::core::utils::connection_string& connstr)
339
341
  : options_(connstr.options)
340
342
  , credentials_(std::move(auth))
343
+ , connection_string_(connstr.input)
341
344
  {
342
345
  nodes_.reserve(connstr.bootstrap_nodes.size());
343
346
  for (const auto& node : connstr.bootstrap_nodes) {
@@ -345,6 +348,9 @@ couchbase::core::origin::origin(couchbase::core::cluster_credentials auth,
345
348
  node.port > 0 ? std::to_string(node.port)
346
349
  : std::to_string(connstr.default_port));
347
350
  }
351
+ if (!options_.preserve_bootstrap_nodes_order) {
352
+ shuffle_nodes();
353
+ }
348
354
  next_node_ = nodes_.begin();
349
355
  }
350
356
  auto
@@ -360,6 +366,11 @@ couchbase::core::origin::operator=(const couchbase::core::origin& other) -> couc
360
366
  return *this;
361
367
  }
362
368
  auto
369
+ couchbase::core::origin::connection_string() const -> const std::string&
370
+ {
371
+ return connection_string_;
372
+ }
373
+ auto
363
374
  couchbase::core::origin::username() const -> const std::string&
364
375
  {
365
376
  return credentials_.username;
@@ -399,10 +410,21 @@ couchbase::core::origin::get_nodes() const -> std::vector<std::string>
399
410
  }
400
411
  return res;
401
412
  }
413
+
414
+ void
415
+ couchbase::core::origin::shuffle_nodes()
416
+ {
417
+ static thread_local std::default_random_engine gen{ std::random_device{}() };
418
+ std::shuffle(nodes_.begin(), nodes_.end(), gen);
419
+ }
420
+
402
421
  void
403
422
  couchbase::core::origin::set_nodes(couchbase::core::origin::node_list nodes)
404
423
  {
405
424
  nodes_ = std::move(nodes);
425
+ if (!options_.preserve_bootstrap_nodes_order) {
426
+ shuffle_nodes();
427
+ }
406
428
  next_node_ = nodes_.begin();
407
429
  exhausted_ = false;
408
430
  }
@@ -428,6 +450,9 @@ couchbase::core::origin::set_nodes_from_config(const topology::configuration& co
428
450
  std::make_pair(node.hostname_for(options_.network), std::to_string(port)));
429
451
  }
430
452
  }
453
+ if (!options_.preserve_bootstrap_nodes_order) {
454
+ shuffle_nodes();
455
+ }
431
456
  next_node_ = nodes_.begin();
432
457
  }
433
458
  auto
@@ -55,29 +55,31 @@ struct origin {
55
55
  const std::string& port,
56
56
  cluster_options options);
57
57
  origin(cluster_credentials auth, const utils::connection_string& connstr);
58
- origin& operator=(origin&& other) = default;
59
- origin& operator=(const origin& other);
58
+ auto operator=(origin&& other) -> origin& = default;
59
+ auto operator=(const origin& other) -> origin&;
60
60
 
61
- [[nodiscard]] const std::string& username() const;
62
- [[nodiscard]] const std::string& password() const;
63
- [[nodiscard]] const std::string& certificate_path() const;
64
- [[nodiscard]] const std::string& key_path() const;
61
+ [[nodiscard]] auto connection_string() const -> const std::string&;
62
+ [[nodiscard]] auto username() const -> const std::string&;
63
+ [[nodiscard]] auto password() const -> const std::string&;
64
+ [[nodiscard]] auto certificate_path() const -> const std::string&;
65
+ [[nodiscard]] auto key_path() const -> const std::string&;
65
66
 
66
- [[nodiscard]] std::vector<std::string> get_hostnames() const;
67
- [[nodiscard]] std::vector<std::string> get_nodes() const;
67
+ [[nodiscard]] auto get_hostnames() const -> std::vector<std::string>;
68
+ [[nodiscard]] auto get_nodes() const -> std::vector<std::string>;
68
69
 
70
+ void shuffle_nodes();
69
71
  void set_nodes(node_list nodes);
70
72
  void set_nodes_from_config(const topology::configuration& config);
71
73
 
72
- [[nodiscard]] std::pair<std::string, std::string> next_address();
74
+ [[nodiscard]] auto next_address() -> std::pair<std::string, std::string>;
73
75
 
74
- [[nodiscard]] bool exhausted() const;
76
+ [[nodiscard]] auto exhausted() const -> bool;
75
77
 
76
78
  void restart();
77
79
 
78
- [[nodiscard]] const couchbase::core::cluster_options& options() const;
79
- [[nodiscard]] couchbase::core::cluster_options& options();
80
- [[nodiscard]] const couchbase::core::cluster_credentials& credentials() const;
80
+ [[nodiscard]] auto options() const -> const couchbase::core::cluster_options&;
81
+ [[nodiscard]] auto options() -> couchbase::core::cluster_options&;
82
+ [[nodiscard]] auto credentials() const -> const couchbase::core::cluster_credentials&;
81
83
  [[nodiscard]] auto to_json() const -> std::string;
82
84
 
83
85
  private:
@@ -86,6 +88,7 @@ private:
86
88
  node_list nodes_{};
87
89
  node_list::iterator next_node_{};
88
90
  bool exhausted_{ false };
91
+ std::string connection_string_{};
89
92
  };
90
93
 
91
94
  } // namespace couchbase::core
@@ -103,7 +103,7 @@ wrap_call_for_public_api(std::function<transaction_get_result()>&& handler)
103
103
  } catch (const transaction_operation_failed& e) {
104
104
  return { core::impl::make_error(e), {} };
105
105
  } catch (const op_exception& ex) {
106
- return { core::impl::make_error(ex.ctx()), {} };
106
+ return { core::impl::make_error(ex), {} };
107
107
  } catch (...) {
108
108
  // the handler should catch everything else, but just in case...
109
109
  return { { errc::transaction_op::generic }, {} };
@@ -123,7 +123,7 @@ wrap_callback_for_async_public_api(
123
123
  try {
124
124
  std::rethrow_exception(err);
125
125
  } catch (const op_exception& e) {
126
- return cb(core::impl::make_error(e.ctx()), {});
126
+ return cb(core::impl::make_error(e), {});
127
127
  } catch (const transaction_operation_failed& e) {
128
128
  return cb(core::impl::make_error(e), {});
129
129
  } catch (...) {
@@ -649,7 +649,7 @@ attempt_context_impl::get_multi(
649
649
  try {
650
650
  std::rethrow_exception(err);
651
651
  } catch (const op_exception& e) {
652
- return cb(core::impl::make_error(e.ctx()), {});
652
+ return cb(core::impl::make_error(e), {});
653
653
  } catch (const transaction_operation_failed& e) {
654
654
  return cb(core::impl::make_error(e), {});
655
655
  } catch (...) {
@@ -766,7 +766,7 @@ attempt_context_impl::get_multi_replicas_from_preferred_server_group(
766
766
  try {
767
767
  std::rethrow_exception(err);
768
768
  } catch (const op_exception& e) {
769
- return cb(core::impl::make_error(e.ctx()), {});
769
+ return cb(core::impl::make_error(e), {});
770
770
  } catch (const transaction_operation_failed& e) {
771
771
  return cb(core::impl::make_error(e), {});
772
772
  } catch (...) {
@@ -2139,11 +2139,25 @@ attempt_context_impl::do_public_query(
2139
2139
  try {
2140
2140
  auto result = do_core_query(statement, opts, query_context);
2141
2141
  auto [ctx, res] = core::impl::build_transaction_query_result(result);
2142
- return std::make_pair(core::impl::make_error(ctx), res);
2142
+ if (ctx.ec()) {
2143
+ // This should have already been converted to an exception by handle_query_error, which we
2144
+ // handle above. Let's return an error here just in case
2145
+ std::string msg = "Txns query error occured that should have been handled further upstream, "
2146
+ "which might indicate a bug.";
2147
+ if (std::holds_alternative<query_error_context>(ctx.cause())) {
2148
+ return { { ctx.ec(),
2149
+ std::move(msg),
2150
+ {},
2151
+ impl::make_error(std::get<query_error_context>(ctx.cause())) },
2152
+ {} };
2153
+ }
2154
+ return { { ctx.ec(), std::move(msg) }, {} };
2155
+ }
2156
+ return { {}, res };
2143
2157
  } catch (const transaction_operation_failed& e) {
2144
2158
  return { core::impl::make_error(e), {} };
2145
2159
  } catch (const op_exception& qe) {
2146
- return { core::impl::make_error(qe.ctx()), {} };
2160
+ return { core::impl::make_error(qe), {} };
2147
2161
  } catch (...) {
2148
2162
  // should not be necessary, but just in case...
2149
2163
  return { { couchbase::errc::transaction_op::generic }, {} };
@@ -2267,7 +2281,7 @@ attempt_context_impl::insert_raw_with_query(const core::document_id& id,
2267
2281
  std::rethrow_exception(err);
2268
2282
  } catch (const transaction_operation_failed& e) {
2269
2283
  return self->op_completed_with_error(std::move(cb), e);
2270
- } catch (const document_exists& ex) {
2284
+ } catch (const op_exception& ex) {
2271
2285
  return self->op_completed_with_error(std::move(cb), ex);
2272
2286
  } catch (const std::exception& e) {
2273
2287
  return self->op_completed_with_error(
@@ -4029,14 +4043,28 @@ attempt_context_impl::query(std::string statement,
4029
4043
  } catch (const transaction_operation_failed& e) {
4030
4044
  return handler(core::impl::make_error(e), {});
4031
4045
  } catch (const op_exception& ex) {
4032
- return handler(core::impl::make_error(ex.ctx()), {});
4046
+ return handler(core::impl::make_error(ex), {});
4033
4047
  } catch (...) {
4034
4048
  // just in case...
4035
4049
  return handler({ couchbase::errc::transaction_op::generic }, {});
4036
4050
  }
4037
4051
  }
4038
4052
  auto [ctx, res] = core::impl::build_transaction_query_result(*resp);
4039
- handler(core::impl::make_error(ctx), res);
4053
+ if (ctx.ec()) {
4054
+ // This should have already been converted to an exception by handle_query_error,
4055
+ // which we handle above. Let's return an error here just in case
4056
+ std::string msg = "Txns query error occured that should have been handled further "
4057
+ "upstream, which might indicate a bug.";
4058
+ if (std::holds_alternative<query_error_context>(ctx.cause())) {
4059
+ return handler({ ctx.ec(),
4060
+ std::move(msg),
4061
+ {},
4062
+ impl::make_error(std::get<query_error_context>(ctx.cause())) },
4063
+ {});
4064
+ }
4065
+ return handler({ ctx.ec(), std::move(msg) }, {});
4066
+ }
4067
+ return handler({}, res);
4040
4068
  });
4041
4069
  }
4042
4070
 
@@ -52,7 +52,8 @@ public:
52
52
 
53
53
  [[nodiscard]] auto exists(std::size_t spec_index) const -> bool
54
54
  {
55
- return spec_index >= content_.size() && content_[spec_index].has_value();
55
+ Expects(spec_index < content_.size());
56
+ return content_[spec_index].has_value();
56
57
  }
57
58
 
58
59
  [[nodiscard]] auto content() const -> const std::vector<std::optional<codec::encoded_value>>&
@@ -47,7 +47,8 @@ public:
47
47
 
48
48
  [[nodiscard]] auto exists(std::size_t spec_index) const -> bool
49
49
  {
50
- return spec_index >= content_.size() && content_[spec_index].has_value();
50
+ Expects(spec_index < content_.size());
51
+ return content_[spec_index].has_value();
51
52
  }
52
53
 
53
54
  [[nodiscard]] auto content() const -> const std::vector<std::optional<codec::encoded_value>>&
@@ -586,6 +586,8 @@ extract_options(connection_string& connstr)
586
586
  parse_option(connstr.options.enable_app_telemetry, name, value, connstr.warnings);
587
587
  } else if (name == "app_telemetry_endpoint") {
588
588
  parse_option(connstr.options.app_telemetry_endpoint, name, value, connstr.warnings);
589
+ } else if (name == "preserve_bootstrap_nodes_order") {
590
+ parse_option(connstr.options.preserve_bootstrap_nodes_order, name, value, connstr.warnings);
589
591
  } else {
590
592
  connstr.warnings.push_back(
591
593
  fmt::format(R"(unknown parameter "{}" in connection string (value "{}"))", name, value));
@@ -598,6 +600,7 @@ auto
598
600
  parse_connection_string(const std::string& input, cluster_options options) -> connection_string
599
601
  {
600
602
  connection_string res{};
603
+ res.input = input;
601
604
  res.options = std::move(options);
602
605
 
603
606
  if (input.empty()) {
@@ -57,6 +57,7 @@ struct connection_string {
57
57
  }
58
58
  };
59
59
 
60
+ std::string input;
60
61
  std::string scheme{ "couchbase" };
61
62
  bool tls{ false };
62
63
  std::map<std::string, std::string> params{};
@@ -67,6 +67,12 @@ public:
67
67
  return *this;
68
68
  }
69
69
 
70
+ auto preserve_bootstrap_nodes_order(bool enable) -> behavior_options&
71
+ {
72
+ preserve_bootstrap_nodes_order_ = enable;
73
+ return *this;
74
+ }
75
+
70
76
  struct built {
71
77
  std::string user_agent_extra;
72
78
  bool show_queries;
@@ -75,6 +81,7 @@ public:
75
81
  bool enable_unordered_execution;
76
82
  bool dump_configuration;
77
83
  std::string network;
84
+ bool preserve_bootstrap_nodes_order;
78
85
  };
79
86
 
80
87
  [[nodiscard]] auto build() const -> built
@@ -87,6 +94,7 @@ public:
87
94
  enable_unordered_execution_,
88
95
  dump_configuration_,
89
96
  network_,
97
+ preserve_bootstrap_nodes_order_,
90
98
  };
91
99
  }
92
100
 
@@ -98,5 +106,6 @@ private:
98
106
  bool enable_unordered_execution_{ true };
99
107
  bool dump_configuration_{ false };
100
108
  std::string network_{ "auto" };
109
+ bool preserve_bootstrap_nodes_order_{ false };
101
110
  };
102
111
  } // namespace couchbase
@@ -91,7 +91,10 @@ public:
91
91
  */
92
92
  [[nodiscard]] auto exists(std::size_t spec_index) const -> bool
93
93
  {
94
- return spec_index >= content_.size() && content_[spec_index].has_value();
94
+ if (spec_index >= content_.size()) {
95
+ throw std::invalid_argument("spec index " + std::to_string(spec_index) + " is not valid");
96
+ }
97
+ return content_[spec_index].has_value();
95
98
  }
96
99
 
97
100
  private:
@@ -85,7 +85,10 @@ public:
85
85
  */
86
86
  [[nodiscard]] auto exists(std::size_t spec_index) const -> bool
87
87
  {
88
- return spec_index >= content_.size() && content_[spec_index].has_value();
88
+ if (spec_index >= content_.size()) {
89
+ throw std::invalid_argument("spec index " + std::to_string(spec_index) + " is not valid");
90
+ }
91
+ return content_[spec_index].has_value();
89
92
  }
90
93
 
91
94
  private:
package/package.json CHANGED
@@ -54,7 +54,7 @@
54
54
  "type": "git",
55
55
  "url": "http://github.com/couchbase/couchnode.git"
56
56
  },
57
- "version": "4.5.0",
57
+ "version": "4.5.1",
58
58
  "config": {
59
59
  "native": false
60
60
  },
@@ -79,13 +79,13 @@
79
79
  ]
80
80
  },
81
81
  "optionalDependencies": {
82
- "@couchbase/couchbase-darwin-arm64-napi": "4.5.0",
83
- "@couchbase/couchbase-darwin-x64-napi": "4.5.0",
84
- "@couchbase/couchbase-linux-arm64-napi": "4.5.0",
85
- "@couchbase/couchbase-linuxmusl-arm64-napi": "4.5.0",
86
- "@couchbase/couchbase-linuxmusl-x64-napi": "4.5.0",
87
- "@couchbase/couchbase-linux-x64-napi": "4.5.0",
88
- "@couchbase/couchbase-win32-x64-napi": "4.5.0"
82
+ "@couchbase/couchbase-darwin-arm64-napi": "4.5.1",
83
+ "@couchbase/couchbase-darwin-x64-napi": "4.5.1",
84
+ "@couchbase/couchbase-linux-arm64-napi": "4.5.1",
85
+ "@couchbase/couchbase-linuxmusl-arm64-napi": "4.5.1",
86
+ "@couchbase/couchbase-linuxmusl-x64-napi": "4.5.1",
87
+ "@couchbase/couchbase-linux-x64-napi": "4.5.1",
88
+ "@couchbase/couchbase-win32-x64-napi": "4.5.1"
89
89
  },
90
90
  "files": [
91
91
  "LICENSE",