couchbase 3.8.1 → 3.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (475) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/ext/CMakeLists.txt +16 -1
  4. data/ext/cache/cpm/{CPM_0.42.0.cmake → CPM_0.43.1.cmake} +18 -2
  5. data/ext/cache/extconf_include.rb +6 -6
  6. data/ext/cache/mozilla-ca-bundle.crt +214 -155
  7. data/ext/cache/mozilla-ca-bundle.sha256 +1 -1
  8. data/ext/couchbase/CMakeLists.txt +130 -21
  9. data/ext/couchbase/cmake/APKBUILD.in +25 -4
  10. data/ext/couchbase/cmake/Bundler.cmake +143 -34
  11. data/ext/couchbase/cmake/CPM.cmake +126 -12
  12. data/ext/couchbase/cmake/Cache.cmake +7 -1
  13. data/ext/couchbase/cmake/CompilerOptions.cmake +1 -1
  14. data/ext/couchbase/cmake/CompilerWarnings.cmake +17 -6
  15. data/ext/couchbase/cmake/GrpcProtobuf.cmake +481 -0
  16. data/ext/couchbase/cmake/OpenSSL.cmake +10 -3
  17. data/ext/couchbase/cmake/Packaging.cmake +519 -65
  18. data/ext/couchbase/cmake/Protostellar.cmake +250 -0
  19. data/ext/couchbase/cmake/Sanitizers.cmake +61 -50
  20. data/ext/couchbase/cmake/StaticAnalyzers.cmake +16 -5
  21. data/ext/couchbase/cmake/TestFramework.cmake +283 -0
  22. data/ext/couchbase/cmake/TestFrameworkAddTests.cmake +51 -0
  23. data/ext/couchbase/cmake/Testing.cmake +27 -9
  24. data/ext/couchbase/cmake/ThirdPartyDependencies.cmake +141 -8
  25. data/ext/couchbase/cmake/VersionInfo.cmake +50 -0
  26. data/ext/couchbase/cmake/build_config.hxx.in +2 -1
  27. data/ext/couchbase/cmake/couchbase-cxx-client.spec.in +101 -23
  28. data/ext/couchbase/cmake/couchbase_cxx_client_static-config.cmake.in +7 -0
  29. data/ext/couchbase/cmake/couchbase_cxx_client_static.pc.in +2 -0
  30. data/ext/couchbase/cmake/gRPC_Generate.cmake +58 -0
  31. data/ext/couchbase/cmake/protobuf_Generate.cmake +69 -0
  32. data/ext/couchbase/cmake/require-git-checkout.cmake +25 -0
  33. data/ext/couchbase/cmake/tarball_glob.txt +49 -0
  34. data/ext/couchbase/core/agent_group.cxx +0 -8
  35. data/ext/couchbase/core/agent_group.hxx +0 -4
  36. data/ext/couchbase/core/analytics_stream.cxx +314 -0
  37. data/ext/couchbase/core/analytics_stream.hxx +129 -0
  38. data/ext/couchbase/core/analytics_stream_component.cxx +245 -0
  39. data/ext/couchbase/core/analytics_stream_component.hxx +67 -0
  40. data/ext/couchbase/core/app_telemetry_meter.cxx +25 -3
  41. data/ext/couchbase/core/app_telemetry_meter.hxx +77 -0
  42. data/ext/couchbase/core/app_telemetry_reporter.cxx +7 -6
  43. data/ext/couchbase/core/bucket.cxx +381 -87
  44. data/ext/couchbase/core/bucket.hxx +105 -25
  45. data/ext/couchbase/core/bucket_unit_test_api.hxx +57 -0
  46. data/ext/couchbase/core/capella.hxx +91 -0
  47. data/ext/couchbase/core/cluster.cxx +1554 -398
  48. data/ext/couchbase/core/cluster.hxx +39 -8
  49. data/ext/couchbase/core/cluster_agent.cxx +0 -8
  50. data/ext/couchbase/core/cluster_agent.hxx +0 -4
  51. data/ext/couchbase/core/cluster_options.hxx +26 -3
  52. data/ext/couchbase/core/collections_component.cxx +39 -15
  53. data/ext/couchbase/core/config_profiles.cxx +1 -1
  54. data/ext/couchbase/core/crud_component.cxx +2 -2
  55. data/ext/couchbase/core/crud_options.hxx +34 -0
  56. data/ext/couchbase/core/crypto/cbcrypto.cc +18 -13
  57. data/ext/couchbase/core/document_id_redaction.hxx +81 -0
  58. data/ext/couchbase/core/error_context/base_error_context.hxx +7 -6
  59. data/ext/couchbase/core/error_context/key_value.cxx +25 -2
  60. data/ext/couchbase/core/error_context/key_value.hxx +60 -33
  61. data/ext/couchbase/core/error_context/key_value_error_context.hxx +16 -15
  62. data/ext/couchbase/core/error_context/search.hxx +5 -0
  63. data/ext/couchbase/core/error_context/search_json.hxx +3 -0
  64. data/ext/couchbase/core/error_context/subdocument_error_context.hxx +19 -18
  65. data/ext/couchbase/core/error_context/view.hxx +5 -0
  66. data/ext/couchbase/core/free_form_http_request.cxx +237 -4
  67. data/ext/couchbase/core/free_form_http_request.hxx +41 -8
  68. data/ext/couchbase/core/http_component.cxx +300 -284
  69. data/ext/couchbase/core/http_component.hxx +0 -4
  70. data/ext/couchbase/core/impl/analytics.cxx +38 -5
  71. data/ext/couchbase/core/impl/analytics.hxx +34 -0
  72. data/ext/couchbase/core/impl/bootstrap_error.hxx +0 -3
  73. data/ext/couchbase/core/impl/collection.cxx +215 -202
  74. data/ext/couchbase/core/impl/collection_manager.cxx +1 -1
  75. data/ext/couchbase/core/impl/dns_srv_tracker.cxx +45 -18
  76. data/ext/couchbase/core/impl/error.cxx +22 -2
  77. data/ext/couchbase/core/impl/internal_analytics_stream_result.hxx +111 -0
  78. data/ext/couchbase/core/impl/internal_query_stream_result.hxx +110 -0
  79. data/ext/couchbase/core/impl/invoke_with_node_id.hxx +15 -7
  80. data/ext/couchbase/core/impl/key_value_error_category.cxx +6 -0
  81. data/ext/couchbase/core/impl/lookup_in_replica.cxx +10 -10
  82. data/ext/couchbase/core/impl/lookup_in_replica.hxx +4 -4
  83. data/ext/couchbase/core/impl/node_id.cxx +49 -13
  84. data/ext/couchbase/core/impl/observability_recorder.cxx +12 -2
  85. data/ext/couchbase/core/impl/observe_poll.cxx +63 -23
  86. data/ext/couchbase/core/impl/public_analytics_stream_result.cxx +372 -0
  87. data/ext/couchbase/core/impl/public_bucket.cxx +48 -2
  88. data/ext/couchbase/core/impl/public_cluster.cxx +325 -25
  89. data/ext/couchbase/core/impl/public_query_stream_result.cxx +380 -0
  90. data/ext/couchbase/core/impl/public_transaction_get_multi_replicas_from_preferred_server_group_result.cxx +42 -0
  91. data/ext/couchbase/core/impl/public_transaction_get_multi_result.cxx +42 -0
  92. data/ext/couchbase/core/impl/query.cxx +76 -7
  93. data/ext/couchbase/core/impl/query.hxx +36 -0
  94. data/ext/couchbase/core/impl/query_index_manager.cxx +54 -1
  95. data/ext/couchbase/core/impl/replica_utils.cxx +101 -0
  96. data/ext/couchbase/core/impl/replica_utils.hxx +64 -0
  97. data/ext/couchbase/core/impl/resolve_node_id.hxx +125 -0
  98. data/ext/couchbase/core/impl/scope.cxx +70 -0
  99. data/ext/couchbase/core/impl/search.cxx +31 -1
  100. data/ext/couchbase/core/impl/transactions.cxx +130 -0
  101. data/ext/couchbase/core/impl/wait_until_ready.cxx +439 -0
  102. data/ext/couchbase/core/impl/wait_until_ready.hxx +110 -0
  103. data/ext/couchbase/core/impl/with_bucket_config_or_timeout.hxx +180 -0
  104. data/ext/couchbase/core/impl/with_cancellation.hxx +11 -3
  105. data/ext/couchbase/core/io/configuration_belongs_to_session.hxx +66 -0
  106. data/ext/couchbase/core/io/dns_client.cxx +122 -45
  107. data/ext/couchbase/core/io/dns_codec.hxx +21 -21
  108. data/ext/couchbase/core/io/dns_config.cxx +21 -6
  109. data/ext/couchbase/core/io/http_command.hxx +149 -121
  110. data/ext/couchbase/core/io/http_error.hxx +107 -0
  111. data/ext/couchbase/core/io/http_parser.cxx +4 -0
  112. data/ext/couchbase/core/io/http_session.cxx +606 -154
  113. data/ext/couchbase/core/io/http_session.hxx +147 -30
  114. data/ext/couchbase/core/io/http_session_manager.hxx +329 -382
  115. data/ext/couchbase/core/io/http_streaming_parser.cxx +4 -0
  116. data/ext/couchbase/core/io/http_streaming_response.cxx +328 -43
  117. data/ext/couchbase/core/io/http_streaming_response.hxx +37 -3
  118. data/ext/couchbase/core/io/mcbp_buffer_pool.hxx +122 -0
  119. data/ext/couchbase/core/io/mcbp_command.hxx +150 -51
  120. data/ext/couchbase/core/io/mcbp_command_id.hxx +45 -0
  121. data/ext/couchbase/core/io/mcbp_message.cxx +9 -1
  122. data/ext/couchbase/core/io/mcbp_message.hxx +19 -0
  123. data/ext/couchbase/core/io/mcbp_output_queue.hxx +150 -0
  124. data/ext/couchbase/core/io/mcbp_parser.cxx +24 -7
  125. data/ext/couchbase/core/io/mcbp_session.cxx +316 -317
  126. data/ext/couchbase/core/io/mcbp_session.hxx +27 -18
  127. data/ext/couchbase/core/io/opaque_ring_table.hxx +145 -0
  128. data/ext/couchbase/core/io/retry_orchestrator.hxx +6 -5
  129. data/ext/couchbase/core/io/stream_deadline.hxx +50 -0
  130. data/ext/couchbase/core/io/streams.cxx +275 -14
  131. data/ext/couchbase/core/io/streams.hxx +53 -0
  132. data/ext/couchbase/core/logger/logger.cxx +36 -0
  133. data/ext/couchbase/core/logger/logger.hxx +46 -6
  134. data/ext/couchbase/core/logger/redaction.hxx +503 -0
  135. data/ext/couchbase/core/management/eventing_status.hxx +10 -0
  136. data/ext/couchbase/core/management/eventing_status_json.hxx +4 -0
  137. data/ext/couchbase/core/mcbp/big_endian.cxx +1 -1
  138. data/ext/couchbase/core/mcbp/codec.cxx +27 -18
  139. data/ext/couchbase/core/mcbp/operation_queue.cxx +2 -2
  140. data/ext/couchbase/core/mcbp/packet.hxx +2 -2
  141. data/ext/couchbase/core/mcbp/queue_request.cxx +23 -6
  142. data/ext/couchbase/core/mcbp/queue_request.hxx +21 -0
  143. data/ext/couchbase/core/meta/features.hxx +13 -0
  144. data/ext/couchbase/core/meta/version.cxx +6 -3
  145. data/ext/couchbase/core/metrics/logging_meter.cxx +5 -10
  146. data/ext/couchbase/core/metrics/meter_wrapper.cxx +63 -33
  147. data/ext/couchbase/core/metrics/meter_wrapper.hxx +55 -3
  148. data/ext/couchbase/core/operations/analytics_response_parsing.cxx +177 -0
  149. data/ext/couchbase/core/operations/analytics_response_parsing.hxx +55 -0
  150. data/ext/couchbase/core/operations/document_analytics.cxx +48 -130
  151. data/ext/couchbase/core/operations/document_analytics.hxx +14 -2
  152. data/ext/couchbase/core/operations/document_get_all_replicas.hxx +15 -7
  153. data/ext/couchbase/core/operations/document_get_any_replica.hxx +19 -8
  154. data/ext/couchbase/core/operations/document_get_projected.cxx +1 -1
  155. data/ext/couchbase/core/{impl/get_replica.cxx → operations/document_get_replica.cxx} +21 -3
  156. data/ext/couchbase/core/{impl/get_replica.hxx → operations/document_get_replica.hxx} +31 -4
  157. data/ext/couchbase/core/operations/document_lookup_in.cxx +10 -10
  158. data/ext/couchbase/core/operations/document_lookup_in_all_replicas.hxx +228 -198
  159. data/ext/couchbase/core/operations/document_lookup_in_any_replica.hxx +215 -217
  160. data/ext/couchbase/core/operations/document_query.cxx +108 -221
  161. data/ext/couchbase/core/operations/document_query.hxx +18 -4
  162. data/ext/couchbase/core/operations/document_search.cxx +52 -8
  163. data/ext/couchbase/core/operations/document_search.hxx +3 -0
  164. data/ext/couchbase/core/operations/document_view.cxx +3 -3
  165. data/ext/couchbase/core/operations/management/analytics_dataset_create.cxx +15 -8
  166. data/ext/couchbase/core/operations/management/analytics_dataset_create.hxx +4 -0
  167. data/ext/couchbase/core/operations/management/analytics_dataset_drop.cxx +11 -6
  168. data/ext/couchbase/core/operations/management/analytics_dataset_get_all.cxx +3 -2
  169. data/ext/couchbase/core/operations/management/analytics_dataverse_create.cxx +10 -5
  170. data/ext/couchbase/core/operations/management/analytics_dataverse_drop.cxx +10 -5
  171. data/ext/couchbase/core/operations/management/analytics_get_pending_mutations.cxx +2 -1
  172. data/ext/couchbase/core/operations/management/analytics_index_create.cxx +33 -8
  173. data/ext/couchbase/core/operations/management/analytics_index_drop.cxx +12 -7
  174. data/ext/couchbase/core/operations/management/analytics_index_get_all.cxx +3 -2
  175. data/ext/couchbase/core/operations/management/analytics_link_connect.cxx +11 -6
  176. data/ext/couchbase/core/operations/management/analytics_link_create.cxx +3 -3
  177. data/ext/couchbase/core/operations/management/analytics_link_disconnect.cxx +10 -4
  178. data/ext/couchbase/core/operations/management/analytics_link_drop.cxx +6 -4
  179. data/ext/couchbase/core/operations/management/analytics_link_get_all.cxx +4 -3
  180. data/ext/couchbase/core/operations/management/analytics_link_replace.cxx +3 -3
  181. data/ext/couchbase/core/operations/management/analytics_link_utils.hxx +1 -1
  182. data/ext/couchbase/core/operations/management/bucket_create.cxx +37 -38
  183. data/ext/couchbase/core/operations/management/bucket_update.cxx +26 -28
  184. data/ext/couchbase/core/operations/management/change_password.cxx +2 -0
  185. data/ext/couchbase/core/operations/management/collection_drop.cxx +5 -1
  186. data/ext/couchbase/core/operations/management/error_utils.cxx +59 -5
  187. data/ext/couchbase/core/operations/management/error_utils.hxx +29 -1
  188. data/ext/couchbase/core/operations/management/eventing_deploy_function.cxx +9 -3
  189. data/ext/couchbase/core/operations/management/eventing_drop_function.cxx +8 -3
  190. data/ext/couchbase/core/operations/management/eventing_get_all_functions.cxx +4 -2
  191. data/ext/couchbase/core/operations/management/eventing_get_function.cxx +5 -3
  192. data/ext/couchbase/core/operations/management/eventing_get_status.cxx +4 -2
  193. data/ext/couchbase/core/operations/management/eventing_pause_function.cxx +9 -3
  194. data/ext/couchbase/core/operations/management/eventing_resume_function.cxx +9 -3
  195. data/ext/couchbase/core/operations/management/eventing_undeploy_function.cxx +9 -3
  196. data/ext/couchbase/core/operations/management/eventing_upsert_function.cxx +9 -3
  197. data/ext/couchbase/core/operations/management/group_drop.cxx +3 -1
  198. data/ext/couchbase/core/operations/management/group_get.cxx +3 -1
  199. data/ext/couchbase/core/operations/management/group_upsert.cxx +11 -8
  200. data/ext/couchbase/core/operations/management/query_index_build.cxx +5 -2
  201. data/ext/couchbase/core/operations/management/query_index_create.cxx +9 -3
  202. data/ext/couchbase/core/operations/management/query_index_drop.cxx +11 -4
  203. data/ext/couchbase/core/operations/management/query_index_get_all.cxx +1 -1
  204. data/ext/couchbase/core/operations/management/query_index_get_all_deferred.cxx +1 -1
  205. data/ext/couchbase/core/operations/management/scope_drop.cxx +5 -1
  206. data/ext/couchbase/core/operations/management/scope_get_all.cxx +6 -1
  207. data/ext/couchbase/core/operations/management/search_get_stats.cxx +10 -0
  208. data/ext/couchbase/core/operations/management/search_index_analyze_document.cxx +3 -2
  209. data/ext/couchbase/core/operations/management/search_index_control_ingest.cxx +4 -3
  210. data/ext/couchbase/core/operations/management/search_index_control_plan_freeze.cxx +4 -3
  211. data/ext/couchbase/core/operations/management/search_index_control_query.cxx +4 -3
  212. data/ext/couchbase/core/operations/management/search_index_drop.cxx +2 -2
  213. data/ext/couchbase/core/operations/management/search_index_get.cxx +2 -2
  214. data/ext/couchbase/core/operations/management/search_index_get_documents_count.cxx +3 -2
  215. data/ext/couchbase/core/operations/management/search_index_get_stats.cxx +3 -1
  216. data/ext/couchbase/core/operations/management/search_index_upsert.cxx +2 -2
  217. data/ext/couchbase/core/operations/management/user_drop.cxx +3 -1
  218. data/ext/couchbase/core/operations/management/user_get.cxx +3 -1
  219. data/ext/couchbase/core/operations/management/user_upsert.cxx +12 -9
  220. data/ext/couchbase/core/operations/management/view_index_drop.cxx +1 -1
  221. data/ext/couchbase/core/operations/management/view_index_get.cxx +1 -1
  222. data/ext/couchbase/core/operations/management/view_index_upsert.cxx +1 -1
  223. data/ext/couchbase/core/operations/operation_traits.hxx +18 -0
  224. data/ext/couchbase/core/operations/query_response_parsing.cxx +211 -0
  225. data/ext/couchbase/core/operations/query_response_parsing.hxx +60 -0
  226. data/ext/couchbase/core/operations_fwd.hxx +3 -3
  227. data/ext/couchbase/core/origin.cxx +54 -26
  228. data/ext/couchbase/core/origin.hxx +12 -0
  229. data/ext/couchbase/core/orphan_reporter.cxx +2 -1
  230. data/ext/couchbase/core/platform/random.cc +7 -7
  231. data/ext/couchbase/core/protocol/client_request.cxx +2 -2
  232. data/ext/couchbase/core/protocol/client_request.hxx +38 -21
  233. data/ext/couchbase/core/protocol/client_response.cxx +11 -3
  234. data/ext/couchbase/core/protocol/client_response.hxx +27 -6
  235. data/ext/couchbase/core/protocol/cmd_append.cxx +2 -2
  236. data/ext/couchbase/core/protocol/cmd_cluster_map_change_notification.cxx +2 -2
  237. data/ext/couchbase/core/protocol/cmd_decrement.cxx +6 -6
  238. data/ext/couchbase/core/protocol/cmd_get.cxx +1 -1
  239. data/ext/couchbase/core/protocol/cmd_get_and_lock.cxx +2 -2
  240. data/ext/couchbase/core/protocol/cmd_get_and_touch.cxx +2 -2
  241. data/ext/couchbase/core/protocol/cmd_get_cluster_config.cxx +6 -4
  242. data/ext/couchbase/core/protocol/cmd_get_collection_id.cxx +2 -2
  243. data/ext/couchbase/core/protocol/cmd_get_error_map.cxx +1 -1
  244. data/ext/couchbase/core/protocol/cmd_get_meta.cxx +4 -4
  245. data/ext/couchbase/core/protocol/cmd_get_replica.cxx +1 -1
  246. data/ext/couchbase/core/protocol/cmd_hello.cxx +1 -1
  247. data/ext/couchbase/core/protocol/cmd_increment.cxx +6 -6
  248. data/ext/couchbase/core/protocol/cmd_insert.cxx +4 -4
  249. data/ext/couchbase/core/protocol/cmd_lookup_in.cxx +4 -3
  250. data/ext/couchbase/core/protocol/cmd_lookup_in_replica.cxx +4 -3
  251. data/ext/couchbase/core/protocol/cmd_mutate_in.cxx +10 -9
  252. data/ext/couchbase/core/protocol/cmd_mutate_in.hxx +10 -10
  253. data/ext/couchbase/core/protocol/cmd_observe_seqno.cxx +7 -7
  254. data/ext/couchbase/core/protocol/cmd_prepend.cxx +2 -2
  255. data/ext/couchbase/core/protocol/cmd_remove.cxx +2 -2
  256. data/ext/couchbase/core/protocol/cmd_replace.cxx +4 -4
  257. data/ext/couchbase/core/protocol/cmd_touch.cxx +1 -1
  258. data/ext/couchbase/core/protocol/cmd_upsert.cxx +4 -4
  259. data/ext/couchbase/core/protocol/datatype.hxx +118 -1
  260. data/ext/couchbase/core/protocol/frame_info_utils.cxx +1 -1
  261. data/ext/couchbase/core/protocol/magic.hxx +4 -0
  262. data/ext/couchbase/core/protocol/magic_fmt.hxx +3 -0
  263. data/ext/couchbase/core/protocol/server_request.hxx +3 -1
  264. data/ext/couchbase/core/protocol/status.cxx +1 -1
  265. data/ext/couchbase/core/protostellar/analytics_converter.hxx +171 -0
  266. data/ext/couchbase/core/protostellar/bucket_admin_converter.hxx +301 -0
  267. data/ext/couchbase/core/protostellar/collection_admin_converter.hxx +92 -0
  268. data/ext/couchbase/core/protostellar/component.cxx +2445 -0
  269. data/ext/couchbase/core/protostellar/component.hxx +391 -0
  270. data/ext/couchbase/core/{columnar/bootstrap_notification_subscriber.hxx → protostellar/compression_settings.hxx} +11 -10
  271. data/ext/couchbase/core/protostellar/credentials.cxx +233 -0
  272. data/ext/couchbase/core/protostellar/credentials.hxx +88 -0
  273. data/ext/couchbase/core/protostellar/dispatcher.cxx +57 -0
  274. data/ext/couchbase/core/protostellar/dispatcher.hxx +482 -0
  275. data/ext/couchbase/core/protostellar/error_utils.cxx +293 -0
  276. data/ext/couchbase/core/protostellar/error_utils.hxx +97 -0
  277. data/ext/couchbase/core/protostellar/json_payload.hxx +49 -0
  278. data/ext/couchbase/core/protostellar/kv_converter.cxx +70 -0
  279. data/ext/couchbase/core/protostellar/kv_converter.hxx +600 -0
  280. data/ext/couchbase/core/protostellar/query_converter.hxx +265 -0
  281. data/ext/couchbase/core/protostellar/query_index_admin_converter.hxx +291 -0
  282. data/ext/couchbase/core/protostellar/query_proto.hxx +73 -0
  283. data/ext/couchbase/core/protostellar/search_converter.hxx +244 -0
  284. data/ext/couchbase/core/protostellar/search_index_admin_converter.hxx +156 -0
  285. data/ext/couchbase/core/protostellar/view_converter.hxx +158 -0
  286. data/ext/couchbase/core/query_stream.cxx +447 -0
  287. data/ext/couchbase/core/query_stream.hxx +141 -0
  288. data/ext/couchbase/core/query_stream_component.cxx +243 -0
  289. data/ext/couchbase/core/query_stream_component.hxx +68 -0
  290. data/ext/couchbase/core/range_scan_load_balancer.cxx +15 -8
  291. data/ext/couchbase/core/range_scan_orchestrator.cxx +15 -3
  292. data/ext/couchbase/core/response_handler.hxx +41 -4
  293. data/ext/couchbase/core/row_streamer.cxx +332 -46
  294. data/ext/couchbase/core/row_streamer.hxx +31 -1
  295. data/ext/couchbase/core/row_streamer_options.hxx +55 -0
  296. data/ext/couchbase/core/sasl/client.h +3 -0
  297. data/ext/couchbase/core/search_scoring.hxx +66 -0
  298. data/ext/couchbase/core/stream_error_details.hxx +69 -0
  299. data/ext/couchbase/core/timeout_defaults.hxx +0 -1
  300. data/ext/couchbase/core/topology/capabilities.hxx +6 -0
  301. data/ext/couchbase/core/topology/capabilities_fmt.hxx +3 -0
  302. data/ext/couchbase/core/topology/configuration.cxx +21 -6
  303. data/ext/couchbase/core/topology/configuration.hxx +29 -8
  304. data/ext/couchbase/core/topology/configuration_json.hxx +3 -0
  305. data/ext/couchbase/core/topology/error_map_json.hxx +3 -1
  306. data/ext/couchbase/core/tracing/threshold_logging_tracer.cxx +70 -4
  307. data/ext/couchbase/core/tracing/threshold_logging_tracer.hxx +10 -0
  308. data/ext/couchbase/core/transactions/active_transaction_record.cxx +0 -34
  309. data/ext/couchbase/core/transactions/attempt_context_impl.cxx +362 -241
  310. data/ext/couchbase/core/transactions/attempt_context_impl.hxx +24 -3
  311. data/ext/couchbase/core/transactions/error_list.hxx +2 -2
  312. data/ext/couchbase/core/transactions/get_multi_fetch.hxx +160 -0
  313. data/ext/couchbase/core/transactions/get_multi_orchestrator.cxx +326 -125
  314. data/ext/couchbase/core/transactions/get_multi_transaction_id.hxx +62 -0
  315. data/ext/couchbase/core/transactions/internal/atr_entry.hxx +22 -2
  316. data/ext/couchbase/core/transactions/internal/transaction_context.hxx +2 -2
  317. data/ext/couchbase/core/transactions/internal/transactions_cleanup.hxx +23 -1
  318. data/ext/couchbase/core/transactions/internal/utils.hxx +50 -14
  319. data/ext/couchbase/core/transactions/staged_mutation.cxx +23 -18
  320. data/ext/couchbase/core/transactions/staged_mutation.hxx +15 -4
  321. data/ext/couchbase/core/transactions/transaction_context.cxx +55 -40
  322. data/ext/couchbase/core/transactions/transaction_get_result.hxx +16 -0
  323. data/ext/couchbase/core/transactions/transactions.cxx +3 -55
  324. data/ext/couchbase/core/transactions/transactions_cleanup.cxx +194 -66
  325. data/ext/couchbase/core/transactions/transactions_config.cxx +0 -11
  326. data/ext/couchbase/core/transactions/utils.cxx +10 -0
  327. data/ext/couchbase/core/transactions/waitable_op_list.hxx +15 -4
  328. data/ext/couchbase/core/transactions.hxx +9 -9
  329. data/ext/couchbase/core/utils/byteswap.hxx +166 -9
  330. data/ext/couchbase/core/utils/connection_string.cxx +50 -85
  331. data/ext/couchbase/core/utils/connection_string.hxx +15 -0
  332. data/ext/couchbase/core/{columnar/backoff_calculator.hxx → utils/deadline.hxx} +13 -13
  333. data/ext/couchbase/core/utils/duration_parser.cxx +1 -1
  334. data/ext/couchbase/core/utils/json_streaming_lexer.cxx +48 -5
  335. data/ext/couchbase/core/utils/json_streaming_lexer.hxx +4 -1
  336. data/ext/couchbase/core/utils/movable_function.hxx +301 -52
  337. data/ext/couchbase/core/utils/name_codec.hxx +154 -11
  338. data/ext/couchbase/core/{columnar/retry_info.hxx → utils/process_id.hxx} +18 -13
  339. data/ext/couchbase/core/utils/url_codec.cxx +12 -51
  340. data/ext/couchbase/core/websocket_codec.cxx +3 -29
  341. data/ext/couchbase/couchbase/analytics_options.hxx +21 -10
  342. data/ext/couchbase/couchbase/analytics_row.hxx +105 -0
  343. data/ext/couchbase/couchbase/analytics_stream_result.hxx +266 -0
  344. data/ext/couchbase/couchbase/boolean_query.hxx +3 -3
  345. data/ext/couchbase/couchbase/bucket.hxx +57 -0
  346. data/ext/couchbase/couchbase/cluster.hxx +216 -5
  347. data/ext/couchbase/{core/columnar/security_options.hxx → couchbase/cluster_state.hxx} +18 -14
  348. data/ext/couchbase/couchbase/codec/lenient_json_transcoder.hxx +69 -0
  349. data/ext/couchbase/couchbase/collection.hxx +234 -14
  350. data/ext/couchbase/couchbase/common_durability_options.hxx +18 -3
  351. data/ext/couchbase/couchbase/conjunction_query.hxx +1 -1
  352. data/ext/couchbase/couchbase/create_dataset_analytics_options.hxx +6 -1
  353. data/ext/couchbase/couchbase/date_range_query.hxx +2 -2
  354. data/ext/couchbase/couchbase/decrement_options.hxx +1 -1
  355. data/ext/couchbase/couchbase/disjunction_query.hxx +1 -1
  356. data/ext/couchbase/couchbase/error.hxx +32 -0
  357. data/ext/couchbase/couchbase/error_codes.hxx +32 -0
  358. data/ext/couchbase/couchbase/geo_bounding_box_query.hxx +1 -1
  359. data/ext/couchbase/couchbase/geo_distance_query.hxx +1 -1
  360. data/ext/couchbase/couchbase/geo_polygon_query.hxx +1 -1
  361. data/ext/couchbase/couchbase/get_replica_options.hxx +68 -0
  362. data/ext/couchbase/couchbase/get_replica_result.hxx +5 -3
  363. data/ext/couchbase/couchbase/get_replica_strategy.hxx +161 -0
  364. data/ext/couchbase/couchbase/get_result.hxx +1 -0
  365. data/ext/couchbase/couchbase/increment_options.hxx +1 -1
  366. data/ext/couchbase/couchbase/insert_options.hxx +1 -1
  367. data/ext/couchbase/couchbase/match_phrase_query.hxx +1 -1
  368. data/ext/couchbase/couchbase/match_query.hxx +1 -1
  369. data/ext/couchbase/couchbase/mutate_in_options.hxx +3 -3
  370. data/ext/couchbase/couchbase/network_options.hxx +1 -1
  371. data/ext/couchbase/couchbase/node_id.hxx +42 -14
  372. data/ext/couchbase/couchbase/node_id_for_options.hxx +7 -1
  373. data/ext/couchbase/couchbase/node_ids_options.hxx +8 -2
  374. data/ext/couchbase/couchbase/numeric_range_query.hxx +1 -1
  375. data/ext/couchbase/couchbase/phrase_query.hxx +1 -1
  376. data/ext/couchbase/couchbase/prefix_query.hxx +1 -1
  377. data/ext/couchbase/couchbase/query_options.hxx +23 -12
  378. data/ext/couchbase/couchbase/query_row.hxx +111 -0
  379. data/ext/couchbase/couchbase/query_stream_result.hxx +302 -0
  380. data/ext/couchbase/couchbase/query_string_query.hxx +3 -3
  381. data/ext/couchbase/couchbase/regexp_query.hxx +1 -1
  382. data/ext/couchbase/couchbase/replace_options.hxx +3 -3
  383. data/ext/couchbase/couchbase/result.hxx +14 -3
  384. data/ext/couchbase/couchbase/scan_result_item.hxx +1 -0
  385. data/ext/couchbase/couchbase/scope.hxx +85 -2
  386. data/ext/couchbase/couchbase/search_options.hxx +58 -8
  387. data/ext/couchbase/couchbase/search_scoring.hxx +94 -0
  388. data/ext/couchbase/couchbase/search_scoring_none.hxx +51 -0
  389. data/ext/couchbase/couchbase/search_scoring_reciprocal_rank_fusion.hxx +88 -0
  390. data/ext/couchbase/couchbase/search_scoring_relative_score_fusion.hxx +70 -0
  391. data/ext/couchbase/couchbase/term_range_query.hxx +1 -1
  392. data/ext/couchbase/couchbase/tracing/request_span.hxx +46 -0
  393. data/ext/couchbase/couchbase/transactions/transaction_get_multi_replicas_from_preferred_server_group_result.hxx +23 -21
  394. data/ext/couchbase/couchbase/transactions/transaction_get_multi_result.hxx +24 -19
  395. data/ext/couchbase/couchbase/transactions/transaction_get_result.hxx +17 -3
  396. data/ext/couchbase/couchbase/transactions/transactions_config.hxx +4 -2
  397. data/ext/couchbase/couchbase/transactions.hxx +27 -18
  398. data/ext/couchbase/couchbase/upsert_options.hxx +3 -3
  399. data/ext/couchbase/couchbase/vector_query.hxx +1 -1
  400. data/ext/couchbase/couchbase/wait_until_ready_options.hxx +111 -0
  401. data/ext/couchbase/couchbase/wildcard_query.hxx +1 -1
  402. data/ext/extconf.rb +15 -10
  403. data/ext/rcb_analytics.cxx +82 -102
  404. data/ext/rcb_backend.cxx +42 -36
  405. data/ext/rcb_backend.hxx +2 -0
  406. data/ext/rcb_buckets.cxx +47 -59
  407. data/ext/rcb_collections.cxx +42 -52
  408. data/ext/rcb_crud.cxx +345 -224
  409. data/ext/rcb_diagnostics.cxx +117 -27
  410. data/ext/rcb_exceptions.cxx +152 -99
  411. data/ext/rcb_exceptions.hxx +25 -0
  412. data/ext/rcb_extras.cxx +18 -19
  413. data/ext/rcb_hdr_histogram.cxx +19 -4
  414. data/ext/rcb_logger.cxx +202 -27
  415. data/ext/rcb_logger.hxx +12 -0
  416. data/ext/rcb_multi.cxx +40 -40
  417. data/ext/rcb_observability.cxx +7 -5
  418. data/ext/rcb_query.cxx +99 -142
  419. data/ext/rcb_range_scan.cxx +41 -35
  420. data/ext/rcb_search.cxx +98 -99
  421. data/ext/rcb_users.cxx +36 -56
  422. data/ext/rcb_utils.cxx +100 -37
  423. data/ext/rcb_utils.hxx +287 -33
  424. data/ext/rcb_version.cxx +1 -1
  425. data/ext/rcb_views.cxx +55 -51
  426. data/lib/active_support/cache/couchbase_store.rb +77 -12
  427. data/lib/couchbase/bucket.rb +20 -0
  428. data/lib/couchbase/cluster.rb +33 -14
  429. data/lib/couchbase/collection.rb +36 -1
  430. data/lib/couchbase/errors.rb +18 -0
  431. data/lib/couchbase/fork_hooks.rb +16 -7
  432. data/lib/couchbase/get_replica_strategy.rb +89 -0
  433. data/lib/couchbase/logger.rb +1 -1
  434. data/lib/couchbase/management/analytics_index_manager.rb +15 -15
  435. data/lib/couchbase/management/bucket_manager.rb +6 -6
  436. data/lib/couchbase/management/collection_manager.rb +6 -6
  437. data/lib/couchbase/management/query_index_manager.rb +7 -7
  438. data/lib/couchbase/management/search_index_manager.rb +13 -13
  439. data/lib/couchbase/management/user_manager.rb +10 -10
  440. data/lib/couchbase/management/view_index_manager.rb +5 -5
  441. data/lib/couchbase/options.rb +181 -44
  442. data/lib/couchbase/protostellar/bucket.rb +4 -0
  443. data/lib/couchbase/protostellar/cluster.rb +4 -0
  444. data/lib/couchbase/protostellar/collection.rb +4 -0
  445. data/lib/couchbase/protostellar/error_handling.rb +2 -1
  446. data/lib/couchbase/protostellar/request.rb +1 -0
  447. data/lib/couchbase/protostellar/request_generator/kv.rb +16 -2
  448. data/lib/couchbase/protostellar/request_generator/search.rb +17 -1
  449. data/lib/couchbase/protostellar/retry/orchestrator.rb +3 -2
  450. data/lib/couchbase/protostellar/retry/strategies/fail_fast.rb +33 -0
  451. data/lib/couchbase/protostellar/retry/strategies.rb +1 -0
  452. data/lib/couchbase/search_options.rb +95 -6
  453. data/lib/couchbase/version.rb +1 -1
  454. metadata +92 -33
  455. data/ext/0001-fix-build-for-mingw-w64-ucrt-x86_64-toolchain.patch +0 -40
  456. data/ext/couchbase/core/columnar/agent.hxx +0 -71
  457. data/ext/couchbase/core/columnar/agent_config.hxx +0 -59
  458. data/ext/couchbase/core/columnar/background_bootstrap_listener.hxx +0 -42
  459. data/ext/couchbase/core/columnar/backoff_calculator.cxx +0 -62
  460. data/ext/couchbase/core/columnar/columnar_agent.cxx +0 -147
  461. data/ext/couchbase/core/columnar/columnar_agent_config.cxx +0 -48
  462. data/ext/couchbase/core/columnar/columnar_error.cxx +0 -51
  463. data/ext/couchbase/core/columnar/database_management_options.hxx +0 -56
  464. data/ext/couchbase/core/columnar/error.hxx +0 -51
  465. data/ext/couchbase/core/columnar/error_codes.cxx +0 -107
  466. data/ext/couchbase/core/columnar/error_codes.hxx +0 -75
  467. data/ext/couchbase/core/columnar/management_component.cxx +0 -300
  468. data/ext/couchbase/core/columnar/management_component.hxx +0 -56
  469. data/ext/couchbase/core/columnar/query_component.cxx +0 -523
  470. data/ext/couchbase/core/columnar/query_component.hxx +0 -57
  471. data/ext/couchbase/core/columnar/query_options.hxx +0 -59
  472. data/ext/couchbase/core/columnar/query_result.cxx +0 -130
  473. data/ext/couchbase/core/columnar/query_result.hxx +0 -78
  474. data/ext/couchbase/core/io/config_tracker.cxx +0 -687
  475. data/ext/couchbase/core/io/config_tracker.hxx +0 -123
