couchbase 3.4.2 → 3.4.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/ext/couchbase/CMakeLists.txt +57 -7
- data/ext/couchbase/cmake/Documentation.cmake +0 -1
- data/ext/couchbase/cmake/OpenSSL.cmake +98 -3
- data/ext/couchbase/cmake/Testing.cmake +12 -4
- data/ext/couchbase/cmake/build_config.hxx.in +3 -0
- data/ext/couchbase/core/bucket.cxx +3 -2
- data/ext/couchbase/core/bucket.hxx +9 -0
- data/ext/couchbase/core/cluster.hxx +17 -0
- data/ext/couchbase/core/cluster_options.cxx +2 -2
- data/ext/couchbase/core/cluster_options.hxx +4 -6
- data/ext/couchbase/core/cluster_options_fwd.hxx +26 -0
- data/ext/couchbase/core/config_profile.hxx +1 -54
- data/ext/couchbase/core/config_profiles.cxx +79 -0
- data/ext/couchbase/core/config_profiles.hxx +56 -0
- data/ext/couchbase/core/error_context/search.hxx +1 -1
- data/ext/couchbase/core/impl/analytics.cxx +1 -0
- data/ext/couchbase/core/impl/boolean_field_query.cxx +40 -0
- data/ext/couchbase/core/impl/boolean_query.cxx +62 -0
- data/ext/couchbase/core/impl/cluster.cxx +2 -0
- data/ext/couchbase/core/impl/conjunction_query.cxx +51 -0
- data/ext/couchbase/core/impl/date_range.cxx +89 -0
- data/ext/couchbase/core/impl/date_range_facet.cxx +54 -0
- data/ext/couchbase/core/impl/date_range_facet_result.cxx +64 -0
- data/ext/couchbase/core/impl/date_range_query.cxx +125 -0
- data/ext/couchbase/core/impl/disjunction_query.cxx +51 -0
- data/ext/couchbase/core/impl/encoded_search_facet.hxx +29 -0
- data/ext/couchbase/core/impl/encoded_search_query.hxx +29 -0
- data/ext/couchbase/core/impl/encoded_search_sort.hxx +29 -0
- data/ext/couchbase/core/impl/geo_bounding_box_query.cxx +46 -0
- data/ext/couchbase/core/impl/geo_distance_query.cxx +43 -0
- data/ext/couchbase/core/impl/geo_polygon_query.cxx +46 -0
- data/ext/couchbase/core/impl/internal_date_range_facet_result.cxx +80 -0
- data/ext/couchbase/core/impl/internal_date_range_facet_result.hxx +48 -0
- data/ext/couchbase/core/impl/internal_numeric_range_facet_result.cxx +80 -0
- data/ext/couchbase/core/impl/internal_numeric_range_facet_result.hxx +48 -0
- data/ext/couchbase/core/impl/internal_search_error_context.cxx +141 -0
- data/ext/couchbase/core/impl/internal_search_error_context.hxx +61 -0
- data/ext/couchbase/core/impl/internal_search_meta_data.cxx +60 -0
- data/ext/couchbase/core/impl/internal_search_meta_data.hxx +41 -0
- data/ext/couchbase/core/impl/internal_search_result.cxx +84 -0
- data/ext/couchbase/core/impl/internal_search_result.hxx +43 -0
- data/ext/couchbase/core/impl/internal_search_row.cxx +82 -0
- data/ext/couchbase/core/impl/internal_search_row.hxx +56 -0
- data/ext/couchbase/core/impl/internal_search_row_location.hxx +32 -0
- data/ext/couchbase/core/impl/internal_search_row_locations.cxx +137 -0
- data/ext/couchbase/core/impl/internal_search_row_locations.hxx +45 -0
- data/ext/couchbase/core/impl/internal_term_facet_result.cxx +80 -0
- data/ext/couchbase/core/impl/internal_term_facet_result.hxx +48 -0
- data/ext/couchbase/core/impl/match_all_query.cxx +35 -0
- data/ext/couchbase/core/impl/match_none_query.cxx +35 -0
- data/ext/couchbase/core/impl/match_phrase_query.cxx +43 -0
- data/ext/couchbase/core/impl/match_query.cxx +59 -0
- data/ext/couchbase/core/impl/numeric_range.cxx +49 -0
- data/ext/couchbase/core/impl/numeric_range_facet.cxx +54 -0
- data/ext/couchbase/core/impl/numeric_range_facet_result.cxx +64 -0
- data/ext/couchbase/core/impl/numeric_range_query.cxx +56 -0
- data/ext/couchbase/core/impl/phrase_query.cxx +42 -0
- data/ext/couchbase/core/impl/prefix_query.cxx +40 -0
- data/ext/couchbase/core/impl/query_string_query.cxx +37 -0
- data/ext/couchbase/core/impl/regexp_query.cxx +40 -0
- data/ext/couchbase/core/impl/search.cxx +191 -0
- data/ext/couchbase/core/impl/search_error_context.cxx +147 -0
- data/ext/couchbase/core/impl/search_meta_data.cxx +46 -0
- data/ext/couchbase/core/impl/search_result.cxx +66 -0
- data/ext/couchbase/core/impl/search_row.cxx +74 -0
- data/ext/couchbase/core/impl/search_row_location.cxx +64 -0
- data/ext/couchbase/core/impl/search_row_locations.cxx +66 -0
- data/ext/couchbase/core/impl/search_sort_field.cxx +104 -0
- data/ext/couchbase/core/impl/search_sort_id.cxx +43 -0
- data/ext/couchbase/core/impl/search_sort_score.cxx +43 -0
- data/ext/couchbase/core/impl/term_facet.cxx +36 -0
- data/ext/couchbase/core/impl/term_facet_result.cxx +64 -0
- data/ext/couchbase/core/impl/term_query.cxx +56 -0
- data/ext/couchbase/core/impl/term_range_query.cxx +57 -0
- data/ext/couchbase/core/impl/wildcard_query.cxx +40 -0
- data/ext/couchbase/core/io/http_context.hxx +1 -1
- data/ext/couchbase/core/io/http_session.hxx +10 -0
- data/ext/couchbase/core/io/http_session_manager.hxx +5 -3
- data/ext/couchbase/core/io/mcbp_session.cxx +28 -1
- data/ext/couchbase/core/io/retry_orchestrator.hxx +3 -2
- data/ext/couchbase/core/json_string.hxx +5 -0
- data/ext/couchbase/core/meta/version.cxx +18 -4
- data/ext/couchbase/core/mozilla_ca_bundle.hxx +39 -0
- data/ext/couchbase/core/operations/document_analytics.cxx +1 -0
- data/ext/couchbase/core/operations/document_analytics.hxx +1 -0
- data/ext/couchbase/core/operations/document_append.hxx +1 -1
- data/ext/couchbase/core/operations/document_decrement.hxx +1 -1
- data/ext/couchbase/core/operations/document_exists.hxx +1 -1
- data/ext/couchbase/core/operations/document_get.hxx +1 -1
- data/ext/couchbase/core/operations/document_get_and_lock.hxx +1 -1
- data/ext/couchbase/core/operations/document_get_and_touch.hxx +1 -1
- data/ext/couchbase/core/operations/document_get_projected.hxx +1 -1
- data/ext/couchbase/core/operations/document_increment.hxx +1 -1
- data/ext/couchbase/core/operations/document_insert.hxx +1 -1
- data/ext/couchbase/core/operations/document_lookup_in.hxx +1 -1
- data/ext/couchbase/core/operations/document_mutate_in.hxx +1 -1
- data/ext/couchbase/core/operations/document_prepend.hxx +1 -1
- data/ext/couchbase/core/operations/document_query.cxx +2 -0
- data/ext/couchbase/core/operations/document_query.hxx +6 -0
- data/ext/couchbase/core/operations/document_remove.hxx +1 -1
- data/ext/couchbase/core/operations/document_replace.hxx +1 -1
- data/ext/couchbase/core/operations/document_search.cxx +4 -1
- data/ext/couchbase/core/operations/document_search.hxx +2 -1
- data/ext/couchbase/core/operations/document_touch.hxx +1 -1
- data/ext/couchbase/core/operations/document_unlock.hxx +1 -1
- data/ext/couchbase/core/operations/document_upsert.hxx +1 -1
- data/ext/couchbase/core/operations/document_view.hxx +1 -0
- data/ext/couchbase/core/protocol/client_request.hxx +11 -2
- data/ext/couchbase/core/public_fwd.hxx +21 -0
- data/ext/couchbase/core/tls_verify_mode.hxx +26 -0
- data/ext/couchbase/core/topology/configuration.cxx +15 -2
- data/ext/couchbase/core/topology/configuration.hxx +5 -1
- data/ext/couchbase/core/transactions/attempt_context_testing_hooks.cxx +93 -0
- data/ext/couchbase/core/transactions/attempt_context_testing_hooks.hxx +48 -75
- data/ext/couchbase/core/transactions/cleanup_testing_hooks.cxx +52 -0
- data/ext/couchbase/core/transactions/cleanup_testing_hooks.hxx +17 -31
- data/ext/couchbase/core/transactions/exceptions.hxx +12 -9
- data/ext/couchbase/core/utils/connection_string.cxx +17 -0
- data/ext/couchbase/core/utils/json.cxx +4 -1
- data/ext/couchbase/couchbase/behavior_options.hxx +10 -1
- data/ext/couchbase/couchbase/boolean_field_query.hxx +77 -0
- data/ext/couchbase/couchbase/boolean_query.hxx +223 -0
- data/ext/couchbase/couchbase/cluster.hxx +42 -1
- data/ext/couchbase/couchbase/conjunction_query.hxx +88 -0
- data/ext/couchbase/couchbase/date_range.hxx +69 -0
- data/ext/couchbase/couchbase/date_range_facet.hxx +56 -0
- data/ext/couchbase/couchbase/date_range_facet_result.hxx +55 -0
- data/ext/couchbase/couchbase/date_range_query.hxx +265 -0
- data/ext/couchbase/couchbase/disjunction_query.hxx +109 -0
- data/ext/couchbase/couchbase/doc_id_query.hxx +111 -0
- data/ext/couchbase/couchbase/error_context.hxx +7 -6
- data/ext/couchbase/couchbase/fmt/analytics_scan_consistency.hxx +52 -0
- data/ext/couchbase/couchbase/fmt/search_scan_consistency.hxx +49 -0
- data/ext/couchbase/couchbase/geo_bounding_box_query.hxx +107 -0
- data/ext/couchbase/couchbase/geo_distance_query.hxx +109 -0
- data/ext/couchbase/couchbase/geo_point.hxx +32 -0
- data/ext/couchbase/couchbase/geo_polygon_query.hxx +85 -0
- data/ext/couchbase/couchbase/highlight_style.hxx +45 -0
- data/ext/couchbase/couchbase/match_all_query.hxx +43 -0
- data/ext/couchbase/couchbase/match_none_query.hxx +43 -0
- data/ext/couchbase/couchbase/match_operator.hxx +45 -0
- data/ext/couchbase/couchbase/match_phrase_query.hxx +108 -0
- data/ext/couchbase/couchbase/match_query.hxx +163 -0
- data/ext/couchbase/couchbase/numeric_range.hxx +58 -0
- data/ext/couchbase/couchbase/numeric_range_facet.hxx +56 -0
- data/ext/couchbase/couchbase/numeric_range_facet_result.hxx +55 -0
- data/ext/couchbase/couchbase/numeric_range_query.hxx +143 -0
- data/ext/couchbase/couchbase/phrase_query.hxx +93 -0
- data/ext/couchbase/couchbase/prefix_query.hxx +82 -0
- data/ext/couchbase/couchbase/query_string_query.hxx +72 -0
- data/ext/couchbase/couchbase/regexp_query.hxx +82 -0
- data/ext/couchbase/couchbase/scope.hxx +40 -0
- data/ext/couchbase/couchbase/search_date_range.hxx +68 -0
- data/ext/couchbase/couchbase/search_error_context.hxx +138 -0
- data/ext/couchbase/couchbase/search_facet.hxx +60 -0
- data/ext/couchbase/couchbase/search_facet_result.hxx +50 -0
- data/ext/couchbase/couchbase/search_meta_data.hxx +85 -0
- data/ext/couchbase/couchbase/search_metrics.hxx +127 -0
- data/ext/couchbase/couchbase/search_numeric_range.hxx +69 -0
- data/ext/couchbase/couchbase/search_options.hxx +509 -0
- data/ext/couchbase/couchbase/search_query.hxx +69 -0
- data/ext/couchbase/couchbase/search_result.hxx +77 -0
- data/ext/couchbase/couchbase/search_row.hxx +104 -0
- data/ext/couchbase/couchbase/search_row_location.hxx +55 -0
- data/ext/couchbase/couchbase/search_row_locations.hxx +86 -0
- data/ext/couchbase/couchbase/search_scan_consistency.hxx +34 -0
- data/ext/couchbase/couchbase/search_sort.hxx +58 -0
- data/ext/couchbase/couchbase/search_sort_field.hxx +117 -0
- data/ext/couchbase/couchbase/search_sort_field_missing.hxx +26 -0
- data/ext/couchbase/couchbase/search_sort_field_mode.hxx +27 -0
- data/ext/couchbase/couchbase/search_sort_field_type.hxx +28 -0
- data/ext/couchbase/couchbase/search_sort_id.hxx +60 -0
- data/ext/couchbase/couchbase/search_sort_score.hxx +60 -0
- data/ext/couchbase/couchbase/search_term_range.hxx +51 -0
- data/ext/couchbase/couchbase/security_options.hxx +3 -0
- data/ext/couchbase/couchbase/term_facet.hxx +48 -0
- data/ext/couchbase/couchbase/term_facet_result.hxx +55 -0
- data/ext/couchbase/couchbase/term_query.hxx +151 -0
- data/ext/couchbase/couchbase/term_range_query.hxx +142 -0
- data/ext/couchbase/couchbase/tracing/request_span.hxx +63 -0
- data/ext/couchbase/couchbase/tracing/request_tracer.hxx +2 -40
- data/ext/couchbase/couchbase/transactions/async_attempt_context.hxx +83 -4
- data/ext/couchbase/couchbase/transactions/attempt_context.hxx +67 -0
- data/ext/couchbase/couchbase/transactions/transaction_get_result.hxx +2 -0
- data/ext/couchbase/couchbase/transactions/transaction_keyspace.hxx +11 -1
- data/ext/couchbase/couchbase/transactions/transaction_options.hxx +79 -8
- data/ext/couchbase/couchbase/transactions/transaction_query_options.hxx +128 -15
- data/ext/couchbase/couchbase/transactions/transaction_query_result.hxx +4 -0
- data/ext/couchbase/couchbase/transactions/transaction_result.hxx +1 -1
- data/ext/couchbase/couchbase/transactions/transactions_cleanup_config.hxx +5 -3
- data/ext/couchbase/couchbase/transactions/transactions_config.hxx +9 -5
- data/ext/couchbase/couchbase/transactions/transactions_query_config.hxx +6 -3
- data/ext/couchbase/couchbase/transactions.hxx +34 -1
- data/ext/couchbase/couchbase/wildcard_query.hxx +83 -0
- data/ext/couchbase/test/CMakeLists.txt +7 -5
- data/ext/couchbase/test/benchmark_helper_integration.hxx +2 -2
- data/ext/couchbase/test/test_helper.hxx +5 -5
- data/ext/couchbase/test/test_integration_analytics.cxx +28 -6
- data/ext/couchbase/test/test_integration_collections.cxx +7 -3
- data/ext/couchbase/test/test_integration_connect.cxx +7 -3
- data/ext/couchbase/test/test_integration_crud.cxx +13 -3
- data/ext/couchbase/test/test_integration_diagnostics.cxx +11 -5
- data/ext/couchbase/test/test_integration_durability.cxx +12 -7
- data/ext/couchbase/test/test_integration_examples.cxx +283 -11
- data/ext/couchbase/test/test_integration_management.cxx +147 -91
- data/ext/couchbase/test/test_integration_query.cxx +68 -10
- data/ext/couchbase/test/test_integration_range_scan.cxx +12 -12
- data/ext/couchbase/test/test_integration_read_replica.cxx +48 -11
- data/ext/couchbase/test/test_integration_search.cxx +22 -2
- data/ext/couchbase/test/test_integration_subdoc.cxx +62 -11
- data/ext/couchbase/test/test_integration_tracer.cxx +5 -0
- data/ext/couchbase/test/test_integration_transcoders.cxx +13 -5
- data/ext/couchbase/test/{test_transaction_transaction_context.cxx → test_transaction_context.cxx} +1 -1
- data/ext/couchbase/test/test_transaction_examples.cxx +195 -0
- data/ext/couchbase/test/{test_transaction_transaction_simple.cxx → test_transaction_simple.cxx} +17 -5
- data/ext/couchbase/test/{test_transaction_transaction_simple_async.cxx → test_transaction_simple_async.cxx} +19 -21
- data/ext/couchbase/test/test_unit_config_profiles.cxx +1 -1
- data/ext/couchbase/test/test_unit_json_transcoder.cxx +4 -0
- data/ext/couchbase/test/test_unit_search.cxx +427 -0
- data/ext/couchbase/test/test_unit_transaction_utils.cxx +10 -1
- data/ext/couchbase/test/test_unit_utils.cxx +8 -4
- data/ext/couchbase.cxx +58 -16
- data/ext/revisions.rb +3 -3
- data/lib/couchbase/authenticator.rb +0 -1
- data/lib/couchbase/cluster.rb +0 -4
- data/lib/couchbase/config_profiles.rb +1 -1
- data/lib/couchbase/json_transcoder.rb +12 -5
- data/lib/couchbase/management/collection_query_index_manager.rb +54 -15
- data/lib/couchbase/management/query_index_manager.rb +70 -5
- data/lib/couchbase/raw_binary_transcoder.rb +37 -0
- data/lib/couchbase/raw_json_transcoder.rb +38 -0
- data/lib/couchbase/raw_string_transcoder.rb +40 -0
- data/lib/couchbase/search_options.rb +5 -0
- data/lib/couchbase/transcoder_flags.rb +62 -0
- data/lib/couchbase/version.rb +1 -1
- metadata +139 -11
- data/ext/couchbase/core/config_profile.cxx +0 -47
- /data/ext/couchbase/test/{test_transaction_transaction_public_async_api.cxx → test_transaction_public_async_api.cxx} +0 -0
- /data/ext/couchbase/test/{test_transaction_transaction_public_blocking_api.cxx → test_transaction_public_blocking_api.cxx} +0 -0
@@ -63,8 +63,13 @@ TEST_CASE("integration: get any replica", "[integration]")
|
|
63
63
|
{
|
64
64
|
test::utils::integration_test_guard integration;
|
65
65
|
|
66
|
-
if (integration.number_of_replicas() == 0
|
67
|
-
|
66
|
+
if (integration.number_of_replicas() == 0) {
|
67
|
+
SKIP("bucket has zero replicas");
|
68
|
+
}
|
69
|
+
if (integration.number_of_nodes() <= integration.number_of_replicas()) {
|
70
|
+
SKIP(fmt::format("number of nodes ({}) is less or equal to number of replicas ({})",
|
71
|
+
integration.number_of_nodes(),
|
72
|
+
integration.number_of_replicas()));
|
68
73
|
}
|
69
74
|
|
70
75
|
test::utils::open_bucket(integration.cluster, integration.ctx.bucket);
|
@@ -95,8 +100,12 @@ TEST_CASE("integration: get all replicas", "[integration]")
|
|
95
100
|
test::utils::integration_test_guard integration;
|
96
101
|
|
97
102
|
auto number_of_replicas = integration.number_of_replicas();
|
98
|
-
if (number_of_replicas == 0
|
99
|
-
|
103
|
+
if (number_of_replicas == 0) {
|
104
|
+
SKIP("bucket has zero replicas");
|
105
|
+
}
|
106
|
+
if (integration.number_of_nodes() <= number_of_replicas) {
|
107
|
+
SKIP(fmt::format(
|
108
|
+
"number of nodes ({}) is less or equal to number of replicas ({})", integration.number_of_nodes(), number_of_replicas));
|
100
109
|
}
|
101
110
|
|
102
111
|
test::utils::open_bucket(integration.cluster, integration.ctx.bucket);
|
@@ -109,10 +118,16 @@ TEST_CASE("integration: get all replicas", "[integration]")
|
|
109
118
|
couchbase::core::document_id id{ integration.ctx.bucket, scope_name, collection_name, key };
|
110
119
|
|
111
120
|
couchbase::core::operations::insert_request req{ id, basic_doc_json };
|
121
|
+
req.durability_level = couchbase::durability_level::majority_and_persist_to_active;
|
112
122
|
auto resp = test::utils::execute(integration.cluster, req);
|
113
123
|
REQUIRE_SUCCESS(resp.ctx.ec());
|
114
124
|
}
|
115
125
|
|
126
|
+
if (integration.cluster_version().is_mock()) {
|
127
|
+
// GOCAVES does not implement syncDurability. See https://github.com/couchbaselabs/gocaves/issues/109
|
128
|
+
std::this_thread::sleep_for(std::chrono::seconds{ 1 });
|
129
|
+
}
|
130
|
+
|
116
131
|
{
|
117
132
|
auto collection =
|
118
133
|
couchbase::cluster(integration.cluster).bucket(integration.ctx.bucket).scope(scope_name).collection(collection_name);
|
@@ -128,8 +143,13 @@ TEST_CASE("integration: get all replicas with missing key", "[integration]")
|
|
128
143
|
{
|
129
144
|
test::utils::integration_test_guard integration;
|
130
145
|
|
131
|
-
if (integration.number_of_replicas() == 0
|
132
|
-
|
146
|
+
if (integration.number_of_replicas() == 0) {
|
147
|
+
SKIP("bucket has zero replicas");
|
148
|
+
}
|
149
|
+
if (integration.number_of_nodes() <= integration.number_of_replicas()) {
|
150
|
+
SKIP(fmt::format("number of nodes ({}) is less or equal to number of replicas ({})",
|
151
|
+
integration.number_of_nodes(),
|
152
|
+
integration.number_of_replicas()));
|
133
153
|
}
|
134
154
|
|
135
155
|
test::utils::open_bucket(integration.cluster, integration.ctx.bucket);
|
@@ -152,7 +172,9 @@ TEST_CASE("integration: get any replica with missing key", "[integration]")
|
|
152
172
|
test::utils::integration_test_guard integration;
|
153
173
|
|
154
174
|
if (integration.number_of_nodes() <= integration.number_of_replicas()) {
|
155
|
-
|
175
|
+
SKIP(fmt::format("number of nodes ({}) is less or equal to number of replicas ({})",
|
176
|
+
integration.number_of_nodes(),
|
177
|
+
integration.number_of_replicas()));
|
156
178
|
}
|
157
179
|
|
158
180
|
test::utils::open_bucket(integration.cluster, integration.ctx.bucket);
|
@@ -173,8 +195,13 @@ TEST_CASE("integration: get any replica low-level version", "[integration]")
|
|
173
195
|
{
|
174
196
|
test::utils::integration_test_guard integration;
|
175
197
|
|
176
|
-
if (integration.number_of_replicas() == 0
|
177
|
-
|
198
|
+
if (integration.number_of_replicas() == 0) {
|
199
|
+
SKIP("bucket has zero replicas");
|
200
|
+
}
|
201
|
+
if (integration.number_of_nodes() <= integration.number_of_replicas()) {
|
202
|
+
SKIP(fmt::format("number of nodes ({}) is less or equal to number of replicas ({})",
|
203
|
+
integration.number_of_nodes(),
|
204
|
+
integration.number_of_replicas()));
|
178
205
|
}
|
179
206
|
|
180
207
|
test::utils::open_bucket(integration.cluster, integration.ctx.bucket);
|
@@ -204,8 +231,12 @@ TEST_CASE("integration: get all replicas low-level version", "[integration]")
|
|
204
231
|
test::utils::integration_test_guard integration;
|
205
232
|
|
206
233
|
auto number_of_replicas = integration.number_of_replicas();
|
207
|
-
if (number_of_replicas == 0
|
208
|
-
|
234
|
+
if (number_of_replicas == 0) {
|
235
|
+
SKIP("bucket has zero replicas");
|
236
|
+
}
|
237
|
+
if (integration.number_of_nodes() <= number_of_replicas) {
|
238
|
+
SKIP(fmt::format(
|
239
|
+
"number of nodes ({}) is less or equal to number of replicas ({})", integration.number_of_nodes(), number_of_replicas));
|
209
240
|
}
|
210
241
|
|
211
242
|
test::utils::open_bucket(integration.cluster, integration.ctx.bucket);
|
@@ -217,10 +248,16 @@ TEST_CASE("integration: get all replicas low-level version", "[integration]")
|
|
217
248
|
{ "b", 2.0 },
|
218
249
|
};
|
219
250
|
couchbase::core::operations::upsert_request req{ id, couchbase::core::utils::json::generate_binary(value) };
|
251
|
+
req.durability_level = couchbase::durability_level::majority_and_persist_to_active;
|
220
252
|
auto resp = test::utils::execute(integration.cluster, req);
|
221
253
|
REQUIRE_SUCCESS(resp.ctx.ec());
|
222
254
|
}
|
223
255
|
|
256
|
+
if (integration.cluster_version().is_mock()) {
|
257
|
+
// GOCAVES does not implement syncDurability. See https://github.com/couchbaselabs/gocaves/issues/109
|
258
|
+
std::this_thread::sleep_for(std::chrono::seconds{ 1 });
|
259
|
+
}
|
260
|
+
|
224
261
|
{
|
225
262
|
couchbase::core::operations::get_all_replicas_request req{ id };
|
226
263
|
auto resp = test::utils::execute(integration.cluster, req);
|
@@ -17,16 +17,24 @@
|
|
17
17
|
|
18
18
|
#include "test_helper_integration.hxx"
|
19
19
|
|
20
|
+
#include <catch2/matchers/catch_matchers_string.hpp>
|
21
|
+
|
20
22
|
#include "core/operations/management/collection_create.hxx"
|
21
23
|
#include "core/operations/management/search_index_drop.hxx"
|
22
24
|
#include "core/operations/management/search_index_upsert.hxx"
|
23
25
|
|
26
|
+
#include <couchbase/query_string_query.hxx>
|
27
|
+
|
24
28
|
using Catch::Matchers::StartsWith;
|
25
29
|
|
26
30
|
TEST_CASE("integration: search query")
|
27
31
|
{
|
28
32
|
test::utils::integration_test_guard integration;
|
29
33
|
|
34
|
+
if (!integration.cluster_version().supports_search()) {
|
35
|
+
SKIP("cluster does not support search");
|
36
|
+
}
|
37
|
+
|
30
38
|
test::utils::open_bucket(integration.cluster, integration.ctx.bucket);
|
31
39
|
|
32
40
|
{
|
@@ -348,6 +356,14 @@ TEST_CASE("integration: search query consistency", "[integration]")
|
|
348
356
|
{
|
349
357
|
test::utils::integration_test_guard integration;
|
350
358
|
|
359
|
+
if (integration.ctx.deployment == test::utils::deployment_type::elixir) {
|
360
|
+
SKIP("elixir deployment is incompatible with parts of this test");
|
361
|
+
}
|
362
|
+
|
363
|
+
if (!integration.cluster_version().supports_search()) {
|
364
|
+
SKIP("cluster does not support search");
|
365
|
+
}
|
366
|
+
|
351
367
|
test::utils::open_bucket(integration.cluster, integration.ctx.bucket);
|
352
368
|
|
353
369
|
const std::string params =
|
@@ -441,7 +457,7 @@ TEST_CASE("integration: search query consistency", "[integration]")
|
|
441
457
|
CB_LOG_INFO("ignore consistency_mismatch: {}", resp.ctx.http_body);
|
442
458
|
continue;
|
443
459
|
}
|
444
|
-
INFO(resp.ctx.http_body)
|
460
|
+
INFO(resp.ctx.http_body);
|
445
461
|
REQUIRE_SUCCESS(resp.ctx.ec);
|
446
462
|
switch (resp.rows.size()) {
|
447
463
|
case 1:
|
@@ -474,8 +490,12 @@ TEST_CASE("integration: search query collections")
|
|
474
490
|
{
|
475
491
|
test::utils::integration_test_guard integration;
|
476
492
|
|
493
|
+
if (!integration.cluster_version().supports_search()) {
|
494
|
+
SKIP("cluster does not support search");
|
495
|
+
}
|
496
|
+
|
477
497
|
if (!integration.cluster_version().supports_collections()) {
|
478
|
-
|
498
|
+
SKIP("cluster does not support collections");
|
479
499
|
}
|
480
500
|
|
481
501
|
test::utils::open_bucket(integration.cluster, integration.ctx.bucket);
|
@@ -30,7 +30,7 @@ assert_single_lookup_success(test::utils::integration_test_guard& integration,
|
|
30
30
|
couchbase::core::operations::lookup_in_request req{ id };
|
31
31
|
req.specs = couchbase::lookup_in_specs{ spec }.specs();
|
32
32
|
auto resp = test::utils::execute(integration.cluster, req);
|
33
|
-
INFO(fmt::format("assert_single_lookup_success(\"{}\", \"{}\")", id, req.specs[0].path_))
|
33
|
+
INFO(fmt::format("assert_single_lookup_success(\"{}\", \"{}\")", id, req.specs[0].path_));
|
34
34
|
REQUIRE_SUCCESS(resp.ctx.ec());
|
35
35
|
REQUIRE_FALSE(resp.cas.empty());
|
36
36
|
REQUIRE(resp.fields.size() == 1);
|
@@ -54,7 +54,7 @@ assert_single_lookup_error(test::utils::integration_test_guard& integration,
|
|
54
54
|
couchbase::core::operations::lookup_in_request req{ id };
|
55
55
|
req.specs = couchbase::lookup_in_specs{ spec }.specs();
|
56
56
|
auto resp = test::utils::execute(integration.cluster, req);
|
57
|
-
INFO(fmt::format("assert_single_lookup_error(\"{}\", \"{}\")", id, req.specs[0].path_))
|
57
|
+
INFO(fmt::format("assert_single_lookup_error(\"{}\", \"{}\")", id, req.specs[0].path_));
|
58
58
|
REQUIRE_SUCCESS(resp.ctx.ec());
|
59
59
|
REQUIRE_FALSE(resp.cas.empty());
|
60
60
|
REQUIRE(resp.fields.size() == 1);
|
@@ -197,6 +197,10 @@ TEST_CASE("integration: subdoc get & exists", "[integration]")
|
|
197
197
|
|
198
198
|
SECTION("non json get")
|
199
199
|
{
|
200
|
+
if (integration.cluster_version().is_mock()) {
|
201
|
+
SKIP("GOCAVES does not handle subdocument operations for non-JSON documents. See "
|
202
|
+
"https://github.com/couchbaselabs/gocaves/issues/103");
|
203
|
+
}
|
200
204
|
assert_single_lookup_error(integration,
|
201
205
|
non_json_id,
|
202
206
|
couchbase::lookup_in_specs::get("non-exist"),
|
@@ -206,6 +210,10 @@ TEST_CASE("integration: subdoc get & exists", "[integration]")
|
|
206
210
|
|
207
211
|
SECTION("non json exists")
|
208
212
|
{
|
213
|
+
if (integration.cluster_version().is_mock()) {
|
214
|
+
SKIP("GOCAVES does not handle subdocument operations for non-JSON documents. See "
|
215
|
+
"https://github.com/couchbaselabs/gocaves/issues/103");
|
216
|
+
}
|
209
217
|
assert_single_lookup_error(integration,
|
210
218
|
non_json_id,
|
211
219
|
couchbase::lookup_in_specs::exists("non-exist"),
|
@@ -218,11 +226,19 @@ TEST_CASE("integration: subdoc get & exists", "[integration]")
|
|
218
226
|
{
|
219
227
|
std::vector<std::string> invalid_paths = { "invalid..path", "invalid[-2]" };
|
220
228
|
for (const auto& path : invalid_paths) {
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
229
|
+
if (integration.cluster_version().is_mock()) {
|
230
|
+
assert_single_lookup_error(integration,
|
231
|
+
id,
|
232
|
+
couchbase::lookup_in_specs::get(path),
|
233
|
+
couchbase::key_value_status_code::subdoc_path_not_found,
|
234
|
+
couchbase::errc::key_value::path_not_found);
|
235
|
+
} else {
|
236
|
+
assert_single_lookup_error(integration,
|
237
|
+
id,
|
238
|
+
couchbase::lookup_in_specs::get(path),
|
239
|
+
couchbase::key_value_status_code::subdoc_path_invalid,
|
240
|
+
couchbase::errc::key_value::path_invalid);
|
241
|
+
}
|
226
242
|
}
|
227
243
|
}
|
228
244
|
|
@@ -317,6 +333,10 @@ TEST_CASE("integration: subdoc store", "[integration]")
|
|
317
333
|
|
318
334
|
SECTION("non json")
|
319
335
|
{
|
336
|
+
if (integration.cluster_version().is_mock()) {
|
337
|
+
SKIP("GOCAVES does not handle subdocument operations for non-JSON documents. See "
|
338
|
+
"https://github.com/couchbaselabs/gocaves/issues/103");
|
339
|
+
}
|
320
340
|
std::string path{ "dict" };
|
321
341
|
auto value = couchbase::core::utils::to_binary("non-json");
|
322
342
|
couchbase::core::operations::mutate_in_request req{ id };
|
@@ -411,6 +431,11 @@ TEST_CASE("integration: subdoc mutate in store semantics", "[integration]")
|
|
411
431
|
TEST_CASE("integration: subdoc unique", "[integration]")
|
412
432
|
{
|
413
433
|
test::utils::integration_test_guard integration;
|
434
|
+
|
435
|
+
if (integration.cluster_version().is_mock()) {
|
436
|
+
SKIP("GOCAVES does not support subdocument create_path feature. See https://github.com/couchbaselabs/gocaves/issues/17");
|
437
|
+
}
|
438
|
+
|
414
439
|
test::utils::open_bucket(integration.cluster, integration.ctx.bucket);
|
415
440
|
couchbase::core::document_id id{ integration.ctx.bucket, "_default", "_default", test::utils::uniq_id("subdoc") };
|
416
441
|
|
@@ -453,7 +478,6 @@ TEST_CASE("integration: subdoc unique", "[integration]")
|
|
453
478
|
couchbase::mutate_in_specs{ couchbase::mutate_in_specs::array_append("a", tao::json::empty_object).create_path() }.specs();
|
454
479
|
auto resp = test::utils::execute(integration.cluster, req);
|
455
480
|
assert_single_mutate_success(resp, "a");
|
456
|
-
assert_single_lookup_success(integration, id, couchbase::lookup_in_specs::get("a[-1]"), "{}");
|
457
481
|
}
|
458
482
|
|
459
483
|
{
|
@@ -472,7 +496,10 @@ TEST_CASE("integration: subdoc counter", "[integration]")
|
|
472
496
|
couchbase::core::document_id id{ integration.ctx.bucket, "_default", "_default", test::utils::uniq_id("subdoc") };
|
473
497
|
|
474
498
|
{
|
475
|
-
auto value_json =
|
499
|
+
auto value_json =
|
500
|
+
integration.cluster_version().is_mock() // kv_engine creates counters automatically
|
501
|
+
? couchbase::core::utils::to_binary(R"({"dictkey":"dictval","array":[1,2,3,4,[10,20,30,[100,200,300]]],"counter":0})")
|
502
|
+
: couchbase::core::utils::to_binary(R"({"dictkey":"dictval","array":[1,2,3,4,[10,20,30,[100,200,300]]]})");
|
476
503
|
couchbase::core::operations::insert_request req{ id, value_json };
|
477
504
|
auto resp = test::utils::execute(integration.cluster, req);
|
478
505
|
REQUIRE_SUCCESS(resp.ctx.ec());
|
@@ -497,6 +524,9 @@ TEST_CASE("integration: subdoc counter", "[integration]")
|
|
497
524
|
|
498
525
|
SECTION("max value")
|
499
526
|
{
|
527
|
+
if (integration.cluster_version().is_mock()) {
|
528
|
+
SKIP("GOCAVES incorrectly handles limits for subdoc counters. See https://github.com/couchbaselabs/gocaves/issues/104");
|
529
|
+
}
|
500
530
|
{
|
501
531
|
int64_t max_value = std::numeric_limits<int64_t>::max();
|
502
532
|
couchbase::core::operations::mutate_in_request req{ id };
|
@@ -516,6 +546,9 @@ TEST_CASE("integration: subdoc counter", "[integration]")
|
|
516
546
|
|
517
547
|
SECTION("invalid delta")
|
518
548
|
{
|
549
|
+
if (integration.cluster_version().is_mock()) {
|
550
|
+
SKIP("GOCAVES incorrectly handles zero delta for subdoc counters. See https://github.com/couchbaselabs/gocaves/issues/105");
|
551
|
+
}
|
519
552
|
couchbase::core::operations::mutate_in_request req{ id };
|
520
553
|
req.specs = couchbase::mutate_in_specs{ couchbase::mutate_in_specs::increment("counter", 0) }.specs();
|
521
554
|
auto resp = test::utils::execute(integration.cluster, req);
|
@@ -525,6 +558,9 @@ TEST_CASE("integration: subdoc counter", "[integration]")
|
|
525
558
|
|
526
559
|
SECTION("increase number already too big")
|
527
560
|
{
|
561
|
+
if (integration.cluster_version().is_mock()) {
|
562
|
+
SKIP("GOCAVES incorrectly handles big values for subdoc counters. See https://github.com/couchbaselabs/gocaves/issues/106");
|
563
|
+
}
|
528
564
|
{
|
529
565
|
auto big_value = R"({"counter":)" + std::to_string(std::numeric_limits<int64_t>::max()) + "999999999999999999999999999999}";
|
530
566
|
auto value_json = couchbase::core::utils::to_binary(big_value);
|
@@ -621,7 +657,11 @@ TEST_CASE("integration: subdoc multi lookup", "[integration]")
|
|
621
657
|
}
|
622
658
|
.specs();
|
623
659
|
auto resp = test::utils::execute(integration.cluster, req);
|
624
|
-
|
660
|
+
if (integration.cluster_version().is_mock()) {
|
661
|
+
REQUIRE(resp.ctx.ec() == couchbase::errc::common::unsupported_operation);
|
662
|
+
} else {
|
663
|
+
REQUIRE(resp.ctx.ec() == couchbase::errc::common::invalid_argument);
|
664
|
+
}
|
625
665
|
}
|
626
666
|
|
627
667
|
SECTION("missing key")
|
@@ -647,7 +687,10 @@ TEST_CASE("integration: subdoc multi mutation", "[integration]")
|
|
647
687
|
couchbase::core::document_id id{ integration.ctx.bucket, "_default", "_default", test::utils::uniq_id("subdoc") };
|
648
688
|
|
649
689
|
{
|
650
|
-
auto value_json =
|
690
|
+
auto value_json =
|
691
|
+
integration.cluster_version().is_mock() // kv_engine creates counters automatically
|
692
|
+
? couchbase::core::utils::to_binary(R"({"dictkey":"dictval","array":[1,2,3,4,[10,20,30,[100,200,300]]],"counter":0})")
|
693
|
+
: couchbase::core::utils::to_binary(R"({"dictkey":"dictval","array":[1,2,3,4,[10,20,30,[100,200,300]]]})");
|
651
694
|
couchbase::core::operations::insert_request req{ id, value_json };
|
652
695
|
auto resp = test::utils::execute(integration.cluster, req);
|
653
696
|
REQUIRE_SUCCESS(resp.ctx.ec());
|
@@ -676,6 +719,9 @@ TEST_CASE("integration: subdoc multi mutation", "[integration]")
|
|
676
719
|
|
677
720
|
SECTION("replace with errors")
|
678
721
|
{
|
722
|
+
if (integration.cluster_version().is_mock()) {
|
723
|
+
SKIP("GOCAVES incorrectly uses error indexes for subdoc mutations. See https://github.com/couchbaselabs/gocaves/issues/107");
|
724
|
+
}
|
679
725
|
couchbase::core::operations::mutate_in_request req{ id };
|
680
726
|
req.specs =
|
681
727
|
couchbase::mutate_in_specs{
|
@@ -695,6 +741,11 @@ TEST_CASE("integration: subdoc multi mutation", "[integration]")
|
|
695
741
|
TEST_CASE("integration: subdoc expiry")
|
696
742
|
{
|
697
743
|
test::utils::integration_test_guard integration;
|
744
|
+
|
745
|
+
if (integration.cluster_version().is_mock()) {
|
746
|
+
SKIP("GOCAVES does not support subdoc mutations with expiry. See https://github.com/couchbaselabs/gocaves/issues/85");
|
747
|
+
}
|
748
|
+
|
698
749
|
test::utils::open_bucket(integration.cluster, integration.ctx.bucket);
|
699
750
|
couchbase::core::document_id id{ integration.ctx.bucket, "_default", "_default", test::utils::uniq_id("subdoc") };
|
700
751
|
|
@@ -17,6 +17,8 @@
|
|
17
17
|
|
18
18
|
#include "test_helper_integration.hxx"
|
19
19
|
|
20
|
+
#include <catch2/generators/catch_generators.hpp>
|
21
|
+
|
20
22
|
#include "core/platform/uuid.h"
|
21
23
|
|
22
24
|
#include <couchbase/lookup_in_specs.hxx>
|
@@ -247,6 +249,9 @@ TEST_CASE("integration: enable external tracer", "[integration]")
|
|
247
249
|
{
|
248
250
|
SECTION("query")
|
249
251
|
{
|
252
|
+
if (!guard.cluster_version().supports_query()) {
|
253
|
+
SKIP("cluster does not support query");
|
254
|
+
}
|
250
255
|
tracer->reset();
|
251
256
|
couchbase::core::operations::query_request req{ R"(SELECT "ruby rules" AS greeting)" };
|
252
257
|
req.parent_span = parent_span;
|
@@ -17,6 +17,10 @@
|
|
17
17
|
|
18
18
|
#include "test_helper_integration.hxx"
|
19
19
|
|
20
|
+
#include <catch2/matchers/catch_matchers.hpp>
|
21
|
+
#include <catch2/matchers/catch_matchers_exception.hpp>
|
22
|
+
#include <catch2/matchers/catch_matchers_string.hpp>
|
23
|
+
|
20
24
|
#include <couchbase/cluster.hxx>
|
21
25
|
#include <couchbase/codec/raw_binary_transcoder.hxx>
|
22
26
|
|
@@ -24,7 +28,7 @@
|
|
24
28
|
|
25
29
|
#include "profile.hxx"
|
26
30
|
|
27
|
-
using Catch::
|
31
|
+
using Catch::Matchers::ContainsSubstring;
|
28
32
|
|
29
33
|
TEST_CASE("integration: upsert/get with json transcoder", "[integration]")
|
30
34
|
{
|
@@ -427,6 +431,10 @@ TEST_CASE("integration: subdoc with public API", "[integration]")
|
|
427
431
|
{
|
428
432
|
test::utils::integration_test_guard integration;
|
429
433
|
|
434
|
+
if (integration.cluster_version().is_mock()) {
|
435
|
+
SKIP("GOCAVES incorrectly uses error indexes for subdoc mutations. See https://github.com/couchbaselabs/gocaves/issues/107");
|
436
|
+
}
|
437
|
+
|
430
438
|
test::utils::open_bucket(integration.cluster, integration.ctx.bucket);
|
431
439
|
|
432
440
|
auto collection = couchbase::cluster(integration.cluster)
|
@@ -497,10 +505,10 @@ TEST_CASE("integration: subdoc with public API", "[integration]")
|
|
497
505
|
REQUIRE(ctx.first_error_path().has_value());
|
498
506
|
REQUIRE(ctx.first_error_path() == "missing_field");
|
499
507
|
REQUIRE(resp.cas().empty());
|
500
|
-
REQUIRE_THROWS_WITH(resp.has_value(0),
|
501
|
-
REQUIRE_THROWS_WITH(resp.has_value("views"),
|
502
|
-
REQUIRE_THROWS_WITH(resp.content_as<std::uint32_t>(0),
|
503
|
-
REQUIRE_THROWS_WITH(resp.content_as<std::uint32_t>("views"),
|
508
|
+
REQUIRE_THROWS_WITH(resp.has_value(0), ContainsSubstring("path_invalid"));
|
509
|
+
REQUIRE_THROWS_WITH(resp.has_value("views"), ContainsSubstring("path_invalid"));
|
510
|
+
REQUIRE_THROWS_WITH(resp.content_as<std::uint32_t>(0), ContainsSubstring("path_invalid"));
|
511
|
+
REQUIRE_THROWS_WITH(resp.content_as<std::uint32_t>("views"), ContainsSubstring("path_invalid"));
|
504
512
|
}
|
505
513
|
|
506
514
|
{
|
data/ext/couchbase/test/{test_transaction_transaction_context.cxx → test_transaction_context.cxx}
RENAMED
@@ -504,7 +504,7 @@ TEST_CASE("transactions: can see some query errors but no transactions failed",
|
|
504
504
|
// eat the expected op_exception
|
505
505
|
} catch (...) {
|
506
506
|
auto e = std::current_exception();
|
507
|
-
|
507
|
+
INFO(fmt::format("got {}", typeid(e).name()));
|
508
508
|
FAIL("expected op_exception to be thrown from the future");
|
509
509
|
}
|
510
510
|
REQUIRE_NOTHROW(tx.existing_error());
|
@@ -0,0 +1,195 @@
|
|
1
|
+
/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
2
|
+
/*
|
3
|
+
* Copyright 2023-Present 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 "test_helper_integration.hxx"
|
19
|
+
|
20
|
+
#include <couchbase/cluster.hxx>
|
21
|
+
#include <couchbase/fmt/cas.hxx>
|
22
|
+
#include <couchbase/transactions/attempt_context.hxx>
|
23
|
+
|
24
|
+
#include <tao/json.hpp>
|
25
|
+
|
26
|
+
namespace blocking_txn
|
27
|
+
{
|
28
|
+
//! [blocking-txn]
|
29
|
+
#include <couchbase/cluster.hxx>
|
30
|
+
#include <couchbase/fmt/cas.hxx>
|
31
|
+
#include <couchbase/transactions/attempt_context.hxx>
|
32
|
+
|
33
|
+
#include <tao/json.hpp>
|
34
|
+
|
35
|
+
int
|
36
|
+
main(int argc, const char* argv[])
|
37
|
+
{
|
38
|
+
if (argc != 4) {
|
39
|
+
fmt::print("USAGE: ./blocking-txn couchbase://127.0.0.1 Administrator password\n");
|
40
|
+
return 1;
|
41
|
+
}
|
42
|
+
|
43
|
+
int retval = 0;
|
44
|
+
|
45
|
+
const std::string connection_string{ argv[1] };
|
46
|
+
const std::string username{ argv[2] };
|
47
|
+
const std::string password{ argv[3] };
|
48
|
+
|
49
|
+
// run IO context on separate thread
|
50
|
+
asio::io_context io;
|
51
|
+
auto guard = asio::make_work_guard(io);
|
52
|
+
std::thread io_thread([&io]() { io.run(); });
|
53
|
+
|
54
|
+
auto options = couchbase::cluster_options(username, password);
|
55
|
+
// customize through the 'options'.
|
56
|
+
// For example, optimize timeouts for WAN
|
57
|
+
options.apply_profile("wan_development");
|
58
|
+
|
59
|
+
// [1] connect to cluster using the given connection string and the options
|
60
|
+
auto [cluster, ec] = couchbase::cluster::connect(io, connection_string, options).get();
|
61
|
+
if (ec) {
|
62
|
+
fmt::print("unable to connect to the cluster: {}\n", ec.message());
|
63
|
+
return 1;
|
64
|
+
}
|
65
|
+
|
66
|
+
// [2] persist three documents to the default collection of bucket "default"
|
67
|
+
auto collection = cluster.bucket("default").default_collection();
|
68
|
+
constexpr auto id_1 = "my-doc_1";
|
69
|
+
constexpr auto id_2 = "my_doc_2";
|
70
|
+
constexpr auto id_3 = "my_doc_3";
|
71
|
+
const tao::json::value content = { { "some", "content" } };
|
72
|
+
|
73
|
+
for (const auto& id : { id_1, id_2, id_3 }) {
|
74
|
+
if (auto [ctx, res] = collection.upsert(id, content).get(); ctx.ec()) {
|
75
|
+
fmt::print(stderr, "upsert \"{}\" failed before starting transaction: {}\n", id, ctx.ec().message());
|
76
|
+
return 1;
|
77
|
+
}
|
78
|
+
}
|
79
|
+
|
80
|
+
{ // [3] blocking transaction
|
81
|
+
//! [simple-blocking-txn]
|
82
|
+
auto [tx_err, tx_res] = cluster.transactions()->run(
|
83
|
+
// [3.1] closure argument to run() method encapsulates logic, that has to be run in transaction
|
84
|
+
[&](couchbase::transactions::attempt_context& ctx) {
|
85
|
+
// [3.2] get document
|
86
|
+
auto [err_ctx, doc] = ctx.get(collection, id_1);
|
87
|
+
if (err_ctx.ec()) {
|
88
|
+
fmt::print(stderr, "failed to get document \"{}\": {}\n", id_1, err_ctx.ec().message());
|
89
|
+
// [3.3] don't continue the transaction logic
|
90
|
+
return;
|
91
|
+
}
|
92
|
+
// [3.4] replace document's content
|
93
|
+
ctx.replace(doc, ::tao::json::value{ { "some", "other content" } });
|
94
|
+
});
|
95
|
+
// [3.5] check the overall status of the transaction
|
96
|
+
if (tx_err.ec()) {
|
97
|
+
fmt::print(stderr, "error in transaction {}, cause: {}\n", tx_err.ec().message(), tx_err.cause().message());
|
98
|
+
retval = 1;
|
99
|
+
} else {
|
100
|
+
fmt::print("transaction {} completed successfully", tx_res.transaction_id);
|
101
|
+
}
|
102
|
+
//! [simple-blocking-txn]
|
103
|
+
}
|
104
|
+
|
105
|
+
{ // [4] asynchronous transaction
|
106
|
+
//! [simple-async-txn]
|
107
|
+
// [4.1] create promise to retrieve result from the transaction
|
108
|
+
auto barrier = std::make_shared<std::promise<std::error_code>>();
|
109
|
+
auto f = barrier->get_future();
|
110
|
+
cluster.transactions()->run(
|
111
|
+
// [4.2] closure argument to run() method encapsulates logic, that has to be run in transaction
|
112
|
+
[&](couchbase::transactions::async_attempt_context& ctx) {
|
113
|
+
// [4.3] get document
|
114
|
+
ctx.get(collection, id_1, [&](auto err_ctx_1, auto doc) {
|
115
|
+
if (err_ctx_1.ec()) {
|
116
|
+
fmt::print(stderr, "failed to get document \"{}\": {}\n", id_1, err_ctx_1.ec().message());
|
117
|
+
return;
|
118
|
+
}
|
119
|
+
// [4.4] replace document's content
|
120
|
+
ctx.replace(doc, ::tao::json::value{ { "some", "other async content" } }, [&](auto err_ctx_2, auto res) {
|
121
|
+
if (err_ctx_2.ec()) {
|
122
|
+
fmt::print(stderr, "error replacing content in doc {}: {}\n", id_1, err_ctx_2.ec().message());
|
123
|
+
} else {
|
124
|
+
fmt::print("successfully replaced: {}, cas={}\n", id_1, res.cas());
|
125
|
+
}
|
126
|
+
});
|
127
|
+
});
|
128
|
+
ctx.get(collection, id_2, [&](auto err_ctx_1, auto doc) {
|
129
|
+
if (err_ctx_1.ec()) {
|
130
|
+
fmt::print("error getting doc {}: {}", id_2, err_ctx_1.ec().message());
|
131
|
+
return;
|
132
|
+
}
|
133
|
+
ctx.replace(doc, ::tao::json::value{ { "some", "other async content" } }, [&](auto err_ctx_2, auto res) {
|
134
|
+
if (err_ctx_2.ec()) {
|
135
|
+
fmt::print(stderr, "error replacing content in doc {}: {}\n", id_2, err_ctx_2.ec().message());
|
136
|
+
} else {
|
137
|
+
fmt::print("successfully replaced: {}, cas={}\n", id_2, res.cas());
|
138
|
+
}
|
139
|
+
});
|
140
|
+
});
|
141
|
+
ctx.get(collection, id_3, [&](auto err_ctx_1, auto doc) {
|
142
|
+
if (err_ctx_1.ec()) {
|
143
|
+
fmt::print("error getting doc {}: {}", id_3, err_ctx_1.ec().message());
|
144
|
+
return;
|
145
|
+
}
|
146
|
+
ctx.replace(doc, ::tao::json::value{ { "some", "other async content" } }, [&](auto err_ctx_2, auto res) {
|
147
|
+
if (err_ctx_2.ec()) {
|
148
|
+
fmt::print(stderr, "error replacing content in doc {}: {}\n", id_3, err_ctx_2.ec().message());
|
149
|
+
} else {
|
150
|
+
fmt::print("successfully replaced: {}, cas={}\n", id_3, res.cas());
|
151
|
+
}
|
152
|
+
});
|
153
|
+
});
|
154
|
+
},
|
155
|
+
// [4.5], second closure represents transaction completion logic
|
156
|
+
[barrier](auto tx_err, auto tx_res) {
|
157
|
+
if (tx_err.ec()) {
|
158
|
+
fmt::print(stderr, "error in async transaction {}, {}\n", tx_res.transaction_id, tx_err.ec().message());
|
159
|
+
}
|
160
|
+
barrier->set_value(tx_err.ec());
|
161
|
+
});
|
162
|
+
if (auto async_err = f.get()) {
|
163
|
+
retval = 1;
|
164
|
+
}
|
165
|
+
//! [simple-async-txn]
|
166
|
+
}
|
167
|
+
|
168
|
+
// [5], close cluster connection
|
169
|
+
cluster.close();
|
170
|
+
guard.reset();
|
171
|
+
|
172
|
+
io_thread.join();
|
173
|
+
return retval;
|
174
|
+
}
|
175
|
+
|
176
|
+
//! [blocking-txn]
|
177
|
+
} // namespace blocking_txn
|
178
|
+
|
179
|
+
TEST_CASE("example: basic transaction", "[integration]")
|
180
|
+
{
|
181
|
+
test::utils::integration_test_guard integration;
|
182
|
+
if (!integration.cluster_version().supports_collections()) {
|
183
|
+
SKIP("cluster does not support collections");
|
184
|
+
}
|
185
|
+
|
186
|
+
const auto env = test::utils::test_context::load_from_environment();
|
187
|
+
const char* argv[] = {
|
188
|
+
"blocking-txn", // name of the "executable"
|
189
|
+
env.connection_string.c_str(),
|
190
|
+
env.username.c_str(),
|
191
|
+
env.password.c_str(),
|
192
|
+
};
|
193
|
+
|
194
|
+
REQUIRE(blocking_txn::main(4, argv) == 0);
|
195
|
+
}
|
data/ext/couchbase/test/{test_transaction_transaction_simple.cxx → test_transaction_simple.cxx}
RENAMED
@@ -14,15 +14,27 @@
|
|
14
14
|
* limitations under the License.
|
15
15
|
*/
|
16
16
|
|
17
|
-
#include "../core/transactions/atr_ids.hxx"
|
18
|
-
#include "simple_object.hxx"
|
19
17
|
#include "test_helper_integration.hxx"
|
20
|
-
|
21
|
-
#include
|
18
|
+
|
19
|
+
#include "simple_object.hxx"
|
20
|
+
|
21
|
+
#include "core/transactions.hxx"
|
22
|
+
#include "core/transactions/atr_ids.hxx"
|
22
23
|
|
23
24
|
#include <spdlog/spdlog.h>
|
25
|
+
#include <tao/json.hpp>
|
26
|
+
|
24
27
|
#include <stdexcept>
|
25
28
|
|
29
|
+
#if defined(__GNUC__)
|
30
|
+
#if __GNUC__ <= 10
|
31
|
+
#pragma GCC diagnostic ignored "-Wparentheses"
|
32
|
+
#endif
|
33
|
+
#if __GNUC__ < 9
|
34
|
+
#pragma GCC diagnostic ignored "-Wuseless-cast"
|
35
|
+
#endif
|
36
|
+
#endif
|
37
|
+
|
26
38
|
using namespace couchbase::core::transactions;
|
27
39
|
static const tao::json::value content{
|
28
40
|
{ "some_number", 0 },
|
@@ -969,4 +981,4 @@ TEST_CASE("transactions: sergey example", "[transactions]")
|
|
969
981
|
auto remove_res = ctx.get_optional(id_to_remove);
|
970
982
|
CHECK_FALSE(remove_res.has_value());
|
971
983
|
}));
|
972
|
-
}
|
984
|
+
}
|