couchbase 3.8.2 → 3.9.1

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 (473) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  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 +121 -55
  7. data/ext/cache/mozilla-ca-bundle.sha256 +1 -1
  8. data/ext/couchbase/CMakeLists.txt +136 -23
  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 +82 -7
  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 +1551 -397
  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 +229 -42
  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 +1 -2
  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 +309 -301
  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 +151 -21
  131. data/ext/couchbase/core/io/streams.hxx +48 -1
  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/change_password.cxx +2 -0
  183. data/ext/couchbase/core/operations/management/collection_drop.cxx +5 -1
  184. data/ext/couchbase/core/operations/management/error_utils.cxx +60 -6
  185. data/ext/couchbase/core/operations/management/error_utils.hxx +29 -1
  186. data/ext/couchbase/core/operations/management/eventing_deploy_function.cxx +9 -3
  187. data/ext/couchbase/core/operations/management/eventing_drop_function.cxx +8 -3
  188. data/ext/couchbase/core/operations/management/eventing_get_all_functions.cxx +4 -2
  189. data/ext/couchbase/core/operations/management/eventing_get_function.cxx +5 -3
  190. data/ext/couchbase/core/operations/management/eventing_get_status.cxx +4 -2
  191. data/ext/couchbase/core/operations/management/eventing_pause_function.cxx +9 -3
  192. data/ext/couchbase/core/operations/management/eventing_resume_function.cxx +9 -3
  193. data/ext/couchbase/core/operations/management/eventing_undeploy_function.cxx +9 -3
  194. data/ext/couchbase/core/operations/management/eventing_upsert_function.cxx +9 -3
  195. data/ext/couchbase/core/operations/management/group_drop.cxx +3 -1
  196. data/ext/couchbase/core/operations/management/group_get.cxx +3 -1
  197. data/ext/couchbase/core/operations/management/group_upsert.cxx +11 -8
  198. data/ext/couchbase/core/operations/management/query_index_build.cxx +5 -2
  199. data/ext/couchbase/core/operations/management/query_index_create.cxx +9 -3
  200. data/ext/couchbase/core/operations/management/query_index_drop.cxx +11 -4
  201. data/ext/couchbase/core/operations/management/query_index_get_all.cxx +1 -1
  202. data/ext/couchbase/core/operations/management/query_index_get_all_deferred.cxx +1 -1
  203. data/ext/couchbase/core/operations/management/scope_drop.cxx +5 -1
  204. data/ext/couchbase/core/operations/management/scope_get_all.cxx +6 -1
  205. data/ext/couchbase/core/operations/management/search_get_stats.cxx +10 -0
  206. data/ext/couchbase/core/operations/management/search_index_analyze_document.cxx +3 -2
  207. data/ext/couchbase/core/operations/management/search_index_control_ingest.cxx +4 -3
  208. data/ext/couchbase/core/operations/management/search_index_control_plan_freeze.cxx +4 -3
  209. data/ext/couchbase/core/operations/management/search_index_control_query.cxx +4 -3
  210. data/ext/couchbase/core/operations/management/search_index_drop.cxx +2 -2
  211. data/ext/couchbase/core/operations/management/search_index_get.cxx +2 -2
  212. data/ext/couchbase/core/operations/management/search_index_get_documents_count.cxx +3 -2
  213. data/ext/couchbase/core/operations/management/search_index_get_stats.cxx +3 -1
  214. data/ext/couchbase/core/operations/management/search_index_upsert.cxx +2 -2
  215. data/ext/couchbase/core/operations/management/user_drop.cxx +3 -1
  216. data/ext/couchbase/core/operations/management/user_get.cxx +3 -1
  217. data/ext/couchbase/core/operations/management/user_upsert.cxx +12 -9
  218. data/ext/couchbase/core/operations/management/view_index_drop.cxx +1 -1
  219. data/ext/couchbase/core/operations/management/view_index_get.cxx +1 -1
  220. data/ext/couchbase/core/operations/management/view_index_upsert.cxx +1 -1
  221. data/ext/couchbase/core/operations/operation_traits.hxx +18 -0
  222. data/ext/couchbase/core/operations/query_response_parsing.cxx +211 -0
  223. data/ext/couchbase/core/operations/query_response_parsing.hxx +60 -0
  224. data/ext/couchbase/core/operations_fwd.hxx +3 -3
  225. data/ext/couchbase/core/origin.cxx +54 -26
  226. data/ext/couchbase/core/origin.hxx +12 -0
  227. data/ext/couchbase/core/orphan_reporter.cxx +2 -1
  228. data/ext/couchbase/core/platform/random.cc +7 -7
  229. data/ext/couchbase/core/protocol/client_request.cxx +2 -2
  230. data/ext/couchbase/core/protocol/client_request.hxx +38 -21
  231. data/ext/couchbase/core/protocol/client_response.cxx +11 -3
  232. data/ext/couchbase/core/protocol/client_response.hxx +27 -6
  233. data/ext/couchbase/core/protocol/cmd_append.cxx +2 -2
  234. data/ext/couchbase/core/protocol/cmd_cluster_map_change_notification.cxx +2 -2
  235. data/ext/couchbase/core/protocol/cmd_decrement.cxx +6 -6
  236. data/ext/couchbase/core/protocol/cmd_get.cxx +1 -1
  237. data/ext/couchbase/core/protocol/cmd_get_and_lock.cxx +2 -2
  238. data/ext/couchbase/core/protocol/cmd_get_and_touch.cxx +2 -2
  239. data/ext/couchbase/core/protocol/cmd_get_cluster_config.cxx +6 -4
  240. data/ext/couchbase/core/protocol/cmd_get_collection_id.cxx +2 -2
  241. data/ext/couchbase/core/protocol/cmd_get_error_map.cxx +1 -1
  242. data/ext/couchbase/core/protocol/cmd_get_meta.cxx +4 -4
  243. data/ext/couchbase/core/protocol/cmd_get_replica.cxx +1 -1
  244. data/ext/couchbase/core/protocol/cmd_hello.cxx +1 -1
  245. data/ext/couchbase/core/protocol/cmd_increment.cxx +6 -6
  246. data/ext/couchbase/core/protocol/cmd_insert.cxx +4 -4
  247. data/ext/couchbase/core/protocol/cmd_lookup_in.cxx +4 -3
  248. data/ext/couchbase/core/protocol/cmd_lookup_in_replica.cxx +4 -3
  249. data/ext/couchbase/core/protocol/cmd_mutate_in.cxx +10 -9
  250. data/ext/couchbase/core/protocol/cmd_mutate_in.hxx +10 -10
  251. data/ext/couchbase/core/protocol/cmd_observe_seqno.cxx +7 -7
  252. data/ext/couchbase/core/protocol/cmd_prepend.cxx +2 -2
  253. data/ext/couchbase/core/protocol/cmd_remove.cxx +2 -2
  254. data/ext/couchbase/core/protocol/cmd_replace.cxx +4 -4
  255. data/ext/couchbase/core/protocol/cmd_touch.cxx +1 -1
  256. data/ext/couchbase/core/protocol/cmd_upsert.cxx +4 -4
  257. data/ext/couchbase/core/protocol/datatype.hxx +118 -1
  258. data/ext/couchbase/core/protocol/frame_info_utils.cxx +1 -1
  259. data/ext/couchbase/core/protocol/magic.hxx +4 -0
  260. data/ext/couchbase/core/protocol/magic_fmt.hxx +3 -0
  261. data/ext/couchbase/core/protocol/server_request.hxx +3 -1
  262. data/ext/couchbase/core/protocol/status.cxx +1 -1
  263. data/ext/couchbase/core/protostellar/analytics_converter.hxx +171 -0
  264. data/ext/couchbase/core/protostellar/bucket_admin_converter.hxx +301 -0
  265. data/ext/couchbase/core/protostellar/collection_admin_converter.hxx +92 -0
  266. data/ext/couchbase/core/protostellar/component.cxx +2445 -0
  267. data/ext/couchbase/core/protostellar/component.hxx +391 -0
  268. data/ext/couchbase/core/{columnar/bootstrap_notification_subscriber.hxx → protostellar/compression_settings.hxx} +11 -10
  269. data/ext/couchbase/core/protostellar/credentials.cxx +233 -0
  270. data/ext/couchbase/core/protostellar/credentials.hxx +88 -0
  271. data/ext/couchbase/core/protostellar/dispatcher.cxx +57 -0
  272. data/ext/couchbase/core/protostellar/dispatcher.hxx +482 -0
  273. data/ext/couchbase/core/protostellar/error_utils.cxx +293 -0
  274. data/ext/couchbase/core/protostellar/error_utils.hxx +97 -0
  275. data/ext/couchbase/core/protostellar/json_payload.hxx +49 -0
  276. data/ext/couchbase/core/protostellar/kv_converter.cxx +70 -0
  277. data/ext/couchbase/core/protostellar/kv_converter.hxx +600 -0
  278. data/ext/couchbase/core/protostellar/query_converter.hxx +265 -0
  279. data/ext/couchbase/core/protostellar/query_index_admin_converter.hxx +291 -0
  280. data/ext/couchbase/core/protostellar/query_proto.hxx +73 -0
  281. data/ext/couchbase/core/protostellar/search_converter.hxx +244 -0
  282. data/ext/couchbase/core/protostellar/search_index_admin_converter.hxx +156 -0
  283. data/ext/couchbase/core/protostellar/view_converter.hxx +158 -0
  284. data/ext/couchbase/core/query_stream.cxx +447 -0
  285. data/ext/couchbase/core/query_stream.hxx +141 -0
  286. data/ext/couchbase/core/query_stream_component.cxx +243 -0
  287. data/ext/couchbase/core/query_stream_component.hxx +68 -0
  288. data/ext/couchbase/core/range_scan_load_balancer.cxx +15 -8
  289. data/ext/couchbase/core/range_scan_orchestrator.cxx +15 -3
  290. data/ext/couchbase/core/response_handler.hxx +41 -4
  291. data/ext/couchbase/core/row_streamer.cxx +332 -46
  292. data/ext/couchbase/core/row_streamer.hxx +31 -1
  293. data/ext/couchbase/core/row_streamer_options.hxx +55 -0
  294. data/ext/couchbase/core/sasl/client.h +3 -0
  295. data/ext/couchbase/core/search_scoring.hxx +66 -0
  296. data/ext/couchbase/core/stream_error_details.hxx +69 -0
  297. data/ext/couchbase/core/timeout_defaults.hxx +0 -1
  298. data/ext/couchbase/core/topology/capabilities.hxx +6 -0
  299. data/ext/couchbase/core/topology/capabilities_fmt.hxx +3 -0
  300. data/ext/couchbase/core/topology/configuration.cxx +21 -6
  301. data/ext/couchbase/core/topology/configuration.hxx +29 -8
  302. data/ext/couchbase/core/topology/configuration_json.hxx +3 -0
  303. data/ext/couchbase/core/topology/error_map_json.hxx +3 -1
  304. data/ext/couchbase/core/tracing/threshold_logging_tracer.cxx +70 -4
  305. data/ext/couchbase/core/tracing/threshold_logging_tracer.hxx +10 -0
  306. data/ext/couchbase/core/transactions/active_transaction_record.cxx +0 -34
  307. data/ext/couchbase/core/transactions/attempt_context_impl.cxx +108 -63
  308. data/ext/couchbase/core/transactions/attempt_context_impl.hxx +19 -2
  309. data/ext/couchbase/core/transactions/error_list.hxx +2 -2
  310. data/ext/couchbase/core/transactions/get_multi_fetch.hxx +160 -0
  311. data/ext/couchbase/core/transactions/get_multi_orchestrator.cxx +326 -125
  312. data/ext/couchbase/core/transactions/get_multi_transaction_id.hxx +62 -0
  313. data/ext/couchbase/core/transactions/internal/atr_entry.hxx +22 -2
  314. data/ext/couchbase/core/transactions/internal/transaction_context.hxx +2 -2
  315. data/ext/couchbase/core/transactions/internal/transactions_cleanup.hxx +23 -1
  316. data/ext/couchbase/core/transactions/internal/utils.hxx +50 -14
  317. data/ext/couchbase/core/transactions/staged_mutation.cxx +23 -18
  318. data/ext/couchbase/core/transactions/staged_mutation.hxx +15 -4
  319. data/ext/couchbase/core/transactions/transaction_context.cxx +55 -40
  320. data/ext/couchbase/core/transactions/transaction_get_result.hxx +16 -0
  321. data/ext/couchbase/core/transactions/transactions.cxx +3 -55
  322. data/ext/couchbase/core/transactions/transactions_cleanup.cxx +165 -72
  323. data/ext/couchbase/core/transactions/transactions_config.cxx +0 -11
  324. data/ext/couchbase/core/transactions/utils.cxx +10 -0
  325. data/ext/couchbase/core/transactions/waitable_op_list.hxx +2 -2
  326. data/ext/couchbase/core/transactions.hxx +9 -9
  327. data/ext/couchbase/core/utils/byteswap.hxx +166 -9
  328. data/ext/couchbase/core/utils/connection_string.cxx +50 -85
  329. data/ext/couchbase/core/utils/connection_string.hxx +15 -0
  330. data/ext/couchbase/core/{columnar/backoff_calculator.hxx → utils/deadline.hxx} +13 -13
  331. data/ext/couchbase/core/utils/duration_parser.cxx +1 -1
  332. data/ext/couchbase/core/utils/json_streaming_lexer.cxx +48 -5
  333. data/ext/couchbase/core/utils/json_streaming_lexer.hxx +4 -1
  334. data/ext/couchbase/core/utils/movable_function.hxx +301 -52
  335. data/ext/couchbase/core/utils/name_codec.hxx +154 -11
  336. data/ext/couchbase/core/{columnar/retry_info.hxx → utils/process_id.hxx} +18 -13
  337. data/ext/couchbase/core/utils/url_codec.cxx +12 -51
  338. data/ext/couchbase/core/websocket_codec.cxx +13 -37
  339. data/ext/couchbase/couchbase/analytics_options.hxx +21 -10
  340. data/ext/couchbase/couchbase/analytics_row.hxx +105 -0
  341. data/ext/couchbase/couchbase/analytics_stream_result.hxx +266 -0
  342. data/ext/couchbase/couchbase/boolean_query.hxx +3 -3
  343. data/ext/couchbase/couchbase/bucket.hxx +57 -0
  344. data/ext/couchbase/couchbase/cluster.hxx +183 -5
  345. data/ext/couchbase/{core/columnar/security_options.hxx → couchbase/cluster_state.hxx} +18 -14
  346. data/ext/couchbase/couchbase/codec/lenient_json_transcoder.hxx +69 -0
  347. data/ext/couchbase/couchbase/collection.hxx +234 -14
  348. data/ext/couchbase/couchbase/common_durability_options.hxx +18 -3
  349. data/ext/couchbase/couchbase/conjunction_query.hxx +1 -1
  350. data/ext/couchbase/couchbase/create_dataset_analytics_options.hxx +6 -1
  351. data/ext/couchbase/couchbase/date_range_query.hxx +2 -2
  352. data/ext/couchbase/couchbase/decrement_options.hxx +1 -1
  353. data/ext/couchbase/couchbase/disjunction_query.hxx +1 -1
  354. data/ext/couchbase/couchbase/error.hxx +32 -0
  355. data/ext/couchbase/couchbase/error_codes.hxx +33 -1
  356. data/ext/couchbase/couchbase/geo_bounding_box_query.hxx +1 -1
  357. data/ext/couchbase/couchbase/geo_distance_query.hxx +1 -1
  358. data/ext/couchbase/couchbase/geo_polygon_query.hxx +1 -1
  359. data/ext/couchbase/couchbase/get_replica_options.hxx +68 -0
  360. data/ext/couchbase/couchbase/get_replica_result.hxx +5 -3
  361. data/ext/couchbase/couchbase/get_replica_strategy.hxx +161 -0
  362. data/ext/couchbase/couchbase/get_result.hxx +1 -0
  363. data/ext/couchbase/couchbase/increment_options.hxx +1 -1
  364. data/ext/couchbase/couchbase/insert_options.hxx +1 -1
  365. data/ext/couchbase/couchbase/match_phrase_query.hxx +1 -1
  366. data/ext/couchbase/couchbase/match_query.hxx +1 -1
  367. data/ext/couchbase/couchbase/mutate_in_options.hxx +3 -3
  368. data/ext/couchbase/couchbase/network_options.hxx +1 -1
  369. data/ext/couchbase/couchbase/node_id.hxx +42 -14
  370. data/ext/couchbase/couchbase/node_id_for_options.hxx +7 -1
  371. data/ext/couchbase/couchbase/node_ids_options.hxx +8 -2
  372. data/ext/couchbase/couchbase/numeric_range_query.hxx +1 -1
  373. data/ext/couchbase/couchbase/phrase_query.hxx +1 -1
  374. data/ext/couchbase/couchbase/prefix_query.hxx +1 -1
  375. data/ext/couchbase/couchbase/query_options.hxx +23 -12
  376. data/ext/couchbase/couchbase/query_row.hxx +111 -0
  377. data/ext/couchbase/couchbase/query_stream_result.hxx +302 -0
  378. data/ext/couchbase/couchbase/query_string_query.hxx +3 -3
  379. data/ext/couchbase/couchbase/regexp_query.hxx +1 -1
  380. data/ext/couchbase/couchbase/replace_options.hxx +3 -3
  381. data/ext/couchbase/couchbase/result.hxx +14 -3
  382. data/ext/couchbase/couchbase/scan_result_item.hxx +1 -0
  383. data/ext/couchbase/couchbase/scope.hxx +85 -2
  384. data/ext/couchbase/couchbase/search_options.hxx +58 -8
  385. data/ext/couchbase/couchbase/search_scoring.hxx +94 -0
  386. data/ext/couchbase/couchbase/search_scoring_none.hxx +51 -0
  387. data/ext/couchbase/couchbase/search_scoring_reciprocal_rank_fusion.hxx +88 -0
  388. data/ext/couchbase/couchbase/search_scoring_relative_score_fusion.hxx +70 -0
  389. data/ext/couchbase/couchbase/term_range_query.hxx +1 -1
  390. data/ext/couchbase/couchbase/tracing/request_span.hxx +46 -0
  391. data/ext/couchbase/couchbase/transactions/transaction_get_multi_replicas_from_preferred_server_group_result.hxx +23 -21
  392. data/ext/couchbase/couchbase/transactions/transaction_get_multi_result.hxx +24 -19
  393. data/ext/couchbase/couchbase/transactions/transaction_get_result.hxx +17 -3
  394. data/ext/couchbase/couchbase/transactions/transactions_config.hxx +4 -2
  395. data/ext/couchbase/couchbase/transactions.hxx +27 -18
  396. data/ext/couchbase/couchbase/upsert_options.hxx +3 -3
  397. data/ext/couchbase/couchbase/vector_query.hxx +1 -1
  398. data/ext/couchbase/couchbase/wait_until_ready_options.hxx +111 -0
  399. data/ext/couchbase/couchbase/wildcard_query.hxx +1 -1
  400. data/ext/extconf.rb +15 -10
  401. data/ext/rcb_analytics.cxx +82 -102
  402. data/ext/rcb_backend.cxx +42 -36
  403. data/ext/rcb_backend.hxx +2 -0
  404. data/ext/rcb_buckets.cxx +47 -59
  405. data/ext/rcb_collections.cxx +42 -52
  406. data/ext/rcb_crud.cxx +345 -224
  407. data/ext/rcb_diagnostics.cxx +117 -27
  408. data/ext/rcb_exceptions.cxx +152 -99
  409. data/ext/rcb_exceptions.hxx +25 -0
  410. data/ext/rcb_extras.cxx +18 -19
  411. data/ext/rcb_hdr_histogram.cxx +19 -4
  412. data/ext/rcb_logger.cxx +202 -27
  413. data/ext/rcb_logger.hxx +12 -0
  414. data/ext/rcb_multi.cxx +40 -40
  415. data/ext/rcb_observability.cxx +7 -5
  416. data/ext/rcb_query.cxx +99 -142
  417. data/ext/rcb_range_scan.cxx +41 -35
  418. data/ext/rcb_search.cxx +98 -99
  419. data/ext/rcb_users.cxx +36 -56
  420. data/ext/rcb_utils.cxx +100 -37
  421. data/ext/rcb_utils.hxx +287 -33
  422. data/ext/rcb_version.cxx +1 -1
  423. data/ext/rcb_views.cxx +55 -51
  424. data/lib/active_support/cache/couchbase_store.rb +77 -12
  425. data/lib/couchbase/bucket.rb +20 -0
  426. data/lib/couchbase/cluster.rb +17 -0
  427. data/lib/couchbase/collection.rb +36 -1
  428. data/lib/couchbase/errors.rb +18 -0
  429. data/lib/couchbase/fork_hooks.rb +16 -7
  430. data/lib/couchbase/get_replica_strategy.rb +89 -0
  431. data/lib/couchbase/logger.rb +1 -1
  432. data/lib/couchbase/management/analytics_index_manager.rb +15 -15
  433. data/lib/couchbase/management/bucket_manager.rb +6 -6
  434. data/lib/couchbase/management/collection_manager.rb +6 -6
  435. data/lib/couchbase/management/query_index_manager.rb +7 -7
  436. data/lib/couchbase/management/search_index_manager.rb +13 -13
  437. data/lib/couchbase/management/user_manager.rb +10 -10
  438. data/lib/couchbase/management/view_index_manager.rb +5 -5
  439. data/lib/couchbase/options.rb +174 -42
  440. data/lib/couchbase/protostellar/bucket.rb +4 -0
  441. data/lib/couchbase/protostellar/cluster.rb +4 -0
  442. data/lib/couchbase/protostellar/collection.rb +4 -0
  443. data/lib/couchbase/protostellar/error_handling.rb +2 -1
  444. data/lib/couchbase/protostellar/request.rb +1 -0
  445. data/lib/couchbase/protostellar/request_generator/kv.rb +16 -2
  446. data/lib/couchbase/protostellar/request_generator/search.rb +17 -1
  447. data/lib/couchbase/protostellar/retry/orchestrator.rb +3 -2
  448. data/lib/couchbase/protostellar/retry/strategies/fail_fast.rb +33 -0
  449. data/lib/couchbase/protostellar/retry/strategies.rb +1 -0
  450. data/lib/couchbase/search_options.rb +95 -6
  451. data/lib/couchbase/version.rb +1 -1
  452. metadata +91 -33
  453. data/ext/0001-fix-build-for-mingw-w64-ucrt-x86_64-toolchain.patch +0 -40
  454. data/ext/couchbase/core/columnar/agent.hxx +0 -71
  455. data/ext/couchbase/core/columnar/agent_config.hxx +0 -59
  456. data/ext/couchbase/core/columnar/background_bootstrap_listener.hxx +0 -42
  457. data/ext/couchbase/core/columnar/backoff_calculator.cxx +0 -62
  458. data/ext/couchbase/core/columnar/columnar_agent.cxx +0 -147
  459. data/ext/couchbase/core/columnar/columnar_agent_config.cxx +0 -48
  460. data/ext/couchbase/core/columnar/columnar_error.cxx +0 -51
  461. data/ext/couchbase/core/columnar/database_management_options.hxx +0 -56
  462. data/ext/couchbase/core/columnar/error.hxx +0 -51
  463. data/ext/couchbase/core/columnar/error_codes.cxx +0 -107
  464. data/ext/couchbase/core/columnar/error_codes.hxx +0 -75
  465. data/ext/couchbase/core/columnar/management_component.cxx +0 -300
  466. data/ext/couchbase/core/columnar/management_component.hxx +0 -56
  467. data/ext/couchbase/core/columnar/query_component.cxx +0 -523
  468. data/ext/couchbase/core/columnar/query_component.hxx +0 -57
  469. data/ext/couchbase/core/columnar/query_options.hxx +0 -59
  470. data/ext/couchbase/core/columnar/query_result.cxx +0 -130
  471. data/ext/couchbase/core/columnar/query_result.hxx +0 -78
  472. data/ext/couchbase/core/io/config_tracker.cxx +0 -687
  473. data/ext/couchbase/core/io/config_tracker.hxx +0 -123