@@ -34,4 +34,22 @@ struct is_cancellable_operation : public std::false_type {
34
34
 
35
35
  template<typename T>
36
36
  inline constexpr bool is_cancellable_operation_v = is_cancellable_operation<T>::value;
37
+
38
+ /**
39
+ * Operations that pick the node to dispatch to themselves, instead of being
40
+ * routed by the vbucket map alone.
41
+ *
42
+ * Specialize this only for a request that provides
43
+ * @c resolve_route(const topology::configuration&) returning an
44
+ * @c std::optional<impl::replica_route_decision>, and a writable @c partition
45
+ * member: that is the whole interface @c bucket::map_and_send() calls through
46
+ * this trait. An empty optional declines self-routing for that request, and the
47
+ * vbucket-map path routes it instead.
48
+ */
49
+ template<typename T>
50
+ struct resolves_own_route : public std::false_type {
51
+ };
52
+
53
+ template<typename T>
54
+ inline constexpr bool resolves_own_route_v = resolves_own_route<T>::value;
37
55
  } // namespace couchbase::core::operations
@@ -0,0 +1,211 @@
1
+ /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Copyright 2020-2021 Couchbase, Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ #include "query_response_parsing.hxx"
19
+
20
+ #include "core/operations/management/error_utils.hxx"
21
+ #include "core/utils/contains_string.hxx"
22
+ #include "core/utils/duration_parser.hxx"
23
+ #include "core/utils/json.hxx"
24
+
25
+ #include <couchbase/error_codes.hxx>
26
+
27
+ #include <tao/json/value.hpp>
28
+
29
+ namespace couchbase::core::operations
30
+ {
31
+
32
+ auto
33
+ parse_query_meta(const tao::json::value& payload) -> query_response::query_meta_data
34
+ {
35
+ query_response::query_meta_data meta{};
36
+
37
+ if (const auto* i = payload.find("requestID"); i != nullptr) {
38
+ meta.request_id = i->get_string();
39
+ }
40
+ if (const auto* i = payload.find("clientContextID"); i != nullptr) {
41
+ meta.client_context_id = i->get_string();
42
+ }
43
+ if (const auto* s = payload.find("status"); s != nullptr) {
44
+ meta.status = s->get_string();
45
+ }
46
+ if (const auto* s = payload.find("signature"); s != nullptr) {
47
+ meta.signature = couchbase::core::utils::json::generate(*s);
48
+ }
49
+ if (const auto* p = payload.find("profile"); p != nullptr) {
50
+ meta.profile = couchbase::core::utils::json::generate(*p);
51
+ }
52
+
53
+ if (const auto* m = payload.find("metrics"); m != nullptr) {
54
+ query_response::query_metrics metrics{};
55
+ metrics.result_count = m->at("resultCount").get_unsigned();
56
+ metrics.result_size = m->at("resultSize").get_unsigned();
57
+ metrics.elapsed_time = utils::parse_duration(m->at("elapsedTime").get_string());
58
+ metrics.execution_time = utils::parse_duration(m->at("executionTime").get_string());
59
+ metrics.sort_count = m->template optional<std::uint64_t>("sortCount").value_or(0);
60
+ metrics.mutation_count = m->template optional<std::uint64_t>("mutationCount").value_or(0);
61
+ metrics.error_count = m->template optional<std::uint64_t>("errorCount").value_or(0);
62
+ metrics.warning_count = m->template optional<std::uint64_t>("warningCount").value_or(0);
63
+ meta.metrics.emplace(metrics);
64
+ }
65
+
66
+ if (const auto* e = payload.find("errors"); e != nullptr) {
67
+ std::vector<query_response::query_problem> problems{};
68
+ for (const auto& err : e->get_array()) {
69
+ query_response::query_problem problem;
70
+ problem.code = err.at("code").get_unsigned();
71
+ problem.message = err.at("msg").get_string();
72
+ if (const auto* reason = err.find("reason"); reason != nullptr && reason->is_object()) {
73
+ problem.reason = reason->optional<std::uint64_t>("code");
74
+ problem.retry = reason->optional<bool>("retry");
75
+ }
76
+ problems.emplace_back(problem);
77
+ }
78
+ meta.errors.emplace(problems);
79
+ }
80
+
81
+ if (const auto* w = payload.find("warnings"); w != nullptr) {
82
+ std::vector<query_response::query_problem> problems{};
83
+ for (const auto& warn : w->get_array()) {
84
+ query_response::query_problem problem;
85
+ problem.code = warn.at("code").get_unsigned();
86
+ problem.message = warn.at("msg").get_string();
87
+ problems.emplace_back(problem);
88
+ }
89
+ meta.warnings.emplace(problems);
90
+ }
91
+
92
+ return meta;
93
+ }
94
+
95
+ auto
96
+ map_query_error(const query_response::query_meta_data& meta, std::uint32_t http_status)
97
+ -> std::error_code
98
+ {
99
+ const auto unmatched =
100
+ http_status == 400 ? errc::common::invalid_argument : errc::common::internal_server_failure;
101
+
102
+ if (meta.status == "success" && http_status != 400) {
103
+ return {};
104
+ }
105
+
106
+ if (!meta.errors || meta.errors->empty()) {
107
+ /* Unreachable from make_response, which only calls map_query_error after confirming
108
+ * errors is non-empty; present for the streaming-path caller, which has no such guard. */
109
+ return unmatched;
110
+ }
111
+
112
+ const auto& first = meta.errors->front();
113
+ const auto first_code = first.code;
114
+ const auto& first_message = first.message;
115
+
116
+ std::error_code ec{};
117
+
118
+ switch (first_code) {
119
+ case 1065: /* IKey: "service.io.request.unrecognized_parameter" */
120
+ if ((first_message.find("Unrecognized parameter in request") != std::string::npos) &&
121
+ (first_message.find("preserve_expiry") != std::string::npos)) {
122
+ ec = errc::common::feature_not_available;
123
+ } else {
124
+ ec = errc::common::invalid_argument;
125
+ }
126
+ break;
127
+ case 1080: /* IKey: "timeout" */
128
+ ec = errc::common::unambiguous_timeout;
129
+ break;
130
+ case 3000: /* IKey: "parse.syntax_error" */
131
+ ec = errc::common::parsing_failure;
132
+ break;
133
+ case 4040: /* IKey: "plan.build_prepared.no_such_name" */
134
+ case 4050: /* IKey: "plan.build_prepared.unrecognized_prepared" */
135
+ case 4060: /* IKey: "plan.build_prepared.no_such_name" */
136
+ case 4070: /* IKey: "plan.build_prepared.decoding" */
137
+ case 4080: /* IKey: "plan.build_prepared.name_encoded_plan_mismatch" */
138
+ case 4090: /* IKey: "plan.build_prepared.name_not_in_encoded_plan" */
139
+ /* NOTE: make_response also does cache.erase + throw retry_http_request for codes
140
+ * 4040/4050/4070. That stateful logic stays in make_response. This pure classifier
141
+ * returns prepared_statement_failure so callers (e.g. streaming path) get a
142
+ * non-empty error_code. */
143
+ ec = errc::query::prepared_statement_failure;
144
+ break;
145
+ case 4300: /* IKey: "plan.new_index_already_exists" */
146
+ ec = errc::common::index_exists;
147
+ break;
148
+ case 5000: /* IKey: "Internal Error" */
149
+ if (utils::contains_string(first_message, "index", true) &&
150
+ utils::contains_string(first_message, "already exist", true)) {
151
+ ec = errc::common::index_exists;
152
+ } else if (utils::contains_string(first_message, "Index does not exist") ||
153
+ (utils::contains_string(first_message, "index", true) &&
154
+ utils::contains_string(first_message, "not found", true))) {
155
+ ec = errc::common::index_not_found;
156
+ } else if (first_message.find("Bucket Not Found") != std::string::npos) {
157
+ ec = errc::common::bucket_not_found;
158
+ }
159
+ break;
160
+ case 12009: /* IKey: "datastore.couchbase.DML_error" */
161
+ if (first_message.find("CAS mismatch") != std::string::npos) {
162
+ ec = errc::common::cas_mismatch;
163
+ } else {
164
+ switch (first.reason.value_or(0)) {
165
+ case 12033:
166
+ ec = errc::common::cas_mismatch;
167
+ break;
168
+ case 17014:
169
+ ec = errc::key_value::document_not_found;
170
+ break;
171
+ case 17012:
172
+ ec = errc::key_value::document_exists;
173
+ break;
174
+ default:
175
+ ec = errc::query::dml_failure;
176
+ break;
177
+ }
178
+ }
179
+ break;
180
+ case 12004: /* IKey: "datastore.couchbase.primary_idx_not_found" */
181
+ case 12016: /* IKey: "datastore.couchbase.index_not_found" */
182
+ ec = errc::common::index_not_found;
183
+ break;
184
+ case 13014: /* IKey: "datastore.couchbase.insufficient_credentials" */
185
+ ec = errc::common::authentication_failure;
186
+ break;
187
+ default:
188
+ if ((first_code >= 12000 && first_code < 13000) ||
189
+ (first_code >= 14000 && first_code < 15000)) {
190
+ ec = errc::query::index_failure;
191
+ } else if (first_code >= 4000 && first_code < 5000) {
192
+ ec = errc::query::planning_failure;
193
+ }
194
+ break;
195
+ }
196
+
197
+ if (!ec) {
198
+ auto common_ec = management::extract_common_query_error_code(first_code, first_message);
199
+ if (common_ec) {
200
+ ec = common_ec.value();
201
+ }
202
+ }
203
+
204
+ if (!ec) {
205
+ ec = unmatched;
206
+ }
207
+
208
+ return ec;
209
+ }
210
+
211
+ } // namespace couchbase::core::operations
@@ -0,0 +1,60 @@
1
+ /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Copyright 2020-2021 Couchbase, Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ #pragma once
19
+
20
+ #include "core/operations/document_query.hxx"
21
+
22
+ #include <couchbase/error_codes.hxx>
23
+
24
+ #include <tao/json/forward.hpp>
25
+
26
+ #include <cstdint>
27
+ #include <system_error>
28
+
29
+ namespace couchbase::core::operations
30
+ {
31
+
32
+ /**
33
+ * Parse query meta-data fields (status, metrics, warnings, errors, signature, profile,
34
+ * requestID, clientContextID) from a top-level response payload.
35
+ *
36
+ * Pure function — no side effects, no access to request state.
37
+ */
38
+ auto
39
+ parse_query_meta(const tao::json::value& payload) -> query_response::query_meta_data;
40
+
41
+ /**
42
+ * Map query meta-data to an error_code.
43
+ *
44
+ * Pure classifier — no side effects, no cache mutations, no exceptions thrown.
45
+ * All prepared-statement codes (4040/4050/4060/4070/4080/4090) are classified as
46
+ * prepared_statement_failure here; the cache-erase + retry_http_request throw remains in
47
+ * make_response and applies only to the 4040/4050/4070 subset.
48
+ *
49
+ * Returns an empty error_code when the query succeeded (meta.status == "success", http_status is
50
+ * not 400, and no prepared-statement retry needed).
51
+ *
52
+ * http_status is the status of the response that carried the metadata, or 0 where there is none.
53
+ * A failure that matches no specific mapping is invalid_argument for an HTTP 400 (RFC-58) and
54
+ * internal_server_failure otherwise.
55
+ */
56
+ [[nodiscard]] auto
57
+ map_query_error(const query_response::query_meta_data& meta, std::uint32_t http_status = 0)
58
+ -> std::error_code;
59
+
60
+ } // namespace couchbase::core::operations
@@ -28,8 +28,6 @@ struct s3_external_link;
28
28
 
