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
@@ -16,10 +16,12 @@
16
16
  */
17
17
 
18
18
  #include "document_analytics.hxx"
19
+ #include "analytics_response_parsing.hxx"
19
20
  #include "core/cluster_options.hxx"
20
21
  #include "core/logger/logger.hxx"
21
- #include "core/utils/duration_parser.hxx"
22
+ #include "core/logger/redaction.hxx"
22
23
  #include "core/utils/json.hxx"
24
+ #include "core/utils/name_codec.hxx"
23
25
 
24
26
  #include <couchbase/error_codes.hxx>
25
27
 
@@ -28,15 +30,10 @@
28
30
 
29
31
  namespace couchbase::core::operations
30
32
  {
31
- auto
32
- analytics_request::encode_to(analytics_request::encoded_request_type& encoded,
33
- http_context& context) -> std::error_code
33
+ void
34
+ encode_analytics_options(tao::json::value& body, const analytics_request& request)
34
35
  {
35
- tao::json::value body{ { "statement", statement },
36
- { "client_context_id", encoded.client_context_id },
37
- { "timeout", fmt::format("{}ms", encoded.timeout.count()) } };
38
-
39
- for (const auto& [name, value] : named_parameters) {
36
+ for (const auto& [name, value] : request.named_parameters) {
40
37
  Expects(name.empty() == false);
41
38
  std::string key = name;
42
39
  if (key[0] != '$') {
@@ -44,19 +41,19 @@ analytics_request::encode_to(analytics_request::encoded_request_type& encoded,
44
41
  }
45
42
  body[key] = utils::json::parse(value);
46
43
  }
47
- if (!positional_parameters.empty()) {
44
+ if (!request.positional_parameters.empty()) {
48
45
  std::vector<tao::json::value> parameters;
49
- parameters.reserve(positional_parameters.size());
50
- for (const auto& value : positional_parameters) {
46
+ parameters.reserve(request.positional_parameters.size());
47
+ for (const auto& value : request.positional_parameters) {
51
48
  parameters.emplace_back(utils::json::parse(value));
52
49
  }
53
50
  body["args"] = std::move(parameters);
54
51
  }
55
- if (readonly) {
52
+ if (request.readonly) {
56
53
  body["readonly"] = true;
57
54
  }
58
- if (scan_consistency) {
59
- switch (scan_consistency.value()) {
55
+ if (request.scan_consistency) {
56
+ switch (request.scan_consistency.value()) {
60
57
  case couchbase::core::analytics_scan_consistency::not_bounded:
61
58
  body["scan_consistency"] = "not_bounded";
62
59
  break;
@@ -65,14 +62,30 @@ analytics_request::encode_to(analytics_request::encoded_request_type& encoded,
65
62
  break;
66
63
  }
67
64
  }
68
- if (scope_qualifier) {
69
- body["query_context"] = scope_qualifier;
70
- } else if (scope_name && bucket_name) {
71
- body["query_context"] = fmt::format("default:`{}`.`{}`", *bucket_name, *scope_name);
65
+ if (request.scope_qualifier) {
66
+ body["query_context"] = request.scope_qualifier.value();
67
+ } else if (request.scope_name && request.bucket_name) {
68
+ // The query context is parsed as SQL++, so its two names are quoted through the same encoder
69
+ // the management statements use rather than wrapped in bare backticks.
70
+ body["query_context"] = fmt::format("default:{}.{}",
71
+ utils::analytics::quote_identifier(*request.bucket_name),
72
+ utils::analytics::quote_identifier(*request.scope_name));
72
73
  }
73
- for (const auto& [name, value] : raw) {
74
+ for (const auto& [name, value] : request.raw) {
74
75
  body[name] = utils::json::parse(value);
75
76
  }
77
+ }
78
+
79
+ auto
80
+ analytics_request::encode_to(analytics_request::encoded_request_type& encoded,
81
+ http_context& context) -> std::error_code
82
+ {
83
+ tao::json::value body{ { "statement", statement },
84
+ { "client_context_id", encoded.client_context_id },
85
+ { "timeout", fmt::format("{}ms", encoded.timeout.count()) } };
86
+
87
+ encode_analytics_options(body, *this);
88
+
76
89
  encoded.type = type;
77
90
  encoded.headers["content-type"] = "application/json";
78
91
  if (priority) {
@@ -85,11 +98,11 @@ analytics_request::encode_to(analytics_request::encoded_request_type& encoded,
85
98
  if (context.options.show_queries) {
86
99
  CB_LOG_INFO("ANALYTICS: client_context_id=\"{}\", {}",
87
100
  encoded.client_context_id,
88
- utils::json::generate(body["statement"]));
101
+ logger::user_data(utils::json::generate(body["statement"])));
89
102
  } else {
90
103
  CB_LOG_DEBUG("ANALYTICS: client_context_id=\"{}\", {}",
91
104
  encoded.client_context_id,
92
- utils::json::generate(body["statement"]));
105
+ logger::user_data(utils::json::generate(body["statement"])));
93
106
  }
94
107
  if (row_callback) {
95
108
  encoded.streaming.emplace(couchbase::core::io::streaming_settings{
@@ -116,78 +129,12 @@ analytics_request::make_response(error_context::analytics&& ctx,
116
129
  response.ctx.ec = errc::common::parsing_failure;
117
130
  return response;
118
131
  }
119
- if (const auto* i = payload.find("requestID"); i != nullptr) {
120
- response.meta.request_id = i->get_string();
121
- }
122
- if (const auto* i = payload.find("clientContextID"); i != nullptr) {
123
- response.meta.client_context_id = i->get_string();
124
- if (response.ctx.client_context_id != response.meta.client_context_id) {
125
- CB_LOG_WARNING(R"(unexpected clientContextID returned by service: "{}", expected "{}")",
126
- response.meta.client_context_id,
127
- response.ctx.client_context_id);
128
- }
129
- }
130
- if (auto& status_prop = payload.at("status"); status_prop.is_string()) {
131
- const auto& status = status_prop.get_string();
132
- if (status == "running") {
133
- response.meta.status = analytics_response::analytics_status::running;
134
- } else if (status == "success") {
135
- response.meta.status = analytics_response::analytics_status::success;
136
- } else if (status == "errors") {
137
- response.meta.status = analytics_response::analytics_status::errors;
138
- } else if (status == "completed") {
139
- response.meta.status = analytics_response::analytics_status::completed;
140
- } else if (status == "stopped") {
141
- response.meta.status = analytics_response::analytics_status::stopped;
142
- } else if (status == "timedout") {
143
- response.meta.status = analytics_response::analytics_status::timedout;
144
- } else if (status == "closed") {
145
- response.meta.status = analytics_response::analytics_status::closed;
146
- } else if (status == "fatal") {
147
- response.meta.status = analytics_response::analytics_status::fatal;
148
- } else if (status == "aborted") {
149
- response.meta.status = analytics_response::analytics_status::aborted;
150
- } else {
151
- response.meta.status = analytics_response::analytics_status::unknown;
152
- }
153
- } else {
154
- response.meta.status = analytics_response::analytics_status::unknown;
155
- }
156
-
157
- if (const auto* s = payload.find("signature"); s != nullptr) {
158
- response.meta.signature = couchbase::core::utils::json::generate(*s);
159
- }
160
-
161
- if (const auto* metrics = payload.find("metrics"); metrics != nullptr) {
162
- response.meta.metrics.result_count = metrics->at("resultCount").get_unsigned();
163
- response.meta.metrics.result_size = metrics->at("resultSize").get_unsigned();
164
- response.meta.metrics.elapsed_time =
165
- utils::parse_duration(metrics->at("elapsedTime").get_string());
166
- response.meta.metrics.execution_time =
167
- utils::parse_duration(metrics->at("executionTime").get_string());
168
- response.meta.metrics.processed_objects = metrics->at("processedObjects").get_unsigned();
169
- response.meta.metrics.error_count =
170
- metrics->optional<std::uint64_t>("errorCount").value_or(0);
171
- response.meta.metrics.warning_count =
172
- metrics->optional<std::uint64_t>("warningCount").value_or(0);
173
- }
174
-
175
- if (const auto* e = payload.find("errors"); e != nullptr) {
176
- for (const auto& err : e->get_array()) {
177
- couchbase::core::operations::analytics_response::analytics_problem problem;
178
- problem.code = err.at("code").get_unsigned();
179
- problem.message = err.at("msg").get_string();
180
- response.meta.errors.emplace_back(problem);
181
- }
182
- }
183
-
184
- if (const auto* w = payload.find("warnings"); w != nullptr) {
185
- for (const auto& warn : w->get_array()) {
186
- couchbase::core::operations::analytics_response::analytics_problem problem;
187
- problem.code = warn.at("code").get_unsigned();
188
- problem.message = warn.at("msg").get_string();
189
- response.meta.warnings.emplace_back(problem);
190
- }
132
+ response.meta = parse_analytics_meta(payload);
133
+ if (response.ctx.client_context_id != response.meta.client_context_id &&
134
+ !response.meta.client_context_id.empty()) {
135
+ CB_LOG_WARNING(R"(unexpected clientContextID returned by service: "{}", expected "{}")",
136
+ response.meta.client_context_id,
137
+ response.ctx.client_context_id);
191
138
  }
192
139
 
193
140
  if (const auto* r = payload.find("results"); r != nullptr) {
@@ -197,43 +144,14 @@ analytics_request::make_response(error_context::analytics&& ctx,
197
144
  }
198
145
  }
199
146
 
200
- if (response.meta.status != analytics_response::analytics_status::success) {
201
- response.ctx.first_error_code = response.meta.errors.front().code;
202
- response.ctx.first_error_message = response.meta.errors.front().message;
203
- switch (response.ctx.first_error_code) {
204
- case 21002: /* Request timed out and will be cancelled */
205
- response.ctx.ec = errc::common::unambiguous_timeout;
206
- break;
207
- case 23007: /* Job queue is full with [string] jobs */
208
- response.ctx.ec = errc::analytics::job_queue_full;
209
- break;
210
- case 24044: /* Cannot find dataset [string] because there is no dataverse declared, nor an
211
- alias with name [string]! */
212
- case 24045: /* Cannot find dataset [string] in dataverse [string] nor an alias with name
213
- [string]! */
214
- case 24025: /* Cannot find dataset with name [string] in dataverse [string] */
215
- response.ctx.ec = errc::analytics::dataset_not_found;
216
- break;
217
- case 24034: /* Cannot find dataverse with name [string] */
218
- response.ctx.ec = errc::analytics::dataverse_not_found;
219
- break;
220
- case 24040: /* A dataset with name [string] already exists in dataverse [string] */
221
- response.ctx.ec = errc::analytics::dataset_exists;
222
- break;
223
- case 24039: /* A dataverse with this name [string] already exists. */
224
- response.ctx.ec = errc::analytics::dataverse_exists;
225
- break;
226
- case 24006: /* Link [string] does not exist | Link [string] does not exist */
227
- response.ctx.ec = errc::analytics::link_not_found;
228
- break;
229
- default:
230
- if (response.ctx.first_error_code >= 24000 && response.ctx.first_error_code < 25000) {
231
- response.ctx.ec = errc::analytics::compilation_failure;
232
- }
233
- }
234
- if (!response.ctx.ec) {
235
- response.ctx.ec = errc::common::internal_server_failure;
147
+ // RFC-58: a 400 is a failure whatever status the body reports.
148
+ if (response.meta.status != analytics_response::analytics_status::success ||
149
+ encoded.status_code == 400) {
150
+ if (!response.meta.errors.empty()) {
151
+ response.ctx.first_error_code = response.meta.errors.front().code;
152
+ response.ctx.first_error_message = response.meta.errors.front().message;
236
153
  }
154
+ response.ctx.ec = map_analytics_error(response.meta, encoded.status_code);
237
155
  }
238
156
  }
239
157
  return response;
@@ -27,8 +27,20 @@
27
27
  #include "core/public_fwd.hxx"
28
28
  #include "core/timeout_defaults.hxx"
29
29
 
30
+ #include <tao/json/forward.hpp>
31
+
30
32
  namespace couchbase::core::operations
31
33
  {
34
+ struct analytics_request;
35
+
36
+ /**
37
+ * Encodes the shared analytics request-body options (parameters, readonly, consistency,
38
+ * query_context, raw) common to the buffered and streaming analytics paths onto @p body, so both
39
+ * paths stay byte-for-byte consistent.
40
+ */
41
+ void
42
+ encode_analytics_options(tao::json::value& body, const analytics_request& request);
43
+
32
44
  struct analytics_response {
33
45
  struct analytics_metrics {
34
46
  std::chrono::nanoseconds elapsed_time{};
@@ -101,8 +113,8 @@ struct analytics_request {
101
113
  std::optional<std::string> client_context_id{};
102
114
  std::optional<std::chrono::milliseconds> timeout{};
103
115
 
104
- [[nodiscard]] auto encode_to(encoded_request_type& encoded,
105
- http_context& context) -> std::error_code;
116
+ [[nodiscard]] auto encode_to(encoded_request_type& encoded, http_context& context)
117
+ -> std::error_code;
106
118
  [[nodiscard]] auto make_response(error_context::analytics&& ctx,
107
119
  const encoded_response_type& encoded) const
108
120
  -> analytics_response;
@@ -20,16 +20,21 @@
20
20
  #include <couchbase/error_codes.hxx>
21
21
  #include <couchbase/node_id.hxx>
22
22
 
23
+ #include "core/document_id_redaction.hxx"
23
24
  #include "core/error_context/key_value.hxx"
24
- #include "core/impl/get_replica.hxx"
25
25
  #include "core/impl/replica_utils.hxx"
26
26
  #include "core/logger/logger.hxx"
27
+ #include "core/logger/redaction.hxx"
27
28
  #include "core/operations/document_get.hxx"
29
+ #include "core/operations/document_get_replica.hxx"
28
30
  #include "core/operations/operation_traits.hxx"
29
31
  #include "core/public_fwd.hxx"
32
+ #include "core/service_type.hxx"
30
33
  #include "core/tracing/constants.hxx"
34
+ #include "core/utils/deadline.hxx"
31
35
  #include "core/utils/movable_function.hxx"
32
36
 
37
+ #include <chrono>
33
38
  #include <memory>
34
39
  #include <mutex>
35
40
 
@@ -64,11 +69,14 @@ struct get_all_replicas_request {
64
69
  template<typename Core, typename Handler>
65
70
  void execute(Core core, Handler handler)
66
71
  {
72
+ const auto deadline = std::chrono::steady_clock::now() +
73
+ timeout.value_or(core->default_timeout_for(service_type::key_value));
67
74
  core->with_bucket_configuration(
68
75
  id.bucket(),
76
+ deadline,
69
77
  [core,
70
78
  id = id,
71
- timeout = timeout,
79
+ deadline,
72
80
  read_preference = read_preference,
73
81
  parent_span = std::move(parent_span),
74
82
  h = std::forward<Handler>(handler)](
@@ -86,8 +94,8 @@ struct get_all_replicas_request {
86
94
  if (nodes.empty()) {
87
95
  CB_LOG_DEBUG(
88
96
  "Unable to retrieve replicas for \"{}\", server_group={}, number_of_replicas={}",
89
- id,
90
- origin.options().server_group,
97
+ logger::document(id),
98
+ logger::metadata(origin.options().server_group),
91
99
  config->num_replicas.value_or(0));
92
100
  return h(response_type{
93
101
  make_key_value_error_context(errc::key_value::document_irretrievable, id) });
@@ -129,9 +137,9 @@ struct get_all_replicas_request {
129
137
  document_id replica_id{ id };
130
138
  replica_id.node_index(node.index);
131
139
  core->execute(
132
- impl::get_replica_request{
140
+ operations::get_replica_request{
133
141
  std::move(replica_id),
134
- timeout,
142
+ utils::remaining_until(deadline),
135
143
  {},
136
144
  {},
137
145
  {},
@@ -184,7 +192,7 @@ struct get_all_replicas_request {
184
192
  document_id{ id },
185
193
  {},
186
194
  {},
187
- timeout,
195
+ utils::remaining_until(deadline),
188
196
  {},
189
197
  subop_span,
190
198
  },
@@ -17,15 +17,20 @@
17
17
 
18
18
  #pragma once
19
19
 
20
+ #include "core/document_id_redaction.hxx"
20
21
  #include "core/error_context/key_value.hxx"
21
- #include "core/impl/get_replica.hxx"
22
22
  #include "core/impl/replica_utils.hxx"
23
23
  #include "core/impl/with_cancellation.hxx"
24
+ #include "core/logger/redaction.hxx"
24
25
  #include "core/operations/document_get.hxx"
26
+ #include "core/operations/document_get_replica.hxx"
25
27
  #include "core/operations/operation_traits.hxx"
28
+ #include "core/service_type.hxx"
29
+ #include "core/utils/deadline.hxx"
26
30
  #include "core/utils/movable_function.hxx"
27
31
  #include "couchbase/error_codes.hxx"
28
32
 
33
+ #include <chrono>
29
34
  #include <functional>
30
35
  #include <memory>
31
36
  #include <mutex>
@@ -57,17 +62,23 @@ struct get_any_replica_request {
57
62
  template<typename Core, typename Handler>
58
63
  void execute(Core core, Handler handler)
59
64
  {
65
+ const auto deadline = std::chrono::steady_clock::now() +
66
+ timeout.value_or(core->default_timeout_for(service_type::key_value));
60
67
  core->with_bucket_configuration(
61
68
  id.bucket(),
69
+ deadline,
62
70
  [core,
63
71
  id = id,
64
- timeout = timeout,
72
+ deadline,
65
73
  read_preference = read_preference,
66
74
  parent_span = std::move(parent_span),
67
75
  h = std::forward<Handler>(handler)](
68
76
  std::error_code ec, std::shared_ptr<topology::configuration> config) mutable {
77
+ if (ec) {
78
+ return h(response_type{ make_key_value_error_context(ec, id) });
79
+ }
69
80
  const auto [e, origin] = core->origin();
70
- if (e && !ec) {
81
+ if (e) {
71
82
  ec = e;
72
83
  }
73
84
 
@@ -76,8 +87,8 @@ struct get_any_replica_request {
76
87
  if (nodes.empty()) {
77
88
  CB_LOG_DEBUG(
78
89
  "Unable to retrieve replicas for \"{}\", server_group={}, number_of_replicas={}",
79
- id,
80
- origin.options().server_group,
90
+ logger::document(id),
91
+ logger::metadata(origin.options().server_group),
81
92
  config->num_replicas.value_or(0));
82
93
  ec = errc::key_value::document_irretrievable;
83
94
  }
@@ -137,10 +148,10 @@ struct get_any_replica_request {
137
148
  if (node.is_replica) {
138
149
  document_id replica_id{ id };
139
150
  replica_id.node_index(node.index);
140
- impl::with_cancellation<impl::get_replica_request> req{
151
+ impl::with_cancellation<operations::get_replica_request> req{
141
152
  {
142
153
  std::move(replica_id),
143
- timeout,
154
+ utils::remaining_until(deadline),
144
155
  {},
145
156
  {},
146
157
  {},
@@ -191,7 +202,7 @@ struct get_any_replica_request {
191
202
  id,
192
203
  {},
193
204
  {},
194
- timeout,
205
+ utils::remaining_until(deadline),
195
206
  {},
196
207
  subop_span,
197
208
  },
@@ -79,7 +79,7 @@ subdoc_lookup(tao::json::value& root, const std::string& path) -> std::optional<
79
79
  void
80
80
  subdoc_apply_projection(tao::json::value& root,
81
81
  const std::string& path,
82
- tao::json::value& value,
82
+ const tao::json::value& value,
83
83
  bool preserve_array_indexes)
84
84
  {
85
85
  std::string::size_type offset = 0;
@@ -15,16 +15,34 @@
15
15
  * limitations under the License.
16
16
  */
17
17
 
18
- #include "get_replica.hxx"
18
+ #include "core/operations/document_get_replica.hxx"
19
19
 
20
20
  #include "core/error_context/key_value_error_context.hxx"
21
21
  #include "core/io/mcbp_context.hxx"
22
22
 
23
+ #include <optional>
23
24
  #include <system_error>
24
25
  #include <utility>
25
26
 
26
- namespace couchbase::core::impl
27
+ namespace couchbase::core::operations
27
28
  {
29
+ auto
30
+ get_replica_request::resolve_route(const topology::configuration& config) const
31
+ -> std::optional<impl::replica_route_decision>
32
+ {
33
+ // The replica fan-out callers share this type but leave the strategy unset:
34
+ // they pin the replica through id.node_index() and want the vbucket-map
35
+ // routing the dispatch path already applies.
36
+ if (!selection.has_value()) {
37
+ return {};
38
+ }
39
+
40
+ // Named vbucket rather than partition: the request carries a partition member,
41
+ // and MSVC rejects a local that hides it.
42
+ const auto vbucket = config.map_key(id.key(), 0).first;
43
+ return impl::resolve_replica_index(config, vbucket, selection->replica_index, selection->wrap);
44
+ }
45
+
28
46
  auto
29
47
  get_replica_request::encode_to(get_replica_request::encoded_request_type& encoded,
30
48
  core::mcbp_context&& /* context */) const -> std::error_code
@@ -48,4 +66,4 @@ get_replica_request::make_response(key_value_error_context&& ctx,
48
66
  }
49
67
  return response;
50
68
  }
51
- } // namespace couchbase::core::impl
69
+ } // namespace couchbase::core::operations
@@ -19,14 +19,19 @@
19
19
 
20
20
  #include "core/error_context/key_value_error_context.hxx"
21
21
 
22
+ #include "core/impl/replica_utils.hxx"
22
23
  #include "core/io/mcbp_context.hxx"
23
24
  #include "core/io/retry_context.hxx"
25
+ #include "core/operations/operation_traits.hxx"
24
26
  #include "core/protocol/client_request.hxx"
25
27
  #include "core/protocol/cmd_get_replica.hxx"
26
28
  #include "core/public_fwd.hxx"
27
29
  #include "core/timeout_defaults.hxx"
30
+ #include "core/utils/movable_function.hxx"
28
31
 
29
- namespace couchbase::core::impl
32
+ #include <couchbase/get_replica_result.hxx>
33
+
34
+ namespace couchbase::core::operations
30
35
  {
31
36
  struct get_replica_response {
32
37
  key_value_error_context ctx{};
@@ -50,12 +55,34 @@ struct get_replica_request {
50
55
  std::uint32_t opaque{};
51
56
  io::retry_context<true> retries{};
52
57
  std::shared_ptr<couchbase::tracing::request_span> parent_span{ nullptr };
58
+ /**
59
+ * Absent for the replica fan-out callers, which pin the replica through
60
+ * @c id.node_index(). When this is unset resolve_route() returns an empty
61
+ * optional, declining to route, and the dispatch path falls back to the
62
+ * vbucket-map routing that honours @c id.node_index().
63
+ */
64
+ std::optional<impl::replica_selection> selection{};
65
+
66
+ /**
67
+ * Selects the node this request should be sent to, against the topology of
68
+ * the current attempt. Empty when the request wants the vbucket-map routing
69
+ * the dispatch path applies to every other request.
70
+ */
71
+ [[nodiscard]] auto resolve_route(const topology::configuration& config) const
72
+ -> std::optional<impl::replica_route_decision>;
53
73
 
54
- [[nodiscard]] auto encode_to(encoded_request_type& encoded,
55
- core::mcbp_context&& context) const -> std::error_code;
74
+ [[nodiscard]] auto encode_to(encoded_request_type& encoded, core::mcbp_context&& context) const
75
+ -> std::error_code;
56
76
 
57
77
  [[nodiscard]] auto make_response(key_value_error_context&& ctx,
58
78
  const encoded_response_type& encoded) const
59
79
  -> get_replica_response;
60
80
  };
61
- } // namespace couchbase::core::impl
81
+
82
+ using movable_get_replica_handler =
83
+ utils::movable_function<void(couchbase::error, get_replica_result)>;
84
+
85
+ template<>
86
+ struct resolves_own_route<get_replica_request> : public std::true_type {
87
+ };
88
+ } // namespace couchbase::core::operations
@@ -66,7 +66,6 @@ lookup_in_request::make_response(key_value_error_context&& ctx,
66
66
  bool deleted = false;
67
67
  couchbase::cas cas{};
68
68
  std::vector<lookup_in_response::entry> fields{};
69
- std::error_code ec = ctx.ec();
70
69
  std::optional<std::size_t> first_error_index{};
71
70
  std::optional<std::string> first_error_path{};
72
71
 
@@ -90,13 +89,14 @@ lookup_in_request::make_response(key_value_error_context&& ctx,
90
89
  static_cast<std::uint16_t>(res_entry.status));
91
90
  if (fields[i].opcode == protocol::subdoc_opcode::exists &&
92
91
  fields[i].ec == errc::key_value::path_not_found) {
92
+ // exists treats path_not_found as success ("false"); suppress the error so the
93
+ // exists flag below carries the result instead.
93
94
  fields[i].ec.clear();
94
95
  }
95
- if (!fields[i].ec && !ctx.ec()) {
96
- ec = fields[i].ec;
97
- }
98
- if (!first_error_index && !fields[i].ec) {
99
- first_error_index = i;
96
+ // Use original_index, not wire-order i: XATTR specs are reordered during encode_to(),
97
+ // so i != original_index (was the CXXCBC-788 bug).
98
+ if (!first_error_index && fields[i].ec) {
99
+ first_error_index = fields[i].original_index;
100
100
  first_error_path = fields[i].path;
101
101
  }
102
102
  fields[i].exists = res_entry.status == key_value_status_code::success ||
@@ -107,16 +107,16 @@ lookup_in_request::make_response(key_value_error_context&& ctx,
107
107
  fields[i].value = utils::to_binary(res_entry.value);
108
108
  }
109
109
  }
110
- if (!ec) {
111
- cas = encoded.cas();
112
- }
110
+ // Always assign CAS; previously guarded by a local ec that was polluted by per-path
111
+ // errors, zeroing CAS whenever any path failed (CXXCBC-788).
112
+ cas = encoded.cas();
113
113
  std::sort(fields.begin(), fields.end(), [](const auto& lhs, const auto& rhs) {
114
114
  return lhs.original_index < rhs.original_index;
115
115
  });
116
116
  }
117
117
 
118
118
  return lookup_in_response{
119
- make_subdocument_error_context(ctx, ec, first_error_path, first_error_index, deleted),
119
+ make_subdocument_error_context(ctx, ctx.ec(), first_error_path, first_error_index, deleted),
120
120
  cas,
121
121
  std::move(fields),
122
122
  deleted,