couchbase 3.5.7 → 3.6.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 (155) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/ext/cache/extconf_include.rb +3 -3
  4. data/ext/cache/mozilla-ca-bundle.crt +3 -165
  5. data/ext/cache/mozilla-ca-bundle.sha256 +1 -1
  6. data/ext/cache/snappy/{585305c8dbb8f762f2c2e17f937f1cf3ac6cbc9c → 3cde171792b3607f75c14e5011eaf69da4857bd8}/snappy/CMakeLists.txt +14 -10
  7. data/ext/cache/snappy/{585305c8dbb8f762f2c2e17f937f1cf3ac6cbc9c → 3cde171792b3607f75c14e5011eaf69da4857bd8}/snappy/snappy.cc +7 -4
  8. data/ext/couchbase/CMakeLists.txt +12 -1
  9. data/ext/couchbase/cmake/Profiler.cmake +15 -0
  10. data/ext/couchbase/cmake/ThirdPartyDependencies.cmake +2 -2
  11. data/ext/couchbase/cmake/couchbase_cxx_client.pc.in +1 -1
  12. data/ext/couchbase/core/app_telemetry_address.cxx +55 -0
  13. data/ext/couchbase/core/app_telemetry_address.hxx +39 -0
  14. data/ext/couchbase/core/app_telemetry_meter.cxx +753 -0
  15. data/ext/couchbase/core/app_telemetry_meter.hxx +198 -0
  16. data/ext/couchbase/core/app_telemetry_reporter.cxx +895 -0
  17. data/ext/couchbase/core/app_telemetry_reporter.hxx +59 -0
  18. data/ext/couchbase/core/bucket.cxx +77 -35
  19. data/ext/couchbase/core/bucket.hxx +17 -10
  20. data/ext/couchbase/core/cluster.cxx +54 -16
  21. data/ext/couchbase/core/cluster_credentials.cxx +27 -0
  22. data/ext/couchbase/core/cluster_credentials.hxx +36 -0
  23. data/ext/couchbase/core/cluster_options.hxx +12 -0
  24. data/ext/couchbase/core/collections_component.cxx +7 -5
  25. data/ext/couchbase/core/http_component.cxx +6 -0
  26. data/ext/couchbase/core/impl/binary_collection.cxx +4 -0
  27. data/ext/couchbase/core/impl/bucket_manager.cxx +2 -0
  28. data/ext/couchbase/core/impl/cluster.cxx +9 -0
  29. data/ext/couchbase/core/impl/collection.cxx +2 -0
  30. data/ext/couchbase/core/impl/error.cxx +1 -0
  31. data/ext/couchbase/core/impl/logger.cxx +51 -0
  32. data/ext/couchbase/core/impl/replica_utils.cxx +1 -1
  33. data/ext/couchbase/core/impl/transaction_get_multi_replicas_from_preferred_server_group_spec.cxx +32 -0
  34. data/ext/couchbase/core/impl/transaction_get_multi_spec.cxx +30 -0
  35. data/ext/couchbase/core/impl/transaction_op_error_category.cxx +2 -0
  36. data/ext/couchbase/core/io/config_tracker.cxx +6 -6
  37. data/ext/couchbase/core/io/http_command.hxx +35 -11
  38. data/ext/couchbase/core/io/http_session.cxx +10 -0
  39. data/ext/couchbase/core/io/http_session.hxx +4 -0
  40. data/ext/couchbase/core/io/http_session_manager.hxx +83 -34
  41. data/ext/couchbase/core/io/mcbp_command.hxx +41 -2
  42. data/ext/couchbase/core/io/mcbp_session.cxx +52 -19
  43. data/ext/couchbase/core/io/mcbp_session.hxx +3 -0
  44. data/ext/couchbase/core/logger/logger.cxx +46 -0
  45. data/ext/couchbase/core/logger/logger.hxx +41 -1
  46. data/ext/couchbase/core/management/bucket_settings.hxx +1 -0
  47. data/ext/couchbase/core/management/bucket_settings_json.hxx +4 -0
  48. data/ext/couchbase/core/meta/features.hxx +32 -0
  49. data/ext/couchbase/core/operations/document_analytics.cxx +9 -9
  50. data/ext/couchbase/core/operations/document_append.cxx +1 -0
  51. data/ext/couchbase/core/operations/document_append.hxx +1 -0
  52. data/ext/couchbase/core/operations/document_get_all_replicas.hxx +10 -2
  53. data/ext/couchbase/core/operations/document_lookup_in.cxx +4 -0
  54. data/ext/couchbase/core/operations/document_lookup_in_all_replicas.hxx +14 -2
  55. data/ext/couchbase/core/operations/document_lookup_in_any_replica.hxx +4 -0
  56. data/ext/couchbase/core/operations/document_mutate_in.cxx +4 -0
  57. data/ext/couchbase/core/operations/document_mutate_in.hxx +1 -0
  58. data/ext/couchbase/core/operations/document_prepend.cxx +1 -0
  59. data/ext/couchbase/core/operations/document_prepend.hxx +1 -0
  60. data/ext/couchbase/core/operations/document_query.cxx +12 -10
  61. data/ext/couchbase/core/operations/http_noop.cxx +1 -0
  62. data/ext/couchbase/core/operations/management/bucket_create.cxx +3 -0
  63. data/ext/couchbase/core/operations/management/bucket_update.cxx +3 -0
  64. data/ext/couchbase/core/origin.cxx +0 -5
  65. data/ext/couchbase/core/origin.hxx +2 -11
  66. data/ext/couchbase/core/platform/random.cc +6 -3
  67. data/ext/couchbase/core/platform/random.h +2 -2
  68. data/ext/couchbase/core/protocol/cmd_mutate_in.hxx +9 -0
  69. data/ext/couchbase/core/timeout_defaults.hxx +4 -0
  70. data/ext/couchbase/core/topology/configuration.cxx +10 -13
  71. data/ext/couchbase/core/topology/configuration.hxx +14 -15
  72. data/ext/couchbase/core/topology/configuration_json.hxx +6 -0
  73. data/ext/couchbase/core/transactions/async_attempt_context.hxx +22 -2
  74. data/ext/couchbase/core/transactions/attempt_context.hxx +25 -7
  75. data/ext/couchbase/core/transactions/attempt_context_impl.cxx +688 -238
  76. data/ext/couchbase/core/transactions/attempt_context_impl.hxx +91 -12
  77. data/ext/couchbase/core/transactions/exceptions.cxx +5 -0
  78. data/ext/couchbase/core/transactions/exceptions.hxx +20 -0
  79. data/ext/couchbase/core/transactions/exceptions_fmt.hxx +3 -0
  80. data/ext/couchbase/core/transactions/forward_compat.cxx +71 -6
  81. data/ext/couchbase/core/transactions/forward_compat.hxx +45 -59
  82. data/ext/couchbase/core/transactions/get_multi_orchestrator.cxx +616 -0
  83. data/ext/couchbase/core/transactions/get_multi_orchestrator.hxx +61 -0
  84. data/ext/couchbase/core/transactions/internal/doc_record.cxx +8 -0
  85. data/ext/couchbase/core/transactions/internal/doc_record.hxx +16 -5
  86. data/ext/couchbase/core/transactions/internal/exceptions_internal.hxx +12 -0
  87. data/ext/couchbase/core/transactions/internal/transaction_context.hxx +13 -0
  88. data/ext/couchbase/core/transactions/internal/transaction_fields.hxx +1 -0
  89. data/ext/couchbase/core/transactions/staged_mutation.cxx +277 -96
  90. data/ext/couchbase/core/transactions/staged_mutation.hxx +28 -76
  91. data/ext/couchbase/core/transactions/transaction_context.cxx +33 -0
  92. data/ext/couchbase/core/transactions/transaction_get_multi_mode.hxx +28 -0
  93. data/ext/couchbase/core/transactions/transaction_get_multi_replicas_from_preferred_server_group_mode.hxx +27 -0
  94. data/ext/couchbase/core/transactions/transaction_get_multi_replicas_from_preferred_server_group_result.hxx +71 -0
  95. data/ext/couchbase/core/transactions/transaction_get_multi_result.hxx +66 -0
  96. data/ext/couchbase/core/transactions/transaction_links.hxx +10 -0
  97. data/ext/couchbase/core/transactions/transactions.cxx +8 -3
  98. data/ext/couchbase/core/utils/connection_string.cxx +4 -0
  99. data/ext/couchbase/core/utils/url_codec.cxx +26 -0
  100. data/ext/couchbase/core/utils/url_codec.hxx +11 -0
  101. data/ext/couchbase/core/websocket_codec.cxx +647 -0
  102. data/ext/couchbase/core/websocket_codec.hxx +77 -0
  103. data/ext/couchbase/couchbase/analytics_options.hxx +70 -6
  104. data/ext/couchbase/couchbase/application_telemetry_options.hxx +124 -0
  105. data/ext/couchbase/couchbase/cluster_options.hxx +17 -0
  106. data/ext/couchbase/couchbase/error_codes.hxx +1 -0
  107. data/ext/couchbase/couchbase/logger.hxx +16 -0
  108. data/ext/couchbase/couchbase/management/bucket_settings.hxx +1 -0
  109. data/ext/couchbase/couchbase/query_options.hxx +70 -6
  110. data/ext/couchbase/couchbase/transactions/async_attempt_context.hxx +29 -5
  111. data/ext/couchbase/couchbase/transactions/attempt_context.hxx +24 -7
  112. data/ext/couchbase/couchbase/transactions/transaction_get_multi_mode.hxx +47 -0
  113. data/ext/couchbase/couchbase/transactions/transaction_get_multi_options.hxx +44 -0
  114. data/ext/couchbase/couchbase/transactions/transaction_get_multi_replicas_from_preferred_server_group_mode.hxx +46 -0
  115. data/ext/couchbase/couchbase/transactions/transaction_get_multi_replicas_from_preferred_server_group_options.hxx +48 -0
  116. data/ext/couchbase/couchbase/transactions/transaction_get_multi_replicas_from_preferred_server_group_result.hxx +109 -0
  117. data/ext/couchbase/couchbase/transactions/transaction_get_multi_replicas_from_preferred_server_group_spec.hxx +47 -0
  118. data/ext/couchbase/couchbase/transactions/transaction_get_multi_result.hxx +102 -0
  119. data/ext/couchbase/couchbase/transactions/transaction_get_multi_spec.hxx +45 -0
  120. data/ext/rcb_buckets.cxx +26 -0
  121. data/lib/active_support/cache/couchbase_store.rb +1 -1
  122. data/lib/couchbase/cluster.rb +1 -1
  123. data/lib/couchbase/collection.rb +1 -1
  124. data/lib/couchbase/collection_options.rb +2 -2
  125. data/lib/couchbase/management/analytics_index_manager.rb +4 -4
  126. data/lib/couchbase/management/bucket_manager.rb +8 -2
  127. data/lib/couchbase/protostellar/cluster.rb +2 -2
  128. data/lib/couchbase/protostellar/collection.rb +1 -1
  129. data/lib/couchbase/protostellar/management/collection_query_index_manager.rb +1 -1
  130. data/lib/couchbase/protostellar/request_generator/admin/bucket.rb +4 -4
  131. data/lib/couchbase/protostellar/request_generator/admin/collection.rb +6 -6
  132. data/lib/couchbase/protostellar/request_generator/admin/query.rb +13 -13
  133. data/lib/couchbase/protostellar/request_generator/kv.rb +25 -25
  134. data/lib/couchbase/protostellar/request_generator/query.rb +4 -4
  135. data/lib/couchbase/protostellar/request_generator/search.rb +25 -25
  136. data/lib/couchbase/protostellar/response_converter/search.rb +1 -1
  137. data/lib/couchbase/protostellar/retry/reason.rb +1 -1
  138. data/lib/couchbase/protostellar/timeouts.rb +1 -1
  139. data/lib/couchbase/scope.rb +1 -1
  140. data/lib/couchbase/transcoder_flags.rb +1 -1
  141. data/lib/couchbase/utils/stdlib_logger_adapter.rb +1 -1
  142. data/lib/couchbase/version.rb +1 -1
  143. metadata +47 -19
  144. /data/ext/cache/snappy/{585305c8dbb8f762f2c2e17f937f1cf3ac6cbc9c → 3cde171792b3607f75c14e5011eaf69da4857bd8}/snappy/COPYING +0 -0
  145. /data/ext/cache/snappy/{585305c8dbb8f762f2c2e17f937f1cf3ac6cbc9c → 3cde171792b3607f75c14e5011eaf69da4857bd8}/snappy/cmake/SnappyConfig.cmake.in +0 -0
  146. /data/ext/cache/snappy/{585305c8dbb8f762f2c2e17f937f1cf3ac6cbc9c → 3cde171792b3607f75c14e5011eaf69da4857bd8}/snappy/cmake/config.h.in +0 -0
  147. /data/ext/cache/snappy/{585305c8dbb8f762f2c2e17f937f1cf3ac6cbc9c → 3cde171792b3607f75c14e5011eaf69da4857bd8}/snappy/snappy-c.cc +0 -0
  148. /data/ext/cache/snappy/{585305c8dbb8f762f2c2e17f937f1cf3ac6cbc9c → 3cde171792b3607f75c14e5011eaf69da4857bd8}/snappy/snappy-c.h +0 -0
  149. /data/ext/cache/snappy/{585305c8dbb8f762f2c2e17f937f1cf3ac6cbc9c → 3cde171792b3607f75c14e5011eaf69da4857bd8}/snappy/snappy-internal.h +0 -0
  150. /data/ext/cache/snappy/{585305c8dbb8f762f2c2e17f937f1cf3ac6cbc9c → 3cde171792b3607f75c14e5011eaf69da4857bd8}/snappy/snappy-sinksource.cc +0 -0
  151. /data/ext/cache/snappy/{585305c8dbb8f762f2c2e17f937f1cf3ac6cbc9c → 3cde171792b3607f75c14e5011eaf69da4857bd8}/snappy/snappy-sinksource.h +0 -0
  152. /data/ext/cache/snappy/{585305c8dbb8f762f2c2e17f937f1cf3ac6cbc9c → 3cde171792b3607f75c14e5011eaf69da4857bd8}/snappy/snappy-stubs-internal.cc +0 -0
  153. /data/ext/cache/snappy/{585305c8dbb8f762f2c2e17f937f1cf3ac6cbc9c → 3cde171792b3607f75c14e5011eaf69da4857bd8}/snappy/snappy-stubs-internal.h +0 -0
  154. /data/ext/cache/snappy/{585305c8dbb8f762f2c2e17f937f1cf3ac6cbc9c → 3cde171792b3607f75c14e5011eaf69da4857bd8}/snappy/snappy-stubs-public.h.in +0 -0
  155. /data/ext/cache/snappy/{585305c8dbb8f762f2c2e17f937f1cf3ac6cbc9c → 3cde171792b3607f75c14e5011eaf69da4857bd8}/snappy/snappy.h +0 -0