29
29
  namespace impl
30
30
  {
31
- struct get_replica_request;
32
- struct get_replica_response;
33
31
  struct lookup_in_replica_request;
34
32
  struct lookup_in_replica_response;
35
33
  struct observe_seqno_request;
@@ -51,6 +49,8 @@ struct decrement_response;
51
49
  struct exists_request;
52
50
  struct exists_response;
53
51
  struct get_request;
52
+ struct get_replica_request;
53
+ struct get_replica_response;
54
54
  struct get_response;
55
55
  struct get_all_replicas_request;
56
56
  struct get_all_replicas_response;
@@ -106,7 +106,7 @@ using replace_request_with_legacy_durability = impl::with_legacy_durability<repl
106
106
  using upsert_request_with_legacy_durability = impl::with_legacy_durability<upsert_request>;
107
107
 
108
108
  using get_request_with_cancellation = impl::with_cancellation<get_request>;
109
- using get_replica_request_with_cancellation = impl::with_cancellation<impl::get_replica_request>;
109
+ using get_replica_request_with_cancellation = impl::with_cancellation<get_replica_request>;
110
110
  using lookup_in_request_with_cancellation = impl::with_cancellation<lookup_in_request>;
111
111
  using lookup_in_replica_request_with_cancellation =
112
112
  impl::with_cancellation<impl::lookup_in_replica_request>;
@@ -16,7 +16,6 @@
16
16
  */
17
17
 
18
18
  #include "origin.hxx"
19
- #include <couchbase/build_config.hxx>
20
19
 
21
20
  #include "core/utils/connection_string.hxx"
22
21
  #include "topology/configuration.hxx"
@@ -224,24 +223,6 @@ struct traits<couchbase::transactions::transactions_config::built> {
224
223
  }
225
224
  };
