couchbase 3.4.3 → 3.4.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +2 -2
- data/ext/couchbase/CMakeLists.txt +15 -1
- data/ext/couchbase/core/bucket.cxx +183 -152
- data/ext/couchbase/core/bucket.hxx +17 -4
- data/ext/couchbase/core/cluster.hxx +34 -13
- data/ext/couchbase/core/cluster_options.hxx +3 -0
- data/ext/couchbase/core/crud_component.cxx +51 -22
- data/ext/couchbase/core/error_context/key_value.cxx +2 -1
- data/ext/couchbase/core/error_context/key_value.hxx +10 -12
- data/ext/couchbase/core/impl/build_deferred_query_indexes.cxx +115 -50
- data/ext/couchbase/core/impl/cluster.cxx +6 -0
- data/ext/couchbase/core/impl/create_bucket.cxx +155 -0
- data/ext/couchbase/core/impl/create_query_index.cxx +172 -59
- data/ext/couchbase/core/impl/dns_srv_tracker.cxx +2 -1
- data/ext/couchbase/core/impl/drop_bucket.cxx +66 -0
- data/ext/couchbase/core/impl/drop_query_index.cxx +138 -59
- data/ext/couchbase/core/impl/flush_bucket.cxx +66 -0
- data/ext/couchbase/core/impl/get_all_buckets.cxx +163 -0
- data/ext/couchbase/core/impl/get_all_query_indexes.cxx +67 -37
- data/ext/couchbase/core/impl/get_bucket.cxx +153 -0
- data/ext/couchbase/core/impl/internal_manager_error_context.cxx +113 -0
- data/ext/couchbase/core/impl/internal_manager_error_context.hxx +60 -0
- data/ext/couchbase/core/impl/key_value_error_category.cxx +2 -4
- data/ext/couchbase/core/impl/key_value_error_context.cxx +98 -0
- data/ext/couchbase/core/impl/lookup_in.cxx +1 -0
- data/ext/couchbase/core/impl/lookup_in_all_replicas.cxx +176 -0
- data/ext/couchbase/core/impl/lookup_in_all_replicas.hxx +80 -0
- data/ext/couchbase/core/impl/lookup_in_any_replica.cxx +167 -0
- data/ext/couchbase/core/impl/lookup_in_any_replica.hxx +75 -0
- data/ext/couchbase/core/impl/lookup_in_replica.cxx +97 -0
- data/ext/couchbase/core/impl/lookup_in_replica.hxx +67 -0
- data/ext/couchbase/core/impl/manager_error_context.cxx +100 -0
- data/ext/couchbase/core/impl/query.cxx +1 -0
- data/ext/couchbase/core/impl/query_error_context.cxx +75 -0
- data/ext/couchbase/core/impl/update_bucket.cxx +130 -0
- data/ext/couchbase/core/impl/watch_query_indexes.cxx +53 -29
- data/ext/couchbase/core/io/dns_client.cxx +111 -40
- data/ext/couchbase/core/io/dns_config.cxx +5 -4
- data/ext/couchbase/core/io/http_session.hxx +24 -1
- data/ext/couchbase/core/io/mcbp_command.hxx +9 -2
- data/ext/couchbase/core/io/mcbp_session.cxx +80 -43
- data/ext/couchbase/core/io/mcbp_session.hxx +4 -3
- data/ext/couchbase/core/logger/custom_rotating_file_sink.cxx +1 -1
- data/ext/couchbase/core/logger/logger.cxx +80 -20
- data/ext/couchbase/core/logger/logger.hxx +31 -0
- data/ext/couchbase/core/meta/features.hxx +25 -0
- data/ext/couchbase/core/operations/document_lookup_in_all_replicas.hxx +192 -0
- data/ext/couchbase/core/operations/document_lookup_in_any_replica.hxx +188 -0
- data/ext/couchbase/core/operations/document_query.cxx +11 -0
- data/ext/couchbase/core/operations/document_query.hxx +1 -0
- data/ext/couchbase/core/operations.hxx +2 -0
- data/ext/couchbase/core/origin.cxx +270 -0
- data/ext/couchbase/core/origin.hxx +2 -0
- data/ext/couchbase/core/protocol/client_response.hxx +1 -0
- data/ext/couchbase/core/protocol/cmd_hello.hxx +1 -0
- data/ext/couchbase/core/protocol/cmd_lookup_in_replica.cxx +107 -0
- data/ext/couchbase/core/protocol/cmd_lookup_in_replica.hxx +137 -0
- data/ext/couchbase/core/protocol/hello_feature.hxx +6 -0
- data/ext/couchbase/core/protocol/hello_feature_fmt.hxx +3 -0
- data/ext/couchbase/core/protocol/status.cxx +2 -2
- data/ext/couchbase/core/range_scan_options.cxx +3 -27
- data/ext/couchbase/core/range_scan_options.hxx +13 -17
- data/ext/couchbase/core/range_scan_orchestrator.cxx +388 -170
- data/ext/couchbase/core/range_scan_orchestrator.hxx +13 -2
- data/ext/couchbase/core/range_scan_orchestrator_options.hxx +5 -3
- data/ext/couchbase/core/scan_options.hxx +0 -19
- data/ext/couchbase/core/scan_result.cxx +19 -5
- data/ext/couchbase/core/scan_result.hxx +5 -2
- data/ext/couchbase/core/timeout_defaults.hxx +2 -3
- data/ext/couchbase/core/topology/capabilities.hxx +3 -0
- data/ext/couchbase/core/topology/capabilities_fmt.hxx +8 -0
- data/ext/couchbase/core/topology/collections_manifest_fmt.hxx +1 -1
- data/ext/couchbase/core/topology/configuration.hxx +15 -0
- data/ext/couchbase/core/topology/configuration_json.hxx +6 -1
- data/ext/couchbase/core/utils/connection_string.cxx +62 -47
- data/ext/couchbase/core/utils/connection_string.hxx +1 -0
- data/ext/couchbase/couchbase/analytics_error_context.hxx +1 -1
- data/ext/couchbase/couchbase/behavior_options.hxx +19 -2
- data/ext/couchbase/couchbase/bucket_manager.hxx +135 -0
- data/ext/couchbase/couchbase/build_query_index_options.hxx +0 -30
- data/ext/couchbase/couchbase/cluster.hxx +14 -0
- data/ext/couchbase/couchbase/collection.hxx +111 -0
- data/ext/couchbase/couchbase/collection_query_index_manager.hxx +7 -48
- data/ext/couchbase/couchbase/create_bucket_options.hxx +41 -0
- data/ext/couchbase/couchbase/create_primary_query_index_options.hxx +0 -29
- data/ext/couchbase/couchbase/create_query_index_options.hxx +0 -33
- data/ext/couchbase/couchbase/drop_bucket_options.hxx +41 -0
- data/ext/couchbase/couchbase/drop_primary_query_index_options.hxx +0 -30
- data/ext/couchbase/couchbase/drop_query_index_options.hxx +0 -31
- data/ext/couchbase/couchbase/error_codes.hxx +1 -2
- data/ext/couchbase/couchbase/error_context.hxx +10 -2
- data/ext/couchbase/couchbase/flush_bucket_options.hxx +41 -0
- data/ext/couchbase/{core/topology/error_map_fmt.hxx → couchbase/fmt/key_value_error_map_attribute.hxx} +21 -21
- data/ext/couchbase/couchbase/get_all_buckets_options.hxx +44 -0
- data/ext/couchbase/couchbase/get_all_query_indexes_options.hxx +0 -30
- data/ext/couchbase/couchbase/get_and_lock_options.hxx +2 -2
- data/ext/couchbase/couchbase/get_and_touch_options.hxx +2 -2
- data/ext/couchbase/couchbase/get_bucket_options.hxx +43 -0
- data/ext/couchbase/couchbase/get_options.hxx +2 -2
- data/ext/couchbase/couchbase/insert_options.hxx +3 -3
- data/ext/couchbase/couchbase/key_value_error_context.hxx +7 -2
- data/ext/couchbase/couchbase/lookup_in_all_replicas_options.hxx +109 -0
- data/ext/couchbase/couchbase/lookup_in_any_replica_options.hxx +101 -0
- data/ext/couchbase/couchbase/lookup_in_options.hxx +2 -2
- data/ext/couchbase/couchbase/lookup_in_replica_result.hxx +74 -0
- data/ext/couchbase/couchbase/lookup_in_result.hxx +26 -0
- data/ext/couchbase/couchbase/management/bucket_settings.hxx +116 -0
- data/ext/couchbase/couchbase/manager_error_context.hxx +29 -53
- data/ext/couchbase/couchbase/mutate_in_options.hxx +2 -2
- data/ext/couchbase/couchbase/query_error_context.hxx +3 -1
- data/ext/couchbase/couchbase/query_index_manager.hxx +16 -83
- data/ext/couchbase/couchbase/query_options.hxx +18 -0
- data/ext/couchbase/couchbase/remove_options.hxx +2 -2
- data/ext/couchbase/couchbase/replace_options.hxx +3 -3
- data/ext/couchbase/couchbase/security_options.hxx +15 -0
- data/ext/couchbase/couchbase/subdocument_error_context.hxx +4 -2
- data/ext/couchbase/couchbase/touch_options.hxx +2 -2
- data/ext/couchbase/couchbase/unlock_options.hxx +2 -2
- data/ext/couchbase/couchbase/update_bucket_options.hxx +41 -0
- data/ext/couchbase/couchbase/upsert_options.hxx +3 -3
- data/ext/couchbase/couchbase/watch_query_indexes_options.hxx +0 -31
- data/ext/couchbase/test/CMakeLists.txt +1 -0
- data/ext/couchbase/test/test_integration_collections.cxx +6 -0
- data/ext/couchbase/test/test_integration_crud.cxx +5 -0
- data/ext/couchbase/test/test_integration_examples.cxx +137 -1
- data/ext/couchbase/test/test_integration_management.cxx +709 -266
- data/ext/couchbase/test/test_integration_query.cxx +19 -7
- data/ext/couchbase/test/test_integration_range_scan.cxx +351 -112
- data/ext/couchbase/test/test_integration_search.cxx +10 -1
- data/ext/couchbase/test/test_integration_subdoc.cxx +655 -0
- data/ext/couchbase/test/test_transaction_public_async_api.cxx +13 -12
- data/ext/couchbase/test/test_transaction_public_blocking_api.cxx +27 -21
- data/ext/couchbase/test/test_unit_connection_string.cxx +29 -0
- data/ext/couchbase/test/test_unit_query.cxx +75 -0
- data/ext/couchbase.cxx +583 -29
- data/ext/revisions.rb +3 -3
- data/lib/couchbase/cluster.rb +1 -1
- data/lib/couchbase/collection.rb +108 -0
- data/lib/couchbase/collection_options.rb +100 -0
- data/lib/couchbase/errors.rb +5 -0
- data/lib/couchbase/key_value_scan.rb +125 -0
- data/lib/couchbase/options.rb +151 -0
- data/lib/couchbase/scope.rb +1 -1
- data/lib/couchbase/utils/time.rb +14 -1
- data/lib/couchbase/version.rb +1 -1
- metadata +41 -7
- data/ext/couchbase/core/impl/collection_query_index_manager.cxx +0 -93
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b3c1e2edfe7f74eb3f3094dd526e7dc1896f3002caca935ddeb76923b593f341
|
4
|
+
data.tar.gz: b5409f7083156b38aee870037ce0c5d3a14dc7ffe3aa3ac64b5862245b47e4d5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 16705649dc3954db461a7f8a63ee1168a4b191cacb0744e4e5b5b7b110788491d42fab78611b4898078a0276bbe0d9930352e24b4f95db87ab79ed6b6e8f9101
|
7
|
+
data.tar.gz: 157af7be99dc745ef7d95ef45490c0025f16ead6abb2f75079188405e82fcec9a64abb681695720e9080fd36b3c17883a56f84bafd06062e56c22ad9286c7ed4
|
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
[![license](https://img.shields.io/github/license/couchbase/couchbase-ruby-client?color=brightgreen)](https://opensource.org/licenses/Apache-2.0)
|
4
4
|
[![gem](https://img.shields.io/gem/v/couchbase?color=brightgreen)](https://rubygems.org/gems/couchbase)
|
5
|
-
[![commits](https://img.shields.io/github/commits-since/couchbase/couchbase-ruby-client/latest?color=brightgreen)](https://github.com/couchbase/couchbase-ruby-client/commits/
|
5
|
+
[![commits](https://img.shields.io/github/commits-since/couchbase/couchbase-ruby-client/latest?color=brightgreen)](https://github.com/couchbase/couchbase-ruby-client/commits/main)
|
6
6
|
[![linters](https://img.shields.io/github/actions/workflow/status/couchbase/couchbase-ruby-client/linters.yml?branch=main&label=linters)](https://github.com/couchbase/couchbase-ruby-client/actions?query=workflow%3Alinters)
|
7
7
|
|
8
8
|
This repository contains the third generation of the official Couchbase SDK for Ruby (aka. SDKv3)
|
@@ -23,7 +23,7 @@ The library has been tested with MRI 3.0, 3.1 and 3.2. Supported platforms are L
|
|
23
23
|
Add this line to your application's Gemfile:
|
24
24
|
|
25
25
|
```ruby
|
26
|
-
gem "couchbase", "3.4.
|
26
|
+
gem "couchbase", "3.4.4"
|
27
27
|
```
|
28
28
|
|
29
29
|
And then execute:
|
@@ -100,6 +100,7 @@ set(couchbase_cxx_client_FILES
|
|
100
100
|
core/free_form_http_request.cxx
|
101
101
|
core/key_value_config.cxx
|
102
102
|
core/n1ql_query_options.cxx
|
103
|
+
core/origin.cxx
|
103
104
|
core/range_scan_options.cxx
|
104
105
|
core/range_scan_orchestrator.cxx
|
105
106
|
core/retry_orchestrator.cxx
|
@@ -232,6 +233,7 @@ set(couchbase_cxx_client_FILES
|
|
232
233
|
core/protocol/cmd_increment.cxx
|
233
234
|
core/protocol/cmd_insert.cxx
|
234
235
|
core/protocol/cmd_lookup_in.cxx
|
236
|
+
core/protocol/cmd_lookup_in_replica.cxx
|
235
237
|
core/protocol/cmd_mutate_in.cxx
|
236
238
|
core/protocol/cmd_noop.cxx
|
237
239
|
core/protocol/cmd_observe_seqno.cxx
|
@@ -265,10 +267,10 @@ set(couchbase_cxx_client_FILES
|
|
265
267
|
core/impl/boolean_query.cxx
|
266
268
|
core/impl/build_deferred_query_indexes.cxx
|
267
269
|
core/impl/cluster.cxx
|
268
|
-
core/impl/collection_query_index_manager.cxx
|
269
270
|
core/impl/common_error_category.cxx
|
270
271
|
core/impl/configuration_profiles_registry.cxx
|
271
272
|
core/impl/conjunction_query.cxx
|
273
|
+
core/impl/create_bucket.cxx
|
272
274
|
core/impl/create_query_index.cxx
|
273
275
|
core/impl/date_range.cxx
|
274
276
|
core/impl/date_range_facet.cxx
|
@@ -277,24 +279,29 @@ set(couchbase_cxx_client_FILES
|
|
277
279
|
core/impl/decrement.cxx
|
278
280
|
core/impl/disjunction_query.cxx
|
279
281
|
core/impl/dns_srv_tracker.cxx
|
282
|
+
core/impl/drop_bucket.cxx
|
280
283
|
core/impl/drop_query_index.cxx
|
281
284
|
core/impl/exists.cxx
|
282
285
|
core/impl/expiry.cxx
|
283
286
|
core/impl/fail_fast_retry_strategy.cxx
|
284
287
|
core/impl/field_level_encryption_error_category.cxx
|
288
|
+
core/impl/flush_bucket.cxx
|
285
289
|
core/impl/geo_bounding_box_query.cxx
|
286
290
|
core/impl/geo_distance_query.cxx
|
287
291
|
core/impl/geo_polygon_query.cxx
|
288
292
|
core/impl/get.cxx
|
293
|
+
core/impl/get_all_buckets.cxx
|
289
294
|
core/impl/get_all_query_indexes.cxx
|
290
295
|
core/impl/get_all_replicas.cxx
|
291
296
|
core/impl/get_and_lock.cxx
|
292
297
|
core/impl/get_and_touch.cxx
|
293
298
|
core/impl/get_any_replica.cxx
|
299
|
+
core/impl/get_bucket.cxx
|
294
300
|
core/impl/get_replica.cxx
|
295
301
|
core/impl/increment.cxx
|
296
302
|
core/impl/insert.cxx
|
297
303
|
core/impl/internal_date_range_facet_result.cxx
|
304
|
+
core/impl/internal_manager_error_context.cxx
|
298
305
|
core/impl/internal_numeric_range_facet_result.cxx
|
299
306
|
core/impl/internal_search_error_context.cxx
|
300
307
|
core/impl/internal_search_meta_data.cxx
|
@@ -303,8 +310,13 @@ set(couchbase_cxx_client_FILES
|
|
303
310
|
core/impl/internal_search_row_locations.cxx
|
304
311
|
core/impl/internal_term_facet_result.cxx
|
305
312
|
core/impl/key_value_error_category.cxx
|
313
|
+
core/impl/key_value_error_context.cxx
|
306
314
|
core/impl/lookup_in.cxx
|
315
|
+
core/impl/lookup_in_replica.cxx
|
316
|
+
core/impl/lookup_in_all_replicas.cxx
|
317
|
+
core/impl/lookup_in_any_replica.cxx
|
307
318
|
core/impl/management_error_category.cxx
|
319
|
+
core/impl/manager_error_context.cxx
|
308
320
|
core/impl/match_all_query.cxx
|
309
321
|
core/impl/match_none_query.cxx
|
310
322
|
core/impl/match_phrase_query.cxx
|
@@ -322,6 +334,7 @@ set(couchbase_cxx_client_FILES
|
|
322
334
|
core/impl/prepend.cxx
|
323
335
|
core/impl/query.cxx
|
324
336
|
core/impl/query_error_category.cxx
|
337
|
+
core/impl/query_error_context.cxx
|
325
338
|
core/impl/query_string_query.cxx
|
326
339
|
core/impl/regexp_query.cxx
|
327
340
|
core/impl/remove.cxx
|
@@ -366,6 +379,7 @@ set(couchbase_cxx_client_FILES
|
|
366
379
|
core/impl/transaction_get_result.cxx
|
367
380
|
core/impl/transaction_op_error_category.cxx
|
368
381
|
core/impl/unlock.cxx
|
382
|
+
core/impl/update_bucket.cxx
|
369
383
|
core/impl/upsert.cxx
|
370
384
|
core/impl/view_error_category.cxx
|
371
385
|
core/impl/watch_query_indexes.cxx
|
@@ -22,7 +22,6 @@
|
|
22
22
|
#include "core/mcbp/codec.hxx"
|
23
23
|
#include "dispatcher.hxx"
|
24
24
|
#include "impl/bootstrap_state_listener.hxx"
|
25
|
-
#include "mcbp/completion_token.hxx"
|
26
25
|
#include "mcbp/operation_queue.hxx"
|
27
26
|
#include "mcbp/queue_request.hxx"
|
28
27
|
#include "mcbp/queue_response.hxx"
|
@@ -41,28 +40,6 @@
|
|
41
40
|
|
42
41
|
namespace couchbase::core
|
43
42
|
{
|
44
|
-
/**
|
45
|
-
* copies nodes from rhs that are not in lhs to output vector
|
46
|
-
*/
|
47
|
-
static void
|
48
|
-
diff_nodes(const std::vector<topology::configuration::node>& lhs,
|
49
|
-
const std::vector<topology::configuration::node>& rhs,
|
50
|
-
std::vector<topology::configuration::node>& output)
|
51
|
-
{
|
52
|
-
for (const auto& re : rhs) {
|
53
|
-
bool known = false;
|
54
|
-
for (const auto& le : lhs) {
|
55
|
-
if (le.hostname == re.hostname && le.services_plain.management.value_or(0) == re.services_plain.management.value_or(0)) {
|
56
|
-
known = true;
|
57
|
-
break;
|
58
|
-
}
|
59
|
-
}
|
60
|
-
if (!known) {
|
61
|
-
output.push_back(re);
|
62
|
-
}
|
63
|
-
}
|
64
|
-
}
|
65
|
-
|
66
43
|
class bucket_impl
|
67
44
|
: public std::enable_shared_from_this<bucket_impl>
|
68
45
|
, public config_listener
|
@@ -303,82 +280,111 @@ class bucket_impl
|
|
303
280
|
return config_->map_key(key, node_index);
|
304
281
|
}
|
305
282
|
|
306
|
-
void
|
283
|
+
void restart_sessions()
|
307
284
|
{
|
308
|
-
|
309
|
-
|
310
|
-
log_prefix_,
|
311
|
-
index,
|
312
|
-
hostname,
|
313
|
-
port);
|
285
|
+
const std::scoped_lock lock(config_mutex_, sessions_mutex_);
|
286
|
+
if (!config_.has_value()) {
|
314
287
|
return;
|
315
288
|
}
|
316
|
-
{
|
317
|
-
std::scoped_lock lock(config_mutex_);
|
318
|
-
if (!config_->has_node(origin_.options().network, service_type::key_value, origin_.options().enable_tls, hostname, port)) {
|
319
|
-
CB_LOG_TRACE(
|
320
|
-
R"({} requested to restart session, but the node has been ejected from current configuration already. idx={}, network={}, address="{}:{}")",
|
321
|
-
log_prefix_,
|
322
|
-
index,
|
323
|
-
origin_.options().network,
|
324
|
-
hostname,
|
325
|
-
port);
|
326
|
-
return;
|
327
|
-
}
|
328
|
-
}
|
329
|
-
couchbase::core::origin origin(origin_.credentials(), hostname, port, origin_.options());
|
330
289
|
|
331
|
-
|
332
|
-
|
333
|
-
|
290
|
+
std::size_t kv_node_index{ 0 };
|
291
|
+
for (std::size_t index = 0; index < config_->nodes.size(); ++index) {
|
292
|
+
const auto& node = config_->nodes[index];
|
334
293
|
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
294
|
+
const auto& hostname = node.hostname_for(origin_.options().network);
|
295
|
+
auto port = node.port_or(origin_.options().network, service_type::key_value, origin_.options().enable_tls, 0);
|
296
|
+
if (port == 0) {
|
297
|
+
continue;
|
298
|
+
}
|
299
|
+
|
300
|
+
auto ptr = std::find_if(sessions_.begin(), sessions_.end(), [&hostname, &port](const auto& session) {
|
301
|
+
return session.second.bootstrap_hostname() == hostname && session.second.bootstrap_port_number() == port;
|
302
|
+
});
|
303
|
+
if (ptr != sessions_.end()) {
|
304
|
+
|
305
|
+
if (auto found_kv_node_index = ptr->first; found_kv_node_index != kv_node_index) {
|
306
|
+
if (auto current = sessions_.find(kv_node_index); current == sessions_.end()) {
|
307
|
+
CB_LOG_WARNING(R"({} KV node index mismatch: config rev={} states that address="{}:{}" should be at idx={}, )"
|
308
|
+
R"(but it is at idx={} ("{}"). Moving session to idx={}.)",
|
309
|
+
log_prefix_,
|
310
|
+
config_->rev_str(),
|
311
|
+
hostname,
|
312
|
+
port,
|
313
|
+
kv_node_index,
|
314
|
+
found_kv_node_index,
|
315
|
+
ptr->second.id(),
|
316
|
+
kv_node_index);
|
317
|
+
sessions_.insert_or_assign(kv_node_index, std::move(ptr->second));
|
318
|
+
sessions_.erase(ptr);
|
319
|
+
} else {
|
320
|
+
CB_LOG_WARNING(
|
321
|
+
R"({} KV node index mismatch: config rev={} states that address="{}:{}" should be at idx={}, )"
|
322
|
+
R"(but it is at idx={} ("{}"). Slot with idx={} is holds session with address="{}" ("{}"), swapping them.)",
|
323
|
+
log_prefix_,
|
324
|
+
config_->rev_str(),
|
325
|
+
hostname,
|
326
|
+
port,
|
327
|
+
kv_node_index,
|
328
|
+
found_kv_node_index,
|
329
|
+
ptr->second.id(),
|
330
|
+
kv_node_index,
|
331
|
+
current->second.bootstrap_address(),
|
332
|
+
current->second.id());
|
333
|
+
std::swap(current->second, ptr->second);
|
334
|
+
}
|
335
|
+
}
|
336
|
+
++kv_node_index;
|
337
|
+
continue;
|
338
|
+
}
|
339
|
+
couchbase::core::origin origin(origin_.credentials(), hostname, port, origin_.options());
|
340
|
+
io::mcbp_session session = origin_.options().enable_tls
|
341
|
+
? io::mcbp_session(client_id_, ctx_, tls_, origin, state_listener_, name_, known_features_)
|
342
|
+
: io::mcbp_session(client_id_, ctx_, origin, state_listener_, name_, known_features_);
|
343
|
+
CB_LOG_DEBUG(R"({} rev={}, restart idx={}, session="{}", address="{}:{}")",
|
349
344
|
log_prefix_,
|
350
|
-
|
351
|
-
|
345
|
+
config_->rev_str(),
|
346
|
+
node.index,
|
352
347
|
session.id(),
|
353
348
|
hostname,
|
354
349
|
port);
|
350
|
+
session.bootstrap(
|
351
|
+
[self = shared_from_this(), session](std::error_code err, topology::configuration cfg) mutable {
|
352
|
+
if (err) {
|
353
|
+
return self->remove_session(session.id());
|
354
|
+
}
|
355
|
+
self->update_config(std::move(cfg));
|
356
|
+
session.on_configuration_update(self);
|
357
|
+
session.on_stop([id = session.id(), self]() { self->remove_session(id); });
|
358
|
+
self->drain_deferred_queue();
|
359
|
+
},
|
360
|
+
true);
|
361
|
+
sessions_.insert_or_assign(index, std::move(session));
|
362
|
+
++kv_node_index;
|
355
363
|
}
|
364
|
+
}
|
356
365
|
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
});
|
366
|
+
void remove_session(const std::string& id)
|
367
|
+
{
|
368
|
+
bool found{ false };
|
369
|
+
const std::scoped_lock lock(sessions_mutex_);
|
370
|
+
for (auto ptr = sessions_.cbegin(); ptr != sessions_.cend();) {
|
371
|
+
if (ptr->second.id() == id) {
|
372
|
+
CB_LOG_DEBUG(R"({} removed session id="{}", address="{}", bootstrap_address="{}:{}")",
|
373
|
+
log_prefix_,
|
374
|
+
ptr->second.id(),
|
375
|
+
ptr->second.remote_address(),
|
376
|
+
ptr->second.bootstrap_hostname(),
|
377
|
+
ptr->second.bootstrap_port());
|
378
|
+
ptr = sessions_.erase(ptr);
|
379
|
+
found = true;
|
380
|
+
} else {
|
381
|
+
ptr = std::next(ptr);
|
382
|
+
}
|
383
|
+
}
|
376
384
|
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
true);
|
381
|
-
sessions_.insert_or_assign(index, std::move(session));
|
385
|
+
if (found) {
|
386
|
+
asio::post(asio::bind_executor(ctx_, [self = shared_from_this()]() { return self->restart_sessions(); }));
|
387
|
+
}
|
382
388
|
}
|
383
389
|
|
384
390
|
void bootstrap(utils::movable_function<void(std::error_code, topology::configuration)>&& handler)
|
@@ -393,15 +399,11 @@ class bucket_impl
|
|
393
399
|
topology::configuration cfg) mutable {
|
394
400
|
if (ec) {
|
395
401
|
CB_LOG_WARNING(R"({} failed to bootstrap session ec={}, bucket="{}")", new_session.log_prefix(), ec.message(), self->name_);
|
402
|
+
self->remove_session(new_session.id());
|
396
403
|
} else {
|
397
404
|
const std::size_t this_index = new_session.index();
|
398
405
|
new_session.on_configuration_update(self);
|
399
|
-
new_session.on_stop([
|
400
|
-
retry_reason reason) {
|
401
|
-
if (reason == retry_reason::socket_closed_while_in_flight) {
|
402
|
-
self->restart_node(this_index, hostname, port);
|
403
|
-
}
|
404
|
-
});
|
406
|
+
new_session.on_stop([id = new_session.id(), self]() { self->remove_session(id); });
|
405
407
|
|
406
408
|
{
|
407
409
|
std::scoped_lock lock(self->sessions_mutex_);
|
@@ -455,6 +457,9 @@ class bucket_impl
|
|
455
457
|
std::scoped_lock lock(deferred_commands_mutex_);
|
456
458
|
std::swap(deferred_commands_, commands);
|
457
459
|
}
|
460
|
+
if (!commands.empty()) {
|
461
|
+
CB_LOG_TRACE(R"({} draining deferred operation queue, size={})", log_prefix_, commands.size());
|
462
|
+
}
|
458
463
|
while (!commands.empty()) {
|
459
464
|
commands.front()();
|
460
465
|
commands.pop();
|
@@ -489,9 +494,33 @@ class bucket_impl
|
|
489
494
|
}
|
490
495
|
}
|
491
496
|
|
497
|
+
/**
|
498
|
+
* copies nodes from rhs that are not in lhs to output vector
|
499
|
+
*/
|
500
|
+
void diff_nodes(const std::vector<topology::configuration::node>& lhs,
|
501
|
+
const std::vector<topology::configuration::node>& rhs,
|
502
|
+
std::vector<topology::configuration::node>& output)
|
503
|
+
{
|
504
|
+
for (const auto& re : rhs) {
|
505
|
+
bool known = false;
|
506
|
+
const auto& rhost = re.hostname_for(origin_.options().network);
|
507
|
+
const auto rport = re.port_or(origin_.options().network, service_type::key_value, origin_.options().enable_tls, 0);
|
508
|
+
for (const auto& le : lhs) {
|
509
|
+
const auto& lhost = le.hostname_for(origin_.options().network);
|
510
|
+
const auto lport = le.port_or(origin_.options().network, service_type::key_value, origin_.options().enable_tls, 0);
|
511
|
+
if (rhost == lhost && rport == lport) {
|
512
|
+
known = true;
|
513
|
+
break;
|
514
|
+
}
|
515
|
+
}
|
516
|
+
if (!known) {
|
517
|
+
output.push_back(re);
|
518
|
+
}
|
519
|
+
}
|
520
|
+
}
|
521
|
+
|
492
522
|
void update_config(topology::configuration config) override
|
493
523
|
{
|
494
|
-
bool forced_config = false;
|
495
524
|
std::vector<topology::configuration::node> added{};
|
496
525
|
std::vector<topology::configuration::node> removed{};
|
497
526
|
{
|
@@ -500,7 +529,6 @@ class bucket_impl
|
|
500
529
|
CB_LOG_DEBUG("{} initialize configuration rev={}", log_prefix_, config.rev_str());
|
501
530
|
} else if (config.force) {
|
502
531
|
CB_LOG_DEBUG("{} forced to accept configuration rev={}", log_prefix_, config.rev_str());
|
503
|
-
forced_config = true;
|
504
532
|
} else if (!config.vbmap) {
|
505
533
|
CB_LOG_DEBUG("{} will not update the configuration old={} -> new={}, because new config does not have partition map",
|
506
534
|
log_prefix_,
|
@@ -533,78 +561,81 @@ class bucket_impl
|
|
533
561
|
std::scoped_lock lock(sessions_mutex_);
|
534
562
|
std::map<size_t, io::mcbp_session> new_sessions{};
|
535
563
|
|
536
|
-
|
537
|
-
std::size_t new_index = config.nodes.size() + 1;
|
538
|
-
for (const auto& node : config.nodes) {
|
539
|
-
if (session.bootstrap_hostname() == node.hostname_for(origin_.options().network) &&
|
540
|
-
session.bootstrap_port() ==
|
541
|
-
std::to_string(
|
542
|
-
node.port_or(origin_.options().network, service_type::key_value, origin_.options().enable_tls, 0))) {
|
543
|
-
new_index = node.index;
|
544
|
-
break;
|
545
|
-
}
|
546
|
-
}
|
547
|
-
if (new_index < config.nodes.size()) {
|
548
|
-
CB_LOG_DEBUG(R"({} rev={}, preserve session="{}", address="{}:{}", index={}->{})",
|
549
|
-
log_prefix_,
|
550
|
-
config.rev_str(),
|
551
|
-
session.id(),
|
552
|
-
session.bootstrap_hostname(),
|
553
|
-
session.bootstrap_port(),
|
554
|
-
index,
|
555
|
-
new_index);
|
556
|
-
new_sessions.insert_or_assign(new_index, std::move(session));
|
557
|
-
} else {
|
558
|
-
CB_LOG_DEBUG(R"({} rev={}, drop session="{}", address="{}:{}", index={})",
|
559
|
-
log_prefix_,
|
560
|
-
config.rev_str(),
|
561
|
-
session.id(),
|
562
|
-
session.bootstrap_hostname(),
|
563
|
-
session.bootstrap_port(),
|
564
|
-
index);
|
565
|
-
asio::post(asio::bind_executor(
|
566
|
-
ctx_, [session = std::move(session)]() mutable { return session.stop(retry_reason::do_not_retry); }));
|
567
|
-
}
|
568
|
-
}
|
569
|
-
|
564
|
+
std::size_t next_index{ 0 };
|
570
565
|
for (const auto& node : config.nodes) {
|
571
|
-
if (new_sessions.find(node.index) != new_sessions.end()) {
|
572
|
-
continue;
|
573
|
-
}
|
574
|
-
|
575
566
|
const auto& hostname = node.hostname_for(origin_.options().network);
|
576
567
|
auto port = node.port_or(origin_.options().network, service_type::key_value, origin_.options().enable_tls, 0);
|
577
568
|
if (port == 0) {
|
578
569
|
continue;
|
579
570
|
}
|
571
|
+
|
572
|
+
bool reused_session{ false };
|
573
|
+
for (auto it = sessions_.begin(); it != sessions_.end(); ++it) {
|
574
|
+
if (it->second.bootstrap_hostname() == hostname && it->second.bootstrap_port_number() == port) {
|
575
|
+
CB_LOG_DEBUG(R"({} rev={}, preserve session="{}", address="{}:{}", index={}->{})",
|
576
|
+
log_prefix_,
|
577
|
+
config.rev_str(),
|
578
|
+
it->second.id(),
|
579
|
+
it->second.bootstrap_hostname(),
|
580
|
+
it->second.bootstrap_port(),
|
581
|
+
it->first,
|
582
|
+
next_index);
|
583
|
+
new_sessions.insert_or_assign(next_index, std::move(it->second));
|
584
|
+
reused_session = true;
|
585
|
+
++next_index;
|
586
|
+
sessions_.erase(it);
|
587
|
+
break;
|
588
|
+
}
|
589
|
+
}
|
590
|
+
if (reused_session) {
|
591
|
+
continue;
|
592
|
+
}
|
593
|
+
|
580
594
|
couchbase::core::origin origin(origin_.credentials(), hostname, port, origin_.options());
|
581
595
|
io::mcbp_session session = origin_.options().enable_tls
|
582
596
|
? io::mcbp_session(client_id_, ctx_, tls_, origin, state_listener_, name_, known_features_)
|
583
597
|
: io::mcbp_session(client_id_, ctx_, origin, state_listener_, name_, known_features_);
|
584
|
-
CB_LOG_DEBUG(
|
585
|
-
|
598
|
+
CB_LOG_DEBUG(R"({} rev={}, add session="{}", address="{}:{}", index={})",
|
599
|
+
log_prefix_,
|
600
|
+
config.rev_str(),
|
601
|
+
session.id(),
|
602
|
+
hostname,
|
603
|
+
port,
|
604
|
+
node.index);
|
586
605
|
session.bootstrap(
|
587
|
-
[self = shared_from_this(), session,
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
}
|
598
|
-
});
|
599
|
-
self->drain_deferred_queue();
|
600
|
-
} else if (err == errc::common::unambiguous_timeout && forced_config) {
|
601
|
-
self->restart_node(idx, session.bootstrap_hostname(), session.bootstrap_port());
|
606
|
+
[self = shared_from_this(), session, idx = next_index](std::error_code err, topology::configuration cfg) mutable {
|
607
|
+
if (err) {
|
608
|
+
CB_LOG_WARNING(R"({} failed to bootstrap session="{}", address="{}:{}", index={}, ec={})",
|
609
|
+
session.log_prefix(),
|
610
|
+
session.id(),
|
611
|
+
session.bootstrap_hostname(),
|
612
|
+
session.bootstrap_port(),
|
613
|
+
idx,
|
614
|
+
err.message());
|
615
|
+
return self->remove_session(session.id());
|
602
616
|
}
|
617
|
+
self->update_config(std::move(cfg));
|
618
|
+
session.on_configuration_update(self);
|
619
|
+
session.on_stop([id = session.id(), self]() { self->remove_session(id); });
|
620
|
+
self->drain_deferred_queue();
|
603
621
|
},
|
604
622
|
true);
|
605
|
-
new_sessions.insert_or_assign(
|
623
|
+
new_sessions.insert_or_assign(next_index, std::move(session));
|
624
|
+
++next_index;
|
625
|
+
}
|
626
|
+
std::swap(sessions_, new_sessions);
|
627
|
+
|
628
|
+
for (auto it = new_sessions.begin(); it != new_sessions.end(); ++it) {
|
629
|
+
CB_LOG_DEBUG(R"({} rev={}, drop session="{}", address="{}:{}", index={})",
|
630
|
+
log_prefix_,
|
631
|
+
config.rev_str(),
|
632
|
+
it->second.id(),
|
633
|
+
it->second.bootstrap_hostname(),
|
634
|
+
it->second.bootstrap_port(),
|
635
|
+
it->first);
|
636
|
+
asio::post(asio::bind_executor(
|
637
|
+
ctx_, [session = std::move(it->second)]() mutable { return session.stop(retry_reason::do_not_retry); }));
|
606
638
|
}
|
607
|
-
sessions_ = new_sessions;
|
608
639
|
}
|
609
640
|
}
|
610
641
|
|
@@ -83,7 +83,7 @@ class bucket
|
|
83
83
|
auto cmd = std::make_shared<operations::mcbp_command<bucket, Request>>(ctx_, shared_from_this(), request, default_timeout());
|
84
84
|
cmd->start([cmd, handler = std::forward<Handler>(handler)](std::error_code ec, std::optional<io::mcbp_message>&& msg) mutable {
|
85
85
|
using encoded_response_type = typename Request::encoded_response_type;
|
86
|
-
std::uint16_t status_code = msg ? msg->header.status() :
|
86
|
+
std::uint16_t status_code = msg ? msg->header.status() : 0xffffU;
|
87
87
|
auto resp = msg ? encoded_response_type(std::move(*msg)) : encoded_response_type{};
|
88
88
|
auto ctx = make_key_value_error_context(ec, status_code, cmd, resp);
|
89
89
|
handler(cmd->request.make_response(std::move(ctx), std::move(resp)));
|
@@ -107,7 +107,7 @@ class bucket
|
|
107
107
|
auto [partition, server] = map_id(cmd->request.id);
|
108
108
|
if (!server.has_value()) {
|
109
109
|
CB_LOG_TRACE(
|
110
|
-
R"({} unable to map key
|
110
|
+
R"({} unable to map key="{}" to the node, id={}, partition={})", log_prefix(), cmd->request.id, cmd->id_, partition);
|
111
111
|
return io::retry_orchestrator::maybe_retry(
|
112
112
|
cmd->manager_, cmd, retry_reason::node_not_available, errc::common::request_canceled);
|
113
113
|
}
|
@@ -116,19 +116,32 @@ class bucket
|
|
116
116
|
}
|
117
117
|
auto session = find_session_by_index(index);
|
118
118
|
if (!session || !session->has_config()) {
|
119
|
-
CB_LOG_TRACE(R"({} defer operation id={}, session={}, has_config={})",
|
119
|
+
CB_LOG_TRACE(R"({} defer operation id={}, key="{}", partition={}, index={}, session={}, address="{}", has_config={})",
|
120
120
|
log_prefix(),
|
121
121
|
cmd->id_,
|
122
|
+
cmd->request.id,
|
123
|
+
cmd->request.partition,
|
124
|
+
index,
|
122
125
|
session.has_value(),
|
126
|
+
session.has_value() ? session->bootstrap_address() : "",
|
123
127
|
session.has_value() && session->has_config());
|
124
128
|
return defer_command([self = shared_from_this(), cmd]() { self->map_and_send(cmd); });
|
125
129
|
}
|
126
130
|
if (session->is_stopped()) {
|
127
131
|
CB_LOG_TRACE(
|
128
|
-
R"({} the session has been found, but it is stopped, retrying id={},
|
132
|
+
R"({} the session has been found for idx={}, but it is stopped, retrying id={}, key="{}", partition={}, session={}, address="{}")",
|
133
|
+
log_prefix(),
|
134
|
+
index,
|
135
|
+
cmd->id_,
|
136
|
+
cmd->request.id,
|
137
|
+
cmd->request.partition,
|
138
|
+
session->id(),
|
139
|
+
session->bootstrap_address());
|
129
140
|
return io::retry_orchestrator::maybe_retry(
|
130
141
|
cmd->manager_, cmd, retry_reason::node_not_available, errc::common::request_canceled);
|
131
142
|
}
|
143
|
+
cmd->last_dispatched_from_ = session->local_address();
|
144
|
+
cmd->last_dispatched_to_ = session->bootstrap_address();
|
132
145
|
cmd->send_to(session.value());
|
133
146
|
}
|
134
147
|
|