@@ -0,0 +1,59 @@
1
+ /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Copyright 2024-Present Couchbase, Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
6
+ * except in compliance with the License. You may obtain a copy of the License at
7
+ *
8
+ * https://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software distributed under
11
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
12
+ * ANY KIND, either express or implied. See the License for the specific language governing
13
+ * permissions and limitations under the License.
14
+ */
15
+
16
+ #pragma once
17
+
18
+ #include "config_listener.hxx"
19
+
20
+ #include <memory>
21
+
22
+ namespace asio
23
+ {
24
+ class io_context;
25
+ namespace ssl
26
+ {
27
+ class context;
28
+ } // namespace ssl
29
+ } // namespace asio
30
+
31
+ namespace couchbase::core
32
+ {
33
+ class app_telemetry_reporter_impl;
34
+ class app_telemetry_meter;
35
+ struct cluster_options;
36
+ struct cluster_credentials;
37
+
38
+ class app_telemetry_reporter : public config_listener
39
+ {
40
+ public:
41
+ app_telemetry_reporter() = delete;
42
+ app_telemetry_reporter(app_telemetry_reporter&&) = default;
43
+ app_telemetry_reporter(const app_telemetry_reporter&) = delete;
44
+ auto operator=(app_telemetry_reporter&&) -> app_telemetry_reporter& = default;
45
+ auto operator=(const app_telemetry_reporter&) -> app_telemetry_reporter& = delete;
46
+
47
+ app_telemetry_reporter(std::shared_ptr<app_telemetry_meter> meter,
48
+ const cluster_options& options,
49
+ const cluster_credentials& credentials,
50
+ asio::io_context& ctx,
51
+ asio::ssl::context& tls);
52
+ ~app_telemetry_reporter() override;
53
+ void update_config(topology::configuration config) override;
54
+ void stop();
55
+
56
+ private:
57
+ std::shared_ptr<app_telemetry_reporter_impl> impl_{};
58
+ };
59
+ } // namespace couchbase::core
@@ -18,6 +18,7 @@
18
18
  #include "bucket.hxx"
