couchbase 3.4.2 → 3.4.3

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 (241) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/ext/couchbase/CMakeLists.txt +57 -7
  4. data/ext/couchbase/cmake/Documentation.cmake +0 -1
  5. data/ext/couchbase/cmake/OpenSSL.cmake +98 -3
  6. data/ext/couchbase/cmake/Testing.cmake +12 -4
  7. data/ext/couchbase/cmake/build_config.hxx.in +3 -0
  8. data/ext/couchbase/core/bucket.cxx +3 -2
  9. data/ext/couchbase/core/bucket.hxx +9 -0
  10. data/ext/couchbase/core/cluster.hxx +17 -0
  11. data/ext/couchbase/core/cluster_options.cxx +2 -2
  12. data/ext/couchbase/core/cluster_options.hxx +4 -6
  13. data/ext/couchbase/core/cluster_options_fwd.hxx +26 -0
  14. data/ext/couchbase/core/config_profile.hxx +1 -54
  15. data/ext/couchbase/core/config_profiles.cxx +79 -0
  16. data/ext/couchbase/core/config_profiles.hxx +56 -0
  17. data/ext/couchbase/core/error_context/search.hxx +1 -1
  18. data/ext/couchbase/core/impl/analytics.cxx +1 -0
  19. data/ext/couchbase/core/impl/boolean_field_query.cxx +40 -0
  20. data/ext/couchbase/core/impl/boolean_query.cxx +62 -0
  21. data/ext/couchbase/core/impl/cluster.cxx +2 -0
  22. data/ext/couchbase/core/impl/conjunction_query.cxx +51 -0
  23. data/ext/couchbase/core/impl/date_range.cxx +89 -0
  24. data/ext/couchbase/core/impl/date_range_facet.cxx +54 -0
  25. data/ext/couchbase/core/impl/date_range_facet_result.cxx +64 -0
  26. data/ext/couchbase/core/impl/date_range_query.cxx +125 -0
  27. data/ext/couchbase/core/impl/disjunction_query.cxx +51 -0
  28. data/ext/couchbase/core/impl/encoded_search_facet.hxx +29 -0
  29. data/ext/couchbase/core/impl/encoded_search_query.hxx +29 -0
  30. data/ext/couchbase/core/impl/encoded_search_sort.hxx +29 -0
  31. data/ext/couchbase/core/impl/geo_bounding_box_query.cxx +46 -0
  32. data/ext/couchbase/core/impl/geo_distance_query.cxx +43 -0
  33. data/ext/couchbase/core/impl/geo_polygon_query.cxx +46 -0
  34. data/ext/couchbase/core/impl/internal_date_range_facet_result.cxx +80 -0
  35. data/ext/couchbase/core/impl/internal_date_range_facet_result.hxx +48 -0
  36. data/ext/couchbase/core/impl/internal_numeric_range_facet_result.cxx +80 -0
  37. data/ext/couchbase/core/impl/internal_numeric_range_facet_result.hxx +48 -0
  38. data/ext/couchbase/core/impl/internal_search_error_context.cxx +141 -0
  39. data/ext/couchbase/core/impl/internal_search_error_context.hxx +61 -0
  40. data/ext/couchbase/core/impl/internal_search_meta_data.cxx +60 -0
  41. data/ext/couchbase/core/impl/internal_search_meta_data.hxx +41 -0
  42. data/ext/couchbase/core/impl/internal_search_result.cxx +84 -0
  43. data/ext/couchbase/core/impl/internal_search_result.hxx +43 -0
  44. data/ext/couchbase/core/impl/internal_search_row.cxx +82 -0
  45. data/ext/couchbase/core/impl/internal_search_row.hxx +56 -0
  46. data/ext/couchbase/core/impl/internal_search_row_location.hxx +32 -0
  47. data/ext/couchbase/core/impl/internal_search_row_locations.cxx +137 -0
  48. data/ext/couchbase/core/impl/internal_search_row_locations.hxx +45 -0
  49. data/ext/couchbase/core/impl/internal_term_facet_result.cxx +80 -0
  50. data/ext/couchbase/core/impl/internal_term_facet_result.hxx +48 -0
  51. data/ext/couchbase/core/impl/match_all_query.cxx +35 -0
  52. data/ext/couchbase/core/impl/match_none_query.cxx +35 -0
  53. data/ext/couchbase/core/impl/match_phrase_query.cxx +43 -0
  54. data/ext/couchbase/core/impl/match_query.cxx +59 -0
  55. data/ext/couchbase/core/impl/numeric_range.cxx +49 -0
  56. data/ext/couchbase/core/impl/numeric_range_facet.cxx +54 -0
  57. data/ext/couchbase/core/impl/numeric_range_facet_result.cxx +64 -0
  58. data/ext/couchbase/core/impl/numeric_range_query.cxx +56 -0
  59. data/ext/couchbase/core/impl/phrase_query.cxx +42 -0
  60. data/ext/couchbase/core/impl/prefix_query.cxx +40 -0
  61. data/ext/couchbase/core/impl/query_string_query.cxx +37 -0
  62. data/ext/couchbase/core/impl/regexp_query.cxx +40 -0
  63. data/ext/couchbase/core/impl/search.cxx +191 -0
  64. data/ext/couchbase/core/impl/search_error_context.cxx +147 -0
  65. data/ext/couchbase/core/impl/search_meta_data.cxx +46 -0
  66. data/ext/couchbase/core/impl/search_result.cxx +66 -0
  67. data/ext/couchbase/core/impl/search_row.cxx +74 -0
  68. data/ext/couchbase/core/impl/search_row_location.cxx +64 -0
  69. data/ext/couchbase/core/impl/search_row_locations.cxx +66 -0
  70. data/ext/couchbase/core/impl/search_sort_field.cxx +104 -0
  71. data/ext/couchbase/core/impl/search_sort_id.cxx +43 -0
  72. data/ext/couchbase/core/impl/search_sort_score.cxx +43 -0
  73. data/ext/couchbase/core/impl/term_facet.cxx +36 -0
  74. data/ext/couchbase/core/impl/term_facet_result.cxx +64 -0
  75. data/ext/couchbase/core/impl/term_query.cxx +56 -0
  76. data/ext/couchbase/core/impl/term_range_query.cxx +57 -0
  77. data/ext/couchbase/core/impl/wildcard_query.cxx +40 -0
  78. data/ext/couchbase/core/io/http_context.hxx +1 -1
  79. data/ext/couchbase/core/io/http_session.hxx +10 -0
  80. data/ext/couchbase/core/io/http_session_manager.hxx +5 -3
  81. data/ext/couchbase/core/io/mcbp_session.cxx +28 -1
  82. data/ext/couchbase/core/io/retry_orchestrator.hxx +3 -2
  83. data/ext/couchbase/core/json_string.hxx +5 -0
  84. data/ext/couchbase/core/meta/version.cxx +18 -4
  85. data/ext/couchbase/core/mozilla_ca_bundle.hxx +39 -0
  86. data/ext/couchbase/core/operations/document_analytics.cxx +1 -0
  87. data/ext/couchbase/core/operations/document_analytics.hxx +1 -0
  88. data/ext/couchbase/core/operations/document_append.hxx +1 -1
  89. data/ext/couchbase/core/operations/document_decrement.hxx +1 -1
  90. data/ext/couchbase/core/operations/document_exists.hxx +1 -1
  91. data/ext/couchbase/core/operations/document_get.hxx +1 -1
  92. data/ext/couchbase/core/operations/document_get_and_lock.hxx +1 -1
  93. data/ext/couchbase/core/operations/document_get_and_touch.hxx +1 -1
  94. data/ext/couchbase/core/operations/document_get_projected.hxx +1 -1
  95. data/ext/couchbase/core/operations/document_increment.hxx +1 -1
  96. data/ext/couchbase/core/operations/document_insert.hxx +1 -1
  97. data/ext/couchbase/core/operations/document_lookup_in.hxx +1 -1
  98. data/ext/couchbase/core/operations/document_mutate_in.hxx +1 -1
  99. data/ext/couchbase/core/operations/document_prepend.hxx +1 -1
  100. data/ext/couchbase/core/operations/document_query.cxx +2 -0
  101. data/ext/couchbase/core/operations/document_query.hxx +6 -0
  102. data/ext/couchbase/core/operations/document_remove.hxx +1 -1
  103. data/ext/couchbase/core/operations/document_replace.hxx +1 -1
  104. data/ext/couchbase/core/operations/document_search.cxx +4 -1
  105. data/ext/couchbase/core/operations/document_search.hxx +2 -1
  106. data/ext/couchbase/core/operations/document_touch.hxx +1 -1
  107. data/ext/couchbase/core/operations/document_unlock.hxx +1 -1
  108. data/ext/couchbase/core/operations/document_upsert.hxx +1 -1
  109. data/ext/couchbase/core/operations/document_view.hxx +1 -0
  110. data/ext/couchbase/core/protocol/client_request.hxx +11 -2
  111. data/ext/couchbase/core/public_fwd.hxx +21 -0
  112. data/ext/couchbase/core/tls_verify_mode.hxx +26 -0
  113. data/ext/couchbase/core/topology/configuration.cxx +15 -2
  114. data/ext/couchbase/core/topology/configuration.hxx +5 -1
  115. data/ext/couchbase/core/transactions/attempt_context_testing_hooks.cxx +93 -0
  116. data/ext/couchbase/core/transactions/attempt_context_testing_hooks.hxx +48 -75
  117. data/ext/couchbase/core/transactions/cleanup_testing_hooks.cxx +52 -0
  118. data/ext/couchbase/core/transactions/cleanup_testing_hooks.hxx +17 -31
  119. data/ext/couchbase/core/transactions/exceptions.hxx +12 -9
  120. data/ext/couchbase/core/utils/connection_string.cxx +17 -0
  121. data/ext/couchbase/core/utils/json.cxx +4 -1
  122. data/ext/couchbase/couchbase/behavior_options.hxx +10 -1
  123. data/ext/couchbase/couchbase/boolean_field_query.hxx +77 -0
  124. data/ext/couchbase/couchbase/boolean_query.hxx +223 -0
  125. data/ext/couchbase/couchbase/cluster.hxx +42 -1
  126. data/ext/couchbase/couchbase/conjunction_query.hxx +88 -0
  127. data/ext/couchbase/couchbase/date_range.hxx +69 -0
  128. data/ext/couchbase/couchbase/date_range_facet.hxx +56 -0
  129. data/ext/couchbase/couchbase/date_range_facet_result.hxx +55 -0
  130. data/ext/couchbase/couchbase/date_range_query.hxx +265 -0
  131. data/ext/couchbase/couchbase/disjunction_query.hxx +109 -0
  132. data/ext/couchbase/couchbase/doc_id_query.hxx +111 -0
  133. data/ext/couchbase/couchbase/error_context.hxx +7 -6
  134. data/ext/couchbase/couchbase/fmt/analytics_scan_consistency.hxx +52 -0
  135. data/ext/couchbase/couchbase/fmt/search_scan_consistency.hxx +49 -0
  136. data/ext/couchbase/couchbase/geo_bounding_box_query.hxx +107 -0
  137. data/ext/couchbase/couchbase/geo_distance_query.hxx +109 -0
  138. data/ext/couchbase/couchbase/geo_point.hxx +32 -0
  139. data/ext/couchbase/couchbase/geo_polygon_query.hxx +85 -0
  140. data/ext/couchbase/couchbase/highlight_style.hxx +45 -0
  141. data/ext/couchbase/couchbase/match_all_query.hxx +43 -0
  142. data/ext/couchbase/couchbase/match_none_query.hxx +43 -0
  143. data/ext/couchbase/couchbase/match_operator.hxx +45 -0
  144. data/ext/couchbase/couchbase/match_phrase_query.hxx +108 -0
  145. data/ext/couchbase/couchbase/match_query.hxx +163 -0
  146. data/ext/couchbase/couchbase/numeric_range.hxx +58 -0
  147. data/ext/couchbase/couchbase/numeric_range_facet.hxx +56 -0
  148. data/ext/couchbase/couchbase/numeric_range_facet_result.hxx +55 -0
  149. data/ext/couchbase/couchbase/numeric_range_query.hxx +143 -0
  150. data/ext/couchbase/couchbase/phrase_query.hxx +93 -0
  151. data/ext/couchbase/couchbase/prefix_query.hxx +82 -0
  152. data/ext/couchbase/couchbase/query_string_query.hxx +72 -0
  153. data/ext/couchbase/couchbase/regexp_query.hxx +82 -0
  154. data/ext/couchbase/couchbase/scope.hxx +40 -0
  155. data/ext/couchbase/couchbase/search_date_range.hxx +68 -0
  156. data/ext/couchbase/couchbase/search_error_context.hxx +138 -0
  157. data/ext/couchbase/couchbase/search_facet.hxx +60 -0
  158. data/ext/couchbase/couchbase/search_facet_result.hxx +50 -0
  159. data/ext/couchbase/couchbase/search_meta_data.hxx +85 -0
  160. data/ext/couchbase/couchbase/search_metrics.hxx +127 -0
  161. data/ext/couchbase/couchbase/search_numeric_range.hxx +69 -0
  162. data/ext/couchbase/couchbase/search_options.hxx +509 -0
  163. data/ext/couchbase/couchbase/search_query.hxx +69 -0
  164. data/ext/couchbase/couchbase/search_result.hxx +77 -0
  165. data/ext/couchbase/couchbase/search_row.hxx +104 -0
  166. data/ext/couchbase/couchbase/search_row_location.hxx +55 -0
  167. data/ext/couchbase/couchbase/search_row_locations.hxx +86 -0
  168. data/ext/couchbase/couchbase/search_scan_consistency.hxx +34 -0
  169. data/ext/couchbase/couchbase/search_sort.hxx +58 -0
  170. data/ext/couchbase/couchbase/search_sort_field.hxx +117 -0
  171. data/ext/couchbase/couchbase/search_sort_field_missing.hxx +26 -0
  172. data/ext/couchbase/couchbase/search_sort_field_mode.hxx +27 -0
  173. data/ext/couchbase/couchbase/search_sort_field_type.hxx +28 -0
  174. data/ext/couchbase/couchbase/search_sort_id.hxx +60 -0
  175. data/ext/couchbase/couchbase/search_sort_score.hxx +60 -0
  176. data/ext/couchbase/couchbase/search_term_range.hxx +51 -0
  177. data/ext/couchbase/couchbase/security_options.hxx +3 -0
  178. data/ext/couchbase/couchbase/term_facet.hxx +48 -0
  179. data/ext/couchbase/couchbase/term_facet_result.hxx +55 -0
  180. data/ext/couchbase/couchbase/term_query.hxx +151 -0
  181. data/ext/couchbase/couchbase/term_range_query.hxx +142 -0
  182. data/ext/couchbase/couchbase/tracing/request_span.hxx +63 -0
  183. data/ext/couchbase/couchbase/tracing/request_tracer.hxx +2 -40
  184. data/ext/couchbase/couchbase/transactions/async_attempt_context.hxx +83 -4
  185. data/ext/couchbase/couchbase/transactions/attempt_context.hxx +67 -0
  186. data/ext/couchbase/couchbase/transactions/transaction_get_result.hxx +2 -0
  187. data/ext/couchbase/couchbase/transactions/transaction_keyspace.hxx +11 -1
  188. data/ext/couchbase/couchbase/transactions/transaction_options.hxx +79 -8
  189. data/ext/couchbase/couchbase/transactions/transaction_query_options.hxx +128 -15
  190. data/ext/couchbase/couchbase/transactions/transaction_query_result.hxx +4 -0
  191. data/ext/couchbase/couchbase/transactions/transaction_result.hxx +1 -1
  192. data/ext/couchbase/couchbase/transactions/transactions_cleanup_config.hxx +5 -3
  193. data/ext/couchbase/couchbase/transactions/transactions_config.hxx +9 -5
  194. data/ext/couchbase/couchbase/transactions/transactions_query_config.hxx +6 -3
  195. data/ext/couchbase/couchbase/transactions.hxx +34 -1
  196. data/ext/couchbase/couchbase/wildcard_query.hxx +83 -0
  197. data/ext/couchbase/test/CMakeLists.txt +7 -5
  198. data/ext/couchbase/test/benchmark_helper_integration.hxx +2 -2
  199. data/ext/couchbase/test/test_helper.hxx +5 -5
  200. data/ext/couchbase/test/test_integration_analytics.cxx +28 -6
  201. data/ext/couchbase/test/test_integration_collections.cxx +7 -3
  202. data/ext/couchbase/test/test_integration_connect.cxx +7 -3
  203. data/ext/couchbase/test/test_integration_crud.cxx +13 -3
  204. data/ext/couchbase/test/test_integration_diagnostics.cxx +11 -5
  205. data/ext/couchbase/test/test_integration_durability.cxx +12 -7
  206. data/ext/couchbase/test/test_integration_examples.cxx +283 -11
  207. data/ext/couchbase/test/test_integration_management.cxx +147 -91
  208. data/ext/couchbase/test/test_integration_query.cxx +68 -10
  209. data/ext/couchbase/test/test_integration_range_scan.cxx +12 -12
  210. data/ext/couchbase/test/test_integration_read_replica.cxx +48 -11
  211. data/ext/couchbase/test/test_integration_search.cxx +22 -2
  212. data/ext/couchbase/test/test_integration_subdoc.cxx +62 -11
  213. data/ext/couchbase/test/test_integration_tracer.cxx +5 -0
  214. data/ext/couchbase/test/test_integration_transcoders.cxx +13 -5
  215. data/ext/couchbase/test/{test_transaction_transaction_context.cxx → test_transaction_context.cxx} +1 -1
  216. data/ext/couchbase/test/test_transaction_examples.cxx +195 -0
  217. data/ext/couchbase/test/{test_transaction_transaction_simple.cxx → test_transaction_simple.cxx} +17 -5
  218. data/ext/couchbase/test/{test_transaction_transaction_simple_async.cxx → test_transaction_simple_async.cxx} +19 -21
  219. data/ext/couchbase/test/test_unit_config_profiles.cxx +1 -1
  220. data/ext/couchbase/test/test_unit_json_transcoder.cxx +4 -0
  221. data/ext/couchbase/test/test_unit_search.cxx +427 -0
  222. data/ext/couchbase/test/test_unit_transaction_utils.cxx +10 -1
  223. data/ext/couchbase/test/test_unit_utils.cxx +8 -4
  224. data/ext/couchbase.cxx +58 -16
  225. data/ext/revisions.rb +3 -3
  226. data/lib/couchbase/authenticator.rb +0 -1
  227. data/lib/couchbase/cluster.rb +0 -4
  228. data/lib/couchbase/config_profiles.rb +1 -1
  229. data/lib/couchbase/json_transcoder.rb +12 -5
  230. data/lib/couchbase/management/collection_query_index_manager.rb +54 -15
  231. data/lib/couchbase/management/query_index_manager.rb +70 -5
  232. data/lib/couchbase/raw_binary_transcoder.rb +37 -0
  233. data/lib/couchbase/raw_json_transcoder.rb +38 -0
  234. data/lib/couchbase/raw_string_transcoder.rb +40 -0
  235. data/lib/couchbase/search_options.rb +5 -0
  236. data/lib/couchbase/transcoder_flags.rb +62 -0
  237. data/lib/couchbase/version.rb +1 -1
  238. metadata +139 -11
  239. data/ext/couchbase/core/config_profile.cxx +0 -47
  240. /data/ext/couchbase/test/{test_transaction_transaction_public_async_api.cxx → test_transaction_public_async_api.cxx} +0 -0
  241. /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 && integration.number_of_nodes() <= integration.number_of_replicas()) {
67
- return;
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 && integration.number_of_nodes() <= number_of_replicas) {
99
- return;
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 && integration.number_of_nodes() <= integration.number_of_replicas()) {
132
- return;
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
- return;
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 && integration.number_of_nodes() <= integration.number_of_replicas()) {
177
- return;
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 && integration.number_of_nodes() <= integration.number_of_replicas()) {
208
- return;
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
- return;
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
- assert_single_lookup_error(integration,
222
- id,
223
- couchbase::lookup_in_specs::get(path),
224
- couchbase::key_value_status_code::subdoc_path_invalid,
225
- couchbase::errc::key_value::path_invalid);
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 = couchbase::core::utils::to_binary(R"({"dictkey":"dictval","array":[1,2,3,4,[10,20,30,[100,200,300]]]})");
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
- REQUIRE(resp.ctx.ec() == couchbase::errc::common::invalid_argument);
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 = couchbase::core::utils::to_binary(R"({"dictkey":"dictval","array":[1,2,3,4,[10,20,30,[100,200,300]]]})");
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::Contains;
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), Contains("path_invalid"));
501
- REQUIRE_THROWS_WITH(resp.has_value("views"), Contains("path_invalid"));
502
- REQUIRE_THROWS_WITH(resp.content_as<std::uint32_t>(0), Contains("path_invalid"));
503
- REQUIRE_THROWS_WITH(resp.content_as<std::uint32_t>("views"), Contains("path_invalid"));
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
  {
@@ -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
- std::cout << "got " << typeid(e).name() << std::endl;
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
+ }
@@ -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
- #include <core/transactions.hxx>
21
- #include <tao/json.hpp>
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
+ }