226
225
 
227
- template<>
228
- struct traits<couchbase::core::columnar::security_options> {
229
- template<template<typename...> class Traits>
230
- static void assign(tao::json::basic_value<Traits>& v,
231
- const couchbase::core::columnar::security_options& o)
232
- {
233
- v = {
234
- { "trust_only_capella", o.trust_only_capella },
235
- { "trust_only_pem_file", o.trust_only_pem_file },
236
- { "trust_only_pem_string", o.trust_only_pem_string },
237
- { "trust_only_platform", o.trust_only_platform },
238
- { "trust_only_certificates", o.trust_only_certificates.size() },
239
- // TODO(JC): add if/when we support the cipher_suites option
240
- // { "cipher_suites", utils::join_strings(o.cipher_suites, ":") },
241
- };
242
- }
243
- };
244
-
245
226
  } // namespace tao::json
246
227
 
247
228
  namespace couchbase::core
@@ -267,13 +248,10 @@ origin::to_json() const -> std::string
267
248
  { "config_poll_floor", options_.config_poll_floor },
268
249
  { "user_agent_extra", options_.user_agent_extra },
269
250
  { "dump_configuration", options_.dump_configuration },
251
+ { "log_redaction", options_.log_redaction },
270
252
  { "disable_mozilla_ca_certificates", options_.disable_mozilla_ca_certificates },