19
19
 
20
20
  #include "collection_id_cache_entry.hxx"
21
+ #include "core/app_telemetry_meter.hxx"
21
22
  #include "core/config_listener.hxx"
22
23
  #include "core/document_id.hxx"
23
24
  #include "core/error_context/key_value_error_map_info.hxx"
@@ -84,6 +85,7 @@ public:
84
85
  couchbase::core::origin origin,
85
86
  std::shared_ptr<tracing::tracer_wrapper> tracer,
86
87
  std::shared_ptr<metrics::meter_wrapper> meter,
88
+ std::shared_ptr<core::app_telemetry_meter> app_telemetry,
87
89
  std::vector<protocol::hello_feature> known_features,
88
90
  std::shared_ptr<impl::bootstrap_state_listener> state_listener,
89
91
  asio::io_context& ctx,
@@ -94,6 +96,7 @@ public:
94
96
  , origin_{ std::move(origin) }
95
97
  , tracer_{ std::move(tracer) }
96
98
  , meter_{ std::move(meter) }
99
+ , app_telemetry_meter_{ std::move(app_telemetry) }
97
100
  , known_features_{ std::move(known_features) }
98
101
  , state_listener_{ std::move(state_listener) }
99
102
  , codec_{ { known_features_.begin(), known_features_.end() } }