@@ -0,0 +1,243 @@
1
+ /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Copyright 2026. 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_stream_component.hxx"
19
+
20
+ #include "free_form_http_request.hxx"
21
+ #include "http_component.hxx"
22
+ #include "impl/bootstrap_error.hxx"
23
+ #include "logger/logger.hxx"
24
+ #include "operations/document_query.hxx"
25
+ #include "platform/uuid.h"
26
+ #include "service_type.hxx"
27
+ #include "utils/json.hxx"
28
+
29
+ #include <couchbase/error_codes.hxx>
30
+
31
+ #include <asio/io_context.hpp>
32
+ #include <spdlog/fmt/bundled/core.h>
33
+ #include <tao/json/value.hpp>
34
+
35
+ #include <chrono>
36
+ #include <memory>
37
+ #include <mutex>
38
+ #include <string>
39
+ #include <system_error>
40
+ #include <utility>
41
+
42
+ namespace couchbase::core
43
+ {
44
+ namespace
45
+ {
46
+ auto
47
+ to_error_code(std::error_code err) -> std::error_code
48
+ {
49
+ return err;
50
+ }
51
+
52
+ auto
53
+ build_streaming_query_body(const operations::query_request& request,
54
+ const std::string& client_context_id,
55
+ std::chrono::milliseconds timeout) -> std::string
56
+ {
57
+ tao::json::value body{};
58
+
59
+ // The remaining options are identical to the buffered query path; share one encoder so the two
60
+ // stay byte-for-byte consistent. The use_replica capability gate is enforced earlier in
61
+ // cluster::query_stream. This runs first so the control fields set below always win over any
62
+ // same-named `raw` entry a caller may have supplied.
63
+ operations::encode_query_options(body, request);
64
+
65
+ auto timeout_for_service = timeout;
66
+ if (timeout_for_service > std::chrono::milliseconds(5'000)) {
67
+ // Tell the query engine its deadline is 500ms tighter than ours, so we always observe the
68
+ // server-side timeout response before our own deadline fires.
69
+ timeout_for_service -= std::chrono::milliseconds(500);
70
+ }
71
+ body["client_context_id"] = client_context_id;
72
+ body["statement"] = request.statement;
73
+ body["timeout"] = fmt::format("{}ms", timeout_for_service.count());
74
+
75
+ return utils::json::generate(body);
76
+ }
77
+ } // namespace
78
+
79
+ class query_stream_component_impl : public std::enable_shared_from_this<query_stream_component_impl>
80
+ {
81
+ public:
82
+ query_stream_component_impl(asio::io_context& io,
83
+ http_component http,
84
+ std::chrono::milliseconds default_timeout,
85
+ row_streamer_options streaming_options)
86
+ : io_{ io }
87
+ , http_{ std::move(http) }
88
+ , default_timeout_{ default_timeout }
89
+ , streaming_options_{ streaming_options }
90
+ {
91
+ }
92
+
93
+ void execute(operations::query_request request, query_stream_component::handler_type&& handler)
94
+ {
95
+ const std::string client_context_id =
96
+ request.client_context_id.value_or(uuid::to_string(uuid::random()));
97
+ const std::chrono::milliseconds timeout = request.timeout.value_or(default_timeout_);
98
+
99
+ http_request http_req{ service_type::query, "POST" };
100
+ http_req.path = "/query/service";
101
+
102
+ // Everything about the request that an error context reports, known before dispatch. The
103
+ // response-side fields (HTTP status, the service's first error, the endpoint) are filled in as
104
+ // they become available, so a failure at any stage carries as much detail as the buffered path.
105
+ // Held behind a shared_ptr, not by value: it carries the encoded request body in
106
+ // `parameters`, and both the dispatch callback and the synchronous dispatch-failure branch
107
+ // below need it, so sharing avoids deep-copying that body on every streaming request.
108
+ auto base_ctx = std::make_shared<error_context::query>();
109
+ base_ctx->client_context_id = client_context_id;
110
+ base_ctx->statement = request.statement;
111
+ base_ctx->method = http_req.method;
112
+ base_ctx->path = http_req.path;
113
+
114
+ try {
115
+ http_req.body = build_streaming_query_body(request, client_context_id, timeout);
116
+ } catch (const std::exception&) {
117
+ // A caller-supplied raw/parameter value that is not valid JSON fails encoding; surface it as
118
+ // invalid_argument rather than letting the exception escape the public API.
119
+ base_ctx->ec = errc::common::invalid_argument;
120
+ return handler({}, std::move(*base_ctx));
121
+ }
122
+ base_ctx->parameters = http_req.body;
123
+ http_req.timeout = timeout;
124
+ http_req.client_context_id = client_context_id;
125
+ http_req.is_read_only = request.readonly;
126
+ http_req.headers["connection"] = "keep-alive";
127
+ http_req.headers["content-type"] = "application/json";
128
+ if (request.parent_span) {
129
+ http_req.parent_span = request.parent_span;
130
+ }
131
+
132
+ auto callback_state = std::make_shared<callback_state_type>(std::move(handler));
133
+
134
+ using dispatch_error = std::error_code;
135
+
136
+ const bool read_only = request.readonly;
137
+ auto op = http_.do_http_request(
138
+ http_req,
139
+ [self = shared_from_this(), callback_state, timeout, read_only, base_ctx](
140
+ http_response resp, dispatch_error err) mutable {
141
+ if (auto ec = to_error_code(err)) {
142
+ base_ctx->ec = ec;
143
+ self->invoke(callback_state, {}, std::move(*base_ctx));
144
+ return;
145
+ }
146
+ // The response is in hand, so the context can now name the endpoint and HTTP status.
147
+ base_ctx->http_status = resp.status_code();
148
+ const auto dispatch_info = resp.dispatch_info();
149
+ base_ctx->hostname = dispatch_info.hostname;
150
+ base_ctx->port = dispatch_info.port;
151
+ if (!dispatch_info.remote_address.empty()) {
152
+ base_ctx->last_dispatched_to = dispatch_info.remote_address;
153
+ }
154
+ if (!dispatch_info.local_address.empty()) {
155
+ base_ctx->last_dispatched_from = dispatch_info.local_address;
156
+ }
157
+ // Use the cluster's streaming tuning, but bound the server between reads with this
158
+ // request's timeout: if it stalls mid-body the stream times out rather than hanging next()
159
+ // forever (the request timeout is otherwise released once headers arrive).
160
+ auto options = self->streaming_options_;
161
+ options.idle_timeout = timeout;
162
+ options.is_read_only = read_only;
163
+ auto stream =
164
+ std::make_shared<query_stream>(self->io_, resp.body(), options, resp.status_code());
165
+ stream->start(
166
+ [self, callback_state, stream, base_ctx](std::error_code early_error) mutable {
167
+ if (early_error) {
168
+ // The preamble is what carried the failure, so stamp its diagnostics before tearing
169
+ // the stream down.
170
+ base_ctx->ec = early_error;
171
+ apply_error_details(*base_ctx, stream->error_details());
172
+ // No consumer will ever take ownership of this stream, so tear the underlying body
173
+ // (socket + timers) down now rather than when the last handle drops.
174
+ stream->cancel();
175
+ self->invoke(callback_state, {}, std::move(*base_ctx));
176
+ return;
177
+ }
178
+ // Hand the base context to the consumer alongside the stream: a terminal error reached
179
+ // later is stamped onto it, so a mid-stream failure reports the same detail as this
180
+ // one.
181
+ self->invoke(callback_state, std::move(*stream), std::move(*base_ctx));
182
+ });
183
+ });
184
+
185
+ if (!op.has_value()) {
186
+ base_ctx->ec = to_error_code(op.error());
187
+ invoke(callback_state, {}, std::move(*base_ctx));
188
+ }
189
+ }
190
+
191
+ private:
192
+ struct callback_state_type {
193
+ explicit callback_state_type(query_stream_component::handler_type h)
194
+ : handler{ std::move(h) }
195
+ {
196
+ }
197
+
198
+ query_stream_component::handler_type handler;
199
+ std::mutex mutex{};
200
+ bool invoked{ false };
201
+ };
202
+
203
+ void invoke(const std::shared_ptr<callback_state_type>& state,
204
+ query_stream stream,
205
+ error_context::query ctx)
206
+ {
207
+ query_stream_component::handler_type handler;
208
+ {
209
+ const std::scoped_lock lock{ state->mutex };
210
+ if (state->invoked) {
211
+ return;
212
+ }
213
+ state->invoked = true;
214
+ handler = std::move(state->handler);
215
+ }
216
+ if (handler) {
217
+ handler(std::move(stream), std::move(ctx));
218
+ }
219
+ }
220
+
221
+ asio::io_context& io_;
222
+ http_component http_;
223
+ std::chrono::milliseconds default_timeout_;
224
+ row_streamer_options streaming_options_;
225
+ };
226
+
227
+ query_stream_component::query_stream_component(asio::io_context& io,
228
+ http_component http,
229
+ std::chrono::milliseconds default_timeout,
230
+ row_streamer_options streaming_options)
231
+ : impl_{ std::make_shared<query_stream_component_impl>(io,
232
+ std::move(http),
233
+ default_timeout,
234
+ streaming_options) }
235
+ {
236
+ }
237
+
238
+ void
239
+ query_stream_component::execute(operations::query_request request, handler_type&& handler) const
240
+ {
241
+ impl_->execute(std::move(request), std::move(handler));
242
+ }
243
+ } // namespace couchbase::core
@@ -0,0 +1,68 @@
1
+ /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Copyright 2026. 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 "error_context/query.hxx"
21
+ #include "operations/document_query.hxx"
22
+ #include "query_stream.hxx"
23
+ #include "utils/movable_function.hxx"
24
+
25
+ #include <chrono>
26
+ #include <memory>
27
+ #include <system_error>
28
+
29
+ namespace asio
30
+ {
31
+ class io_context;
32
+ } // namespace asio
33
+
34
+ namespace couchbase::core
35
+ {
36
+ class http_component;
37
+
38
+ /**
39
+ * Dispatches a classic N1QL query as a streaming HTTP request and resolves to a query_stream
40
+ * handle once the response preamble (signature + upfront errors) has been parsed.
41
+ *
42
+ * Unlike the buffered query() path this never materialises the full response body. It performs no
43
+ * client-side retry or prepared-statement caching: the streaming path is only taken for adhoc
44
+ * requests (the public layer routes prepared statements to the buffered path).
45
+ */
46
+ class query_stream_component
47
+ {
48
+ public:
49
+ // The context carries the error code (error_context::query::ec) alongside the diagnostics the
50
+ // buffered path reports — statement, parameters, the service's first error, HTTP status and body,
51
+ // and where the request was dispatched — so a streaming failure is as diagnosable as a buffered
52
+ // one. It is delivered on both outcomes: when the stream fails to start it describes that
53
+ // failure, and when it starts it describes the request and its dispatch, for the consumer to
54
+ // report a terminal error against later. Only `ec` differs between the two: falsy means the
55
+ // stream started.
56
+ using handler_type = utils::movable_function<void(query_stream, error_context::query)>;
57
+
58
+ query_stream_component(asio::io_context& io,
59
+ http_component http,
60
+ std::chrono::milliseconds default_timeout,
61
+ row_streamer_options streaming_options = {});
62
+
63
+ void execute(operations::query_request request, handler_type&& handler) const;
64
+
65
+ private:
66
+ std::shared_ptr<class query_stream_component_impl> impl_;
67
+ };
68
+ } // namespace couchbase::core
@@ -36,7 +36,7 @@ range_scan_node_state::range_scan_node_state(std::queue<std::uint16_t> vbuckets)
36
36
  auto
37
37
  range_scan_node_state::fetch_vbucket_id() -> std::optional<std::uint16_t>
38
38
  {
39
- const std::lock_guard<std::mutex> lock{ mutex_ };
39
+ const std::scoped_lock<std::mutex> lock{ mutex_ };
40
40
  if (pending_vbuckets_.empty()) {
41
41
  return {};
42
42
  }
@@ -49,28 +49,28 @@ range_scan_node_state::fetch_vbucket_id() -> std::optional<std::uint16_t>
49
49
  void
50
50
  range_scan_node_state::notify_stream_ended()
51
51
  {
52
- const std::lock_guard<std::mutex> lock{ mutex_ };
52
+ const std::scoped_lock<std::mutex> lock{ mutex_ };
53
53
  active_stream_count_--;
54
54
  }
55
55
 
56
56
  void
57
57
  range_scan_node_state::enqueue_vbucket(std::uint16_t vbucket_id)
58
58
  {
59
- const std::lock_guard<std::mutex> lock{ mutex_ };
59
+ const std::scoped_lock<std::mutex> lock{ mutex_ };
60
60
  pending_vbuckets_.push(vbucket_id);
61
61
  }
62
62
 
63
63
  auto
64
64
  range_scan_node_state::active_stream_count() -> std::uint16_t
65
65
  {
66
- const std::lock_guard<std::mutex> lock{ mutex_ };
66
+ const std::scoped_lock<std::mutex> lock{ mutex_ };
67
67
  return active_stream_count_;
68
68
  }
69
69
 
70
70
  auto
71
71
  range_scan_node_state::pending_vbucket_count() -> std::size_t
72
72
  {
73
- const std::lock_guard<std::mutex> lock{ mutex_ };
73
+ const std::scoped_lock<std::mutex> lock{ mutex_ };
74
74
  return pending_vbuckets_.size();
75
75
  }
76
76
 
@@ -81,8 +81,15 @@ range_scan_load_balancer::range_scan_load_balancer(
81
81
  {
82
82
  std::map<std::int16_t, std::queue<std::uint16_t>> node_to_vbucket_map{};
83
83
  for (std::size_t vbucket_id = 0; vbucket_id < vbucket_map.size(); vbucket_id++) {
84
- auto node_id = vbucket_map[vbucket_id][0];
85
- node_to_vbucket_map[node_id].push(gsl::narrow_cast<std::uint16_t>(vbucket_id));
84
+ const auto& chain = vbucket_map[vbucket_id];
85
+ if (chain.empty()) {
86
+ // A row that names no node at all cannot be scanned, and there is no node
87
+ // to queue it against. range_scan_orchestrator refuses such a map before
88
+ // it starts any stream, so leaving the vbucket out here cannot silently
89
+ // shorten a scan.
90
+ continue;
91
+ }
92
+ node_to_vbucket_map[chain[0]].push(gsl::narrow_cast<std::uint16_t>(vbucket_id));
86
93
  }
87
94
  for (auto [node_id, vbucket_ids] : node_to_vbucket_map) {
88
95
  nodes_.emplace(node_id, std::move(vbucket_ids));
@@ -98,7 +105,7 @@ range_scan_load_balancer::seed(std::uint64_t seed)
98
105
  auto
99
106
  range_scan_load_balancer::select_vbucket() -> std::optional<std::uint16_t>
100
107
  {
101
- const std::lock_guard<std::mutex> lock{ select_vbucket_mutex_ };
108
+ const std::scoped_lock<std::mutex> lock{ select_vbucket_mutex_ };
102
109
 
103
110
  auto min_stream_count = std::numeric_limits<std::uint16_t>::max();
104
111
  std::optional<std::int16_t> selected_node_id{};
@@ -31,6 +31,7 @@
31
31
 
32
32
  #include <gsl/util>
33
33
 
34
+ #include <algorithm>
34
35
  #include <atomic>
35
36
  #include <chrono>
36
37
  #include <future>
@@ -398,6 +399,16 @@ public:
398
399
  return cb(errc::common::invalid_argument, {});
399
400
  }
400
401
 
402
+ // A scan needs an active copy for every vbucket, and every row of the map is
403
+ // indexed below to find one. A row that names no node at all leaves the scan
404
+ // unable to cover its vbucket, which is reported rather than served as a
405
+ // silently short result.
406
+ if (std::any_of(vbucket_map_.begin(), vbucket_map_.end(), [](const auto& chain) {
407
+ return chain.empty();
408
+ })) {
409
+ return cb(errc::network::configuration_not_available, {});
410
+ }
411
+
401
412
  const get_collection_id_options get_cid_options{ options_.retry_strategy,
402
413
  options_.timeout,
403
414
  options_.parent_span };
@@ -429,7 +440,8 @@ public:
429
440
  };
430
441
 
431
442
  // Get the active node for the vbucket (values in vbucket map are the active node id
432
- // followed by the ids of the replicas)
443
+ // followed by the ids of the replicas). scan() has already established that every row
444
+ // names one.
433
445
  auto node_id = self->vbucket_map_[vbucket][0];
434
446
 
435
447
  auto stream = std::make_shared<range_scan_stream>(
@@ -510,7 +522,7 @@ public:
510
522
  } else {
511
523
  // Empty signal means that stream has completed
512
524
  {
513
- const std::lock_guard<std::mutex> lock{ self->stream_map_mutex_ };
525
+ const std::scoped_lock<std::mutex> lock{ self->stream_map_mutex_ };
514
526
  self->streams_.erase(signal.vbucket_id);
515
527
  }
516
528
  return asio::post(asio::bind_executor(
@@ -540,7 +552,7 @@ public:
540
552
  auto v = vbucket_id.value();
541
553
  std::shared_ptr<range_scan_stream> stream{};
542
554
  {
543
- const std::lock_guard<std::mutex> lock{ stream_map_mutex_ };
555
+ const std::scoped_lock<std::mutex> lock{ stream_map_mutex_ };
544
556
  stream = streams_.at(v);
545
557
  }
546
558
  CB_LOG_TRACE("scanning vbucket {} at node {}", vbucket_id.value(), stream->node_id());
@@ -18,28 +18,65 @@
18
18
  #pragma once
19
19
 
20
20
  #include "core/error_context/key_value_error_map_info.hxx"
21
+
21
22
  #include <couchbase/retry_reason.hxx>
22
23
 
23
24
  #include <memory>
24
25
  #include <optional>
25
26
  #include <system_error>
26
27
 
28
+ namespace couchbase::core::mcbp
29
+ {
30
+ class queue_request;
31
+ } // namespace couchbase::core::mcbp
32
+
27
33
  namespace couchbase::core
28
34
  {
29
35
  namespace io
30
36
  {
31
37
  struct mcbp_message;
38
+ class mcbp_session;
32
39
  } // namespace io
33
- namespace mcbp
34
- {
35
- class queue_request;
36
- } // namespace mcbp
37
40
 
41
+ /**
42
+ * Interface for handling MCBP (Memcached Binary Protocol) responses dispatched by
43
+ * @ref io::mcbp_session.
44
+ *
45
+ * Implementors receive the decoded response together with enough context to populate
46
+ * dispatch tracing spans and key-value error contexts without holding a long-lived
47
+ * reference to the session.
48
+ *
49
+ * @note Adding, removing, or reordering parameters of @ref handle_response is an ABI
50
+ * breaking change for any out-of-tree implementors of this interface.
51
+ */
38
52
  class response_handler
39
53
  {
40
54
  public:
55
+ response_handler() = default;
56
+ response_handler(const response_handler&) = default;
57
+ response_handler(response_handler&&) = delete;
58
+ auto operator=(const response_handler&) -> response_handler& = default;
59
+ auto operator=(response_handler&&) -> response_handler& = delete;
41
60
  virtual ~response_handler() = default;
61
+
62
+ /**
63
+ * Called by @ref io::mcbp_session when a queued request completes (successfully or with
64
+ * an error).
65
+ *
66
+ * @param request The originating request. May be empty when the session is shutting
67
+ * down and synthetically cancels in-flight operations.
68
+ * @param session A snapshot of the session that delivered the response, carrying
69
+ * connection metadata (remote/local address and port) needed to populate
70
+ * dispatch tracing spans and error contexts. Used by
71
+ * @ref crud_component (CXXCBC-798) to build
72
+ * @ref key_value_error_context without retaining a live session reference.
73
+ * @param error Transport-level or protocol-level error code; empty on success.
74
+ * @param reason Retry classification hint supplied by the session.
75
+ * @param msg The raw decoded MCBP response message.
76
+ * @param error_info Optional extended error information from the server's error map.
77
+ */
42
78
  virtual void handle_response(std::shared_ptr<mcbp::queue_request> request,
79
+ std::optional<io::mcbp_session> session,
43
80
  std::error_code error,
44
81
  retry_reason reason,
45
82
  io::mcbp_message msg,