271
253
  { "network", options_.network },
272
254
  { "tls_verify", options_.tls_verify },
273
- #ifdef COUCHBASE_CXX_CLIENT_COLUMNAR
274
- { "dispatch_timeout", options_.dispatch_timeout },
275
- { "security_options", options_.security_options },
276
- #else
277
255
  { "key_value_timeout", options_.key_value_timeout },
278
256
  { "key_value_durable_timeout", options_.key_value_durable_timeout },
279
257
  { "view_timeout", options_.view_timeout },
@@ -297,7 +275,6 @@ origin::to_json() const -> std::string
297
275
  { "orphan_reporter_options", options_.orphan_options },
298
276
  { "transactions_options", options_.transactions },
299
277
  { "server_group", options_.server_group },
300
- #endif
301
278
  },
302
279
  },
303
280
  };
@@ -311,6 +288,9 @@ origin::to_json() const -> std::string
311
288
  }
312
289
  json["bootstrap_nodes"] = nodes;
313
290
  }
291
+ // Every value in here is left as it is. The document this returns is annotated as a whole at
292
+ // the log site, because a tag written into one of its string values would be read back as part
293
+ // of that value by anything that parses the line as JSON.
314
294
  return tao::json::to_string(json);
315
295
  }
316
296
 
@@ -319,9 +299,15 @@ origin::to_json() const -> std::string
319
299
  couchbase::core::origin::origin(origin&& other) noexcept