@@ -201,7 +204,10 @@ public:
201
204
  return errc::network::bucket_closed;
202
205
  }
203
206
  if (!configured_) {
204
- return defer_command([self = shared_from_this(), req]() {
207
+ return defer_command([self = shared_from_this(), req](std::error_code ec) {
208
+ if (ec == errc::common::request_canceled) {
209
+ return req->cancel(ec);
210
+ }
205
211
  self->direct_dispatch(req);
206
212
  });
207
213
  }
@@ -210,7 +216,10 @@ public:
210
216
 
211
217
  auto session = route_request(req);
212
218
  if (!session || !session->has_config()) {
213
- return defer_command([self = shared_from_this(), req]() mutable {
219
+ return defer_command([self = shared_from_this(), req](std::error_code ec) mutable {
220
+ if (ec == errc::common::request_canceled) {
221
+ return req->cancel(ec);
222
+ }
214
223
  self->direct_dispatch(std::move(req));
215
224
  });
216
225
  }
@@ -241,7 +250,10 @@ public:
241
250
 
242
251
  auto session = route_request(req);
243
252
  if (!session || !session->has_config()) {
244
- return defer_command([self = shared_from_this(), req]() {
253
+ return defer_command([self = shared_from_this(), req](std::error_code ec) {
254
+ if (ec == errc::common::request_canceled) {
255
+ return req->cancel(ec);
256
+ }
245
257
  self->direct_dispatch(req);
246
258
  });
247
259
  }
@@ -417,9 +429,16 @@ public:
417
429
  origin_.credentials(), hostname, port, origin_.options());
418
430
  io::mcbp_session session =
419
431
  origin_.options().enable_tls
420
- ? io::mcbp_session(
421
- client_id_, ctx_, tls_, origin, state_listener_, name_, known_features_)
422
- : io::mcbp_session(client_id_, ctx_, origin, state_listener_, name_, known_features_);
432
+ ? io::mcbp_session(client_id_,
433
+ node.node_uuid,
434
+ ctx_,
435
+ tls_,
436
+ origin,
437
+ state_listener_,
438
+ name_,
439
+ known_features_)
440
+ : io::mcbp_session(
441
+ client_id_, node.node_uuid, ctx_, origin, state_listener_, name_, known_features_);
423
442
  CB_LOG_DEBUG(R"({} rev={}, restart idx={}, session="{}", address="{}:{}")",
424
443
  log_prefix_,
425
444
  config_->rev_str(),
@@ -438,7 +457,7 @@ public:
438
457
  session.on_stop([id = session.id(), self]() {
439
458
  self->remove_session(id);
440
459
  });
441
- self->drain_deferred_queue();
460
+ self->drain_deferred_queue({});
442
461
  },
443
462
  true);
444
463
  sessions_.insert_or_assign(index, std::move(session));
@@ -479,8 +498,9 @@ public:
479
498
  }
480
499
  io::mcbp_session new_session =
481
500
  origin_.options().enable_tls
482
- ? io::mcbp_session(client_id_, ctx_, tls_, origin_, state_listener_, name_, known_features_)
483
- : io::mcbp_session(client_id_, ctx_, origin_, state_listener_, name_, known_features_);
501
+ ? io::mcbp_session(
502
+ client_id_, {}, ctx_, tls_, origin_, state_listener_, name_, known_features_)
503
+ : io::mcbp_session(client_id_, {}, ctx_, origin_, state_listener_, name_, known_features_);
484
504
  new_session.bootstrap([self = shared_from_this(), new_session, h = std::move(handler)](
485
505
  std::error_code ec, topology::configuration cfg) mutable {
486
506
  if (ec) {
@@ -501,7 +521,7 @@ public:
501
521
  self->sessions_.insert_or_assign(this_index, std::move(new_session));
502
522
  }
503
523
  self->update_config(cfg);
504
- self->drain_deferred_queue();
524
+ self->drain_deferred_queue({});
505
525
  self->poll_config({});
506
526
  }
507
527
  asio::post(
@@ -530,26 +550,27 @@ public:
530
550
  return handler(errc::network::configuration_not_available, nullptr);
531
551
  }
532
552
  const std::scoped_lock lock(deferred_commands_mutex_);
533
- deferred_commands_.emplace([self = shared_from_this(), handler = std::move(handler)]() mutable {
534
- if (self->closed_ || !self->configured_) {
535
- return handler(errc::network::configuration_not_available, nullptr);
536
- }
553
+ deferred_commands_.emplace(
554
+ [self = shared_from_this(), handler = std::move(handler)](std::error_code ec) mutable {
555
+ if (ec == errc::common::request_canceled || self->closed_ || !self->configured_) {
556
+ return handler(errc::network::configuration_not_available, nullptr);
557
+ }
537
558
 
538
- std::shared_ptr<topology::configuration> config{};
539
- {
540
- const std::scoped_lock config_lock(self->config_mutex_);
541
- config = self->config_;
542
- }
543
- if (config) {
544
- return handler({}, std::move(config));
545
- }
546
- return handler(errc::network::configuration_not_available, nullptr);
547
- });
559
+ std::shared_ptr<topology::configuration> config{};
560
+ {
561
+ const std::scoped_lock config_lock(self->config_mutex_);
562
+ config = self->config_;
563
+ }
564
+ if (config) {
565
+ return handler({}, config);
566
+ }
567
+ return handler(errc::network::configuration_not_available, nullptr);
568
+ });
548
569
  }
549
570
 
550
- void drain_deferred_queue()
571
+ void drain_deferred_queue(std::error_code ec)
551
572
  {
552
- std::queue<utils::movable_function<void()>> commands{};
573
+ std::queue<utils::movable_function<void(std::error_code)>> commands{};
553
574
  {
554
575
  const std::scoped_lock lock(deferred_commands_mutex_);
555
576
  std::swap(deferred_commands_, commands);
@@ -559,7 +580,7 @@ public:
559
580
  R"({} draining deferred operation queue, size={})", log_prefix_, commands.size());
560
581
  }
561
582
  while (!commands.empty()) {
562
- commands.front()();
583
+ commands.front()(ec);
563
584
  commands.pop();
564
585
  }
565
586
  }
@@ -629,7 +650,7 @@ public:
629
650
 
630
651
  heartbeat_timer_.cancel();
631
652
 
632
- drain_deferred_queue();
653
+ drain_deferred_queue(errc::common::request_canceled);
633
654
 
634
655
  if (state_listener_ != nullptr) {
635
656
  state_listener_->unregister_config_listener(shared_from_this());
@@ -793,9 +814,16 @@ public:
793
814
  origin_.credentials(), hostname, port, origin_.options());
794
815
  io::mcbp_session session =
795
816
  origin_.options().enable_tls
796
- ? io::mcbp_session(
797
- client_id_, ctx_, tls_, origin, state_listener_, name_, known_features_)
798
- : io::mcbp_session(client_id_, ctx_, origin, state_listener_, name_, known_features_);
817
+ ? io::mcbp_session(client_id_,
818
+ node.node_uuid,
819
+ ctx_,
820
+ tls_,
821
+ origin,
822
+ state_listener_,
823
+ name_,
824
+ known_features_)
825
+ : io::mcbp_session(
826
+ client_id_, node.node_uuid, ctx_, origin, state_listener_, name_, known_features_);
799
827
  CB_LOG_DEBUG(R"({} rev={}, add session="{}", address="{}:{}", index={})",
800
828
  log_prefix_,
801
829
  config.rev_str(),
@@ -822,7 +850,7 @@ public:
822
850
  session.on_stop([id = session.id(), self]() {
823
851
  self->remove_session(id);
824
852
  });
825
- self->drain_deferred_queue();
853
+ self->drain_deferred_queue({});
826
854
  },
827
855
  true);
828
856
  new_sessions.insert_or_assign(next_index, std::move(session));
@@ -901,6 +929,11 @@ public:
901
929
  return meter_;
902
930
  }
903
931
 
932
+ [[nodiscard]] auto app_telemetry_meter() const -> std::shared_ptr<core::app_telemetry_meter>
933
+ {
934
+ return app_telemetry_meter_;
935
+ }
936
+
904
937
  void export_diag_info(diag::diagnostics_result& res) const
905
938
  {
906
939
  std::map<size_t, io::mcbp_session> sessions;
@@ -937,7 +970,7 @@ public:
937
970
  config_listeners_.emplace_back(std::move(handler));
938
971
  }
939
972
 
940
- auto defer_command(utils::movable_function<void()> command) -> std::error_code
973
+ auto defer_command(utils::movable_function<void(std::error_code)> command) -> std::error_code
941
974
  {
942
975
  const std::scoped_lock lock_for_deferred_commands(deferred_commands_mutex_);
943
976
  deferred_commands_.emplace(std::move(command));
@@ -951,6 +984,7 @@ private:
951
984
  const origin origin_;
952
985
  const std::shared_ptr<tracing::tracer_wrapper> tracer_;
953
986
  const std::shared_ptr<metrics::meter_wrapper> meter_;
987
+ const std::shared_ptr<core::app_telemetry_meter> app_telemetry_meter_;
954
988
  const std::vector<protocol::hello_feature> known_features_;
955
989
  const std::shared_ptr<impl::bootstrap_state_listener> state_listener_;
956
990
  mcbp::codec codec_;
@@ -971,7 +1005,7 @@ private:
971
1005
  std::vector<std::shared_ptr<config_listener>> config_listeners_{};
972
1006
  std::mutex config_listeners_mutex_{};
973
1007
 
974
- std::queue<utils::movable_function<void()>> deferred_commands_{};
1008
+ std::queue<utils::movable_function<void(std::error_code)>> deferred_commands_{};
975
1009
  std::mutex deferred_commands_mutex_{};
976
1010
 
977
1011
  std::map<size_t, io::mcbp_session> sessions_{};
@@ -984,6 +1018,7 @@ bucket::bucket(std::string client_id,
984
1018
  asio::ssl::context& tls,
985
1019
  std::shared_ptr<tracing::tracer_wrapper> tracer,
986
1020
  std::shared_ptr<metrics::meter_wrapper> meter,
1021
+ std::shared_ptr<core::app_telemetry_meter> app_telemetry_meter,
987
1022
  std::string name,
988
1023
  couchbase::core::origin origin,
989
1024
  std::vector<protocol::hello_feature> known_features,
@@ -995,6 +1030,7 @@ bucket::bucket(std::string client_id,
995
1030
  std::move(origin),
996
1031
  std::move(tracer),
997
1032
  std::move(meter),
1033
+ std::move(app_telemetry_meter),
998
1034
  std::move(known_features),
999
1035
  std::move(state_listener),
1000
1036
  ctx,
@@ -1062,6 +1098,12 @@ bucket::meter() const -> std::shared_ptr<metrics::meter_wrapper>
1062
1098
  return impl_->meter();
1063
1099
  }
1064
1100
 
1101
+ auto
1102
+ bucket::app_telemetry_meter() const -> std::shared_ptr<core::app_telemetry_meter>
1103
+ {
1104
+ return impl_->app_telemetry_meter();
1105
+ }
1106
+
1065
1107
  auto
1066
1108
  bucket::default_retry_strategy() const -> std::shared_ptr<couchbase::retry_strategy>
1067
1109
  {
@@ -1101,7 +1143,7 @@ bucket::is_configured() const -> bool
1101
1143
  }
1102
1144
 
1103
1145
  void
1104
- bucket::defer_command(utils::movable_function<void()> command)
1146
+ bucket::defer_command(utils::movable_function<void(std::error_code)> command)
1105
1147
  {
1106
1148
  impl_->defer_command(std::move(command));
1107
1149
  }
@@ -31,9 +31,7 @@
31
31
  #include <utility>
32
32
  #include <vector>
33
33
 
34
- namespace couchbase
35
- {
36
- namespace core
34
+ namespace couchbase::core
37
35
  {
38
36
  namespace mcbp
39
37
  {
@@ -57,6 +55,8 @@ namespace impl
57
55
  class bootstrap_state_listener;
58
56
  } // namespace impl
59
57
 
58
+ class app_telemetry_meter;
59
+
60
60
  class bucket_impl;
61
61
  struct origin;
62
62
 
@@ -70,6 +70,7 @@ public:
70
70
  asio::ssl::context& tls,
71
71
  std::shared_ptr<tracing::tracer_wrapper> tracer,
72
72
  std::shared_ptr<metrics::meter_wrapper> meter,
73
+ std::shared_ptr<core::app_telemetry_meter> app_telemetry_meter,
73
74
  std::string name,
74
75
  couchbase::core::origin origin,
75
76
  std::vector<protocol::hello_feature> known_features,
@@ -95,7 +96,10 @@ public:
95
96
  if (is_configured()) {
96
97
  return map_and_send(cmd);
97
98
  }
98
- return defer_command([self = shared_from_this(), cmd]() {
99
+ return defer_command([self = shared_from_this(), cmd](std::error_code ec) {
100
+ if (ec == errc::common::request_canceled) {
101
+ return cmd->cancel(retry_reason::do_not_retry);
102
+ }
99
103
  self->map_and_send(cmd);
100
104
  });
101
105
  }
@@ -137,7 +141,10 @@ public:
137
141
  session.has_value() ? session->bootstrap_address() : "",
138
142
  session.has_value() && session->has_config(),
139
143
  config_rev());
140
- return defer_command([self = shared_from_this(), cmd]() {
144
+ return defer_command([self = shared_from_this(), cmd](std::error_code ec) {
145
+ if (ec == errc::common::request_canceled) {
146
+ return cmd->cancel(retry_reason::do_not_retry);
147
+ }
141
148
  self->map_and_send(cmd);
142
149
  });
143
150
  }
@@ -197,19 +204,20 @@ public:
197
204
  void export_diag_info(diag::diagnostics_result& res) const;
198
205
  void ping(const std::shared_ptr<diag::ping_collector>& collector,
199
206
  std::optional<std::chrono::milliseconds> timeout);
200
- void defer_command(utils::movable_function<void()> command);
207
+ void defer_command(utils::movable_function<void(std::error_code)> command);
201
208
 
202
209
  [[nodiscard]] auto name() const -> const std::string&;
203
210
  [[nodiscard]] auto log_prefix() const -> const std::string&;
204
211
  [[nodiscard]] auto tracer() const -> std::shared_ptr<tracing::tracer_wrapper>;
205
212
  [[nodiscard]] auto meter() const -> std::shared_ptr<metrics::meter_wrapper>;
213
+ [[nodiscard]] auto app_telemetry_meter() const -> std::shared_ptr<app_telemetry_meter>;
206
214
  [[nodiscard]] auto default_retry_strategy() const -> std::shared_ptr<couchbase::retry_strategy>;
207
215
  [[nodiscard]] auto is_closed() const -> bool;
208
216
  [[nodiscard]] auto is_configured() const -> bool;
209
217
 
210
218
  auto direct_dispatch(std::shared_ptr<mcbp::queue_request> req) -> std::error_code;
211
- auto direct_re_queue(const std::shared_ptr<mcbp::queue_request>& req,
212
- bool is_retry) -> std::error_code;
219
+ auto direct_re_queue(const std::shared_ptr<mcbp::queue_request>& req, bool is_retry)
220
+ -> std::error_code;
213
221
 
214
222
  private:
215
223
  [[nodiscard]] auto default_timeout() const -> std::chrono::milliseconds;
@@ -223,5 +231,4 @@ private:
223
231
  asio::io_context& ctx_;
224
232
  std::shared_ptr<bucket_impl> impl_;
225
233
  };
226
- } // namespace core
227
- } // namespace couchbase
234
+ } // namespace couchbase::core
@@ -21,6 +21,8 @@
21
21
 
22
22
  #include "bucket.hxx"
23
23
  #include "capella_ca.hxx"
24
+ #include "core/app_telemetry_meter.hxx"
25
+ #include "core/app_telemetry_reporter.hxx"
24
26
  #include "core/diagnostics.hxx"
25
27
  #include "core/impl/get_replica.hxx"
26
28
  #include "core/impl/lookup_in_replica.hxx"
@@ -444,13 +446,22 @@ public:
444
446
  }