320
300
  : options_(std::move(other.options_))
321
301
  , nodes_(std::move(other.nodes_))
322
- , next_node_(other.next_node_)
302
+ // next_node_ is an iterator into nodes_. Container move construction transfers the buffer, so
303
+ // iterators into the source stay valid and now denote elements of nodes_ -- other.next_node_ can
304
+ // be adopted as-is, preserving the round-robin position. The empty case is guarded separately
305
+ // because that guarantee does not extend to a past-the-end iterator. nodes_ is declared before
306
+ // next_node_, so it is already initialized here.
307
+ , next_node_(nodes_.empty() ? nodes_.begin() : other.next_node_)
323
308
  , exhausted_(other.exhausted_)
324
309
  , connection_string_(std::move(other.connection_string_))
310
+ , uses_protostellar_(other.uses_protostellar_)
325
311
  , credentials_(std::move(other.credentials_))
326
312
  {
327
313
  }
@@ -330,20 +316,38 @@ auto
330
316
  couchbase::core::origin::operator=(origin&& other) noexcept -> origin&
331
317
  {
332
318
  if (this != &other) {
319
+ const auto offset = other.nodes_.empty() ? 0 : other.next_node_ - other.nodes_.begin();
333
320
  options_ = std::move(other.options_);
334
321
  nodes_ = std::move(other.nodes_);
335
- next_node_ = other.next_node_;
322
+ next_node_ = nodes_.begin() + offset;
336
323
  exhausted_ = other.exhausted_;
337
324
  connection_string_ = std::move(other.connection_string_);
325
+ uses_protostellar_ = other.uses_protostellar_;
338
326
  credentials_ = std::move(other.credentials_);
339
327
  }
340
328
  return *this;
341
329
  }