445
447
  }
446
448
 
447
- b = std::make_shared<bucket>(
448
- id_, ctx_, tls_, tracer_, meter_, bucket_name, origin, known_features, dns_srv_tracker_);
449
+ b = std::make_shared<bucket>(id_,
450
+ ctx_,
451
+ tls_,
452
+ tracer_,
453
+ meter_,
454
+ app_telemetry_meter_,
455
+ bucket_name,
456
+ origin,
457
+ known_features,
458
+ dns_srv_tracker_);
449
459
  buckets_.try_emplace(bucket_name, b);
450
460
 
451
461
  // Register the tracer & the meter for config updates to track Cluster name & UUID
452
462
  b->on_configuration_update(tracer_);
453
463
  b->on_configuration_update(meter_);
464
+ b->on_configuration_update(app_telemetry_reporter_);
454
465
  }
455
466
  }
456
467
  if (b == nullptr) {
@@ -766,9 +777,9 @@ public:
766
777
  });
767
778
  }
768
779
  }
769
- session_ = io::mcbp_session(id_, ctx_, tls_, origin_, dns_srv_tracker_);
780
+ session_ = io::mcbp_session(id_, {}, ctx_, tls_, origin_, dns_srv_tracker_);
770
781
  } else {
771
- session_ = io::mcbp_session(id_, ctx_, origin_, dns_srv_tracker_);
782
+ session_ = io::mcbp_session(id_, {}, ctx_, origin_, dns_srv_tracker_);
772
783
  }
773
784
  session_->bootstrap([self = shared_from_this(), handler = std::move(handler)](
774
785
  std::error_code ec, const topology::configuration& config) mutable {
@@ -793,8 +804,12 @@ public:
793
804
  self->origin_.options().network,
794
805
  utils::join_strings(self->origin_.get_nodes(), ","));
795
806
  }
807
+ // FIXME(SA): fix the session manager to receive initial configuration and cluster-wide
808
+ // session to poll for updates like the bucket does. Or just subscribe before the bootstrap.
796
809
  self->session_manager_->set_configuration(config, self->origin_.options());
797
810
  self->session_->on_configuration_update(self->session_manager_);
811
+ self->session_->on_configuration_update(self->app_telemetry_reporter_);
812
+ self->app_telemetry_reporter_->update_config(config);
798
813
  self->session_->on_stop([self]() {
799
814
  if (self->session_) {
800
815
  self->session_.reset();
@@ -972,6 +987,8 @@ public:
972
987
  } else {
973
988
  self->session_manager_->set_configuration(cfg, options);
974
989
  self->config_tracker_->on_configuration_update(self->session_manager_);
990
+ self->config_tracker_->on_configuration_update(self->app_telemetry_reporter_);
991
+ self->app_telemetry_reporter_->update_config(cfg);
975
992
  self->config_tracker_->register_state_listener();
976
993
  }
977
994
  });
@@ -1092,9 +1109,8 @@ public:
1092
1109
  stopped_ = true;