342
330
 
331
+ // A copy is a fresh origin that has not attempted anything, so the rotation cursor is deliberately
332
+ // reset rather than carried. This matters: next_address() marks an origin exhausted as it hands out
333
+ // the *last* node, which on a single-node cluster is the very first call, so a cluster origin is
334
+ // normally exhausted immediately after bootstrap. open_bucket() copies that origin into every
335
+ // bucket and on into every session, and mcbp_session::initiate_bootstrap() tests exhausted()
336
+ // before it ever calls next_address() -- so carrying the flag would send a session that has tried
337
+ // nothing down the "reached the end of the list of bootstrap nodes" path: an unconditional 500 ms
338
+ // backoff.
339
+ //
340
+ // Moving, by contrast, does carry it: a move transfers identity rather than producing an
341
+ // independent origin.
342
+ //
343
+ // connection_string_ and uses_protostellar_ *are* copied. They were being dropped entirely, which
344
+ // left connection_string() returning "" on any copied origin.
343
345
  couchbase::core::origin::origin(const couchbase::core::origin& other)
344
346
  : options_(other.options_)
345
347
  , nodes_(other.nodes_)
346
348
  , next_node_(nodes_.begin())
349
+ , connection_string_(other.connection_string_)
350
+ , uses_protostellar_(other.uses_protostellar_)
347
351
  {
348
352
  update_credentials(other.credentials());
349
353
  }
@@ -378,6 +382,7 @@ couchbase::core::origin::origin(couchbase::core::cluster_credentials auth,
378
382
  const couchbase::core::utils::connection_string& connstr)
379
383
  : options_(connstr.options)
380
384
  , connection_string_(connstr.input)
385
+ , uses_protostellar_(connstr.uses_protostellar())
381
386
  , credentials_(std::move(auth))
382
387
  {
383
388
  nodes_.reserve(connstr.bootstrap_nodes.size());
@@ -396,10 +401,13 @@ couchbase::core::origin::operator=(const couchbase::core::origin& other) -> couc
396
401
  {
397
402
  if (this != &other) {
398
403
  options_ = other.options_;
404
+ connection_string_ = other.connection_string_;
399
405
  update_credentials(other.credentials());
400
406
  nodes_ = other.nodes_;
407
+ // Rotation state is reset, not carried -- see the copy constructor for why.
401
408
  next_node_ = nodes_.begin();
402
409
  exhausted_ = false;
410
+ uses_protostellar_ = other.uses_protostellar_;
403
411
  }
404
412
  return *this;
405
413
  }
@@ -409,6 +417,11 @@ couchbase::core::origin::connection_string() const -> const std::string&
409
417
  return connection_string_;
410
418
  }
411
419
  auto
420
+ couchbase::core::origin::uses_protostellar() const -> bool
421
+ {
422
+ return uses_protostellar_;
423
+ }
424
+ auto
412
425
  couchbase::core::origin::username() const -> std::string
413
426
  {
414
427
  const std::shared_lock lock(credentials_mutex_);
@@ -458,6 +471,16 @@ couchbase::core::origin::get_nodes() const -> std::vector<std::string>
458
471
  }
459
472
  return res;
460
473
  }
474
+ auto
475
+ couchbase::core::origin::get_node_addresses() const -> std::vector<std::string>
476
+ {
477
+ std::vector<std::string> res;
478
+ res.reserve(nodes_.size());
479
+ for (const auto& [hostname, port] : nodes_) {
480
+ res.emplace_back(fmt::format("{}:{}", hostname, port));
481
+ }
482
+ return res;
483
+ }
461
484
 
462
485
  void
463
486
  couchbase::core::origin::shuffle_nodes()
@@ -502,6 +525,11 @@ couchbase::core::origin::set_nodes_from_config(const topology::configuration& co
502
525
  shuffle_nodes();
503
526
  }
504
527
  next_node_ = nodes_.begin();
528
+ // Matches set_nodes(): the node list has just been replaced, so any exhaustion recorded against
529
+ // the previous list is meaningless. Without this an origin that was exhausted stays exhausted
530
+ // across every config update -- cluster.cxx calls this on a long-lived origin that
531
+ // next_address() will have marked exhausted.
532
+ exhausted_ = false;
505
533
  }
506
534
  void
507
535
  couchbase::core::origin::update_credentials(cluster_credentials auth)
@@ -60,6 +60,9 @@ struct origin {
60
60
  auto operator=(const origin& other) -> origin&;
61
61
 
62
62
  [[nodiscard]] auto connection_string() const -> const std::string&;
63
+ // True when built from a couchbase2:// connection string (Protostellar transport). Lets the
64
+ // connect path branch to the gRPC client without re-parsing the connection string.
65
+ [[nodiscard]] auto uses_protostellar() const -> bool;
63
66
  [[nodiscard]] auto username() const -> std::string;
64
67
  [[nodiscard]] auto password() const -> std::string;
65
68
  [[nodiscard]] auto certificate_path() const -> std::string;
@@ -68,6 +71,10 @@ struct origin {
68
71
 
69
72
  [[nodiscard]] auto get_hostnames() const -> std::vector<std::string>;
70
73
  [[nodiscard]] auto get_nodes() const -> std::vector<std::string>;
74
+ // The same addresses as get_nodes(), without the display quotes baked into each entry. Log
75
+ // statements want them bare so that logger::system_data_list() can put a tag inside the quotes it
76
+ // renders; a tag around a pre-quoted entry hashes the punctuation with the value.
77
+ [[nodiscard]] auto get_node_addresses() const -> std::vector<std::string>;
71
78
 
72
79
  void shuffle_nodes();
73
80
  void set_nodes(node_list nodes);
@@ -84,6 +91,10 @@ struct origin {
84
91
  [[nodiscard]] auto options() const -> const couchbase::core::cluster_options&;
85
92
  [[nodiscard]] auto options() -> couchbase::core::cluster_options&;
86
93
  [[nodiscard]] auto credentials() const -> couchbase::core::cluster_credentials;
94
+ // A JSON dump of the whole origin, less the credentials. Its only callers are the log
95
+ // statements in the cluster open paths, and they annotate the whole document: a tag written
96
+ // into one of these values instead would be read back as part of that value by anything that
97
+ // parses the line as JSON. So nothing in here is annotated.
87
98
  [[nodiscard]] auto to_json() const -> std::string;
88
99
 
89
100
  private:
@@ -92,6 +103,7 @@ private:
92
103
  node_list::iterator next_node_{};
93
104
  bool exhausted_{ false };
94
105
  std::string connection_string_{};
106
+ bool uses_protostellar_{ false };
95
107
  cluster_credentials credentials_{};
96
108
  mutable std::shared_mutex credentials_mutex_{};
97
109
  };
@@ -20,6 +20,7 @@
20
20
  #include <couchbase/build_info.hxx>
21
21
 
22
22
  #include "logger/logger.hxx"
23
+ #include "logger/redaction.hxx"
23
24
  #include "utils/concurrent_fixed_priority_queue.hxx"
24
25
  #include "utils/json.hxx"
25
26
 
@@ -120,7 +121,7 @@ private:
120
121
  }
121
122
 
122
123
  if (auto report = self->flush_and_create_output(); report.has_value()) {
123
- CB_LOG_WARNING("Orphan responses observed: {}", report.value());
124
+ CB_LOG_WARNING("Orphan responses observed: {}", logger::system_data(report.value()));
124
125
  }
125
126
 
126
127
  self->rearm();
@@ -25,7 +25,7 @@
25
25
  #include <mutex>
26
26
  #include <system_error>
27
27
 
28
- #ifdef WIN32
28
+ #ifdef _WIN32
29
29
  // We need to include windows.h _before_ wincrypt.h
30
30
  #ifndef WIN32_LEAN_AND_MEAN
31
31
  #define WIN32_LEAN_AND_MEAN
@@ -45,7 +45,7 @@ class RandomGeneratorProvider
45
45
  public:
46
46
  RandomGeneratorProvider()
47
47
  {
48
- #ifdef WIN32
48
+ #ifdef _WIN32
49
49
  if (!CryptAcquireContext(
50
50
  &handle, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
51
51
  throw std::system_error(int(GetLastError()),
@@ -69,7 +69,7 @@ public:
69
69
 
70
70
  virtual ~RandomGeneratorProvider()
71
71
  {
72
- #ifdef WIN32
72
+ #ifdef _WIN32
73
73
  CryptReleaseContext(handle, 0);
74
74
  #else
75
75
  close(handle);
@@ -78,8 +78,8 @@ public:
78
78
 
79
79
  auto getBytes(void* dest, std::size_t size) -> bool
80
80
  {
81
- const std::lock_guard<std::mutex> lock(mutex);
82
- #ifdef WIN32
81
+ const std::scoped_lock<std::mutex> lock(mutex);
82
+ #ifdef _WIN32
83
83
  return CryptGenRandom(handle, (DWORD)size, static_cast<BYTE*>(dest));
84
84
  #else
85
85
  #if defined(__clang__) && defined(__clang_analyzer__)
@@ -92,7 +92,7 @@ public:
92
92
  }
93
93
 
94
94
  private:
95
- #ifdef WIN32
95
+ #ifdef _WIN32
96
96
  HCRYPTPROV handle{};
97
97
  #else
98
98
  int handle = -1;
@@ -107,7 +107,7 @@ RandomGenerator::RandomGenerator()
107
107
  {
108
108
  if (!shared_provider) {
109
109
  // This might be the first one, lets lock and create
110
- const std::lock_guard<std::mutex> guard(shared_provider_lock);
110
+ const std::scoped_lock<std::mutex> guard(shared_provider_lock);
111
111
  if (!shared_provider) { // cppcheck-suppress identicalInnerCondition; DCLP
112
112
  shared_provider = std::make_unique<RandomGeneratorProvider>();
113
113
  }
@@ -23,8 +23,8 @@
23
23
  namespace couchbase::core::protocol
24
24
  {
25
25
  auto
26
- compress_value(const std::vector<std::byte>& value,
27
- std::vector<std::byte>::iterator& output) -> std::pair<bool, std::uint32_t>
26
+ compress_value(const std::vector<std::byte>& value, const std::vector<std::byte>::iterator& output)
27
+ -> std::pair<bool, std::uint32_t>
28
28
  {
29
29
  static const double min_ratio = 0.83;
30
30