1093
1110
  asio::post(asio::bind_executor(
1094
1111
  ctx_, [self = shared_from_this(), handler = std::move(handler)]() mutable {
1095
- if (self->session_) {
1096
- self->session_->stop(retry_reason::do_not_retry);
1097
- self->session_.reset();
1112
+ if (auto session = std::move(self->session_); session) {
1113
+ session->stop(retry_reason::do_not_retry);
1098
1114
  }
1099
1115
  #ifdef COUCHBASE_CXX_CLIENT_COLUMNAR
1100
1116
  if (self->config_tracker_) {
@@ -1104,19 +1120,31 @@ public:
1104
1120
  }
1105
1121
  self->retry_backoff_.cancel();
1106
1122
  #endif
1107
- self->for_each_bucket([](const auto& bucket) {
1123
+
1124
+ std::map<std::string, std::shared_ptr<bucket>> buckets{};
1125
+ {
1126
+ const std::scoped_lock lock(self->buckets_mutex_);
1127
+ buckets = std::move(self->buckets_);
1128
+ }
1129
+ for (const auto& [_, bucket] : buckets) {
1108
1130
  bucket->close();
1109
- });
1110
- self->session_manager_->close();
1131
+ }
1132
+ if (auto session_manager = std::move(self->session_manager_); session_manager) {
1133
+ session_manager->close();
1134
+ }
1111
1135
  self->work_.reset();
1112
- if (self->tracer_) {
1113
- self->tracer_->stop();
1136
+ if (auto tracer = std::move(self->tracer_); tracer) {
1137
+ tracer->stop();
1138
+ }
1139
+ if (auto meter = std::move(self->meter_); meter) {
1140
+ meter->stop();
1141
+ }
1142
+ if (auto meter = std::move(self->app_telemetry_meter_); meter) {
1143
+ meter->disable();
1114
1144
  }
1115
- self->tracer_.reset();
1116
- if (self->meter_) {
1117
- self->meter_->stop();
1145
+ if (auto reporter = std::move(self->app_telemetry_reporter_); reporter) {
1146
+ reporter->stop();
1118
1147
  }
1119
- self->meter_.reset();
1120
1148
  handler();
1121
1149
  }));
1122
1150
  }
@@ -1210,6 +1238,11 @@ private:
1210
1238
 
1211
1239
  session_manager_->set_tracer(tracer_);
1212
1240
  session_manager_->set_meter(meter_);
1241
+
1242
+ app_telemetry_meter_->update_agent(origin_.options().user_agent_extra);
1243
+ session_manager_->set_app_telemetry_meter(app_telemetry_meter_);
1244
+ app_telemetry_reporter_ = std::make_shared<app_telemetry_reporter>(
1245
+ app_telemetry_meter_, origin_.options(), origin_.credentials(), ctx_, tls_);
1213
1246
  }
1214
1247
 
1215
1248
  std::string id_{ uuid::to_string(uuid::random()) };
@@ -1217,6 +1250,7 @@ private:
1217
1250
  asio::executor_work_guard<asio::io_context::executor_type> work_;
1218
1251
  asio::ssl::context tls_{ asio::ssl::context::tls_client };
1219
1252
  std::shared_ptr<io::http_session_manager> session_manager_;
1253
+ std::shared_ptr<app_telemetry_reporter> app_telemetry_reporter_{};
1220
1254
  std::optional<io::mcbp_session> session_{};
1221
1255
  std::shared_ptr<impl::dns_srv_tracker> dns_srv_tracker_{};
1222
1256
  std::mutex buckets_mutex_{};
@@ -1225,6 +1259,10 @@ private:
1225
1259
  std::shared_ptr<tracing::tracer_wrapper> tracer_{ nullptr };
1226
1260
  std::shared_ptr<metrics::meter_wrapper> meter_{ nullptr };
1227
1261
  std::atomic_bool stopped_{ false };
1262
+ std::shared_ptr<core::app_telemetry_meter> app_telemetry_meter_{
1263
+ std::make_shared<core::app_telemetry_meter>()
1264
+ };
1265
+
1228
1266
  #ifdef COUCHBASE_CXX_CLIENT_COLUMNAR
1229
1267
  std::shared_ptr<couchbase::core::io::cluster_config_tracker> config_tracker_{};
1230
1268
  asio::steady_timer retry_backoff_;
@@ -0,0 +1,27 @@
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
+ #include "cluster_credentials.hxx"
19
+
20
+ namespace couchbase::core
21
+ {
22
+ auto
23
+ cluster_credentials::uses_certificate() const -> bool
24
+ {
25
+ return !certificate_path.empty();
26
+ }
27
+ } // namespace couchbase::core
@@ -0,0 +1,36 @@
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 <optional>
21
+ #include <string>
22
+ #include <vector>
23
+
24
+ namespace couchbase::core
25
+ {
26
+ struct cluster_credentials {
27
+ std::string username{};
28
+ std::string password{};
29
+ std::string certificate_path{};
30
+ std::string key_path{};
31
+ std::optional<std::vector<std::string>> allowed_sasl_mechanisms{};
32
+
33
+ [[nodiscard]] auto uses_certificate() const -> bool;
34
+ };
35
+
36
+ } // namespace couchbase::core
@@ -95,6 +95,18 @@ public:
95
95
  bool dump_configuration{ false };
96
96
  bool disable_mozilla_ca_certificates{ false };
97
97
  couchbase::core::columnar::security_options security_options{};
98
+
99
+ bool enable_app_telemetry{ true };
100
+ std::string app_telemetry_endpoint{};
101
+ std::chrono::milliseconds app_telemetry_ping_interval{
102
+ timeout_defaults::app_telemetry_ping_interval
103
+ };
104
+ std::chrono::milliseconds app_telemetry_ping_timeout{
105
+ timeout_defaults::app_telemetry_ping_timeout
106
+ };
107
+ std::chrono::milliseconds app_telemetry_backoff_interval{
108
+ timeout_defaults::app_telemetry_backoff_interval
109
+ };
98
110
  };
99
111
 
100
112
  } // namespace couchbase::core
@@ -166,9 +166,8 @@ public:
166
166
  {
167
167
  }
168
168
 
169
- auto get_and_maybe_insert(std::string scope_name,
170
- std::string collection_name,
171
- std::uint32_t id) -> std::shared_ptr<collection_id_cache_entry>
169
+ auto get_and_maybe_insert(std::string scope_name, std::string collection_name, std::uint32_t id)
170
+ -> std::shared_ptr<collection_id_cache_entry>
172
171
  {
173
172
  const std::scoped_lock lock(cache_mutex_);
174
173
  auto key = build_key(scope_name, collection_name);
@@ -298,8 +297,8 @@ public:
298
297
  return req;
299
298
  }
300
299
 
301
- auto direct_re_queue(std::shared_ptr<mcbp::queue_request> request,
302
- bool is_retry) -> std::error_code
300
+ auto direct_re_queue(std::shared_ptr<mcbp::queue_request> request, bool is_retry)
301
+ -> std::error_code
303
302
  {
304
303
  return dispatcher_.direct_re_queue(std::move(request), is_retry);
305
304
  }
@@ -455,6 +454,9 @@ collection_id_cache_entry_impl::refresh_collection_id(
455
454
  self->manager_.lock()->direct_re_queue(r, false);
456
455
  });
457
456
  });
457
+ #if defined(__clang__) && defined(__clang_analyzer__)
458
+ [[clang::suppress]]
459
+ #endif
458
460
  // TODO(CXXCBC-549)
459
461
  // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
460
462
  if (op) {