couchbase 3.8.2 → 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 (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 +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 +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 +59 -5
  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 +3 -29
  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 +32 -0
  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
@@ -15,6 +15,8 @@
15
15
  * limitations under the License.
16
16
  */
17
17
 
18
+ #include <couchbase/build_config.hxx>
19
+
18
20
  #include "core/cluster.hxx"
19
21
 
20
22
  #include "analytics.hxx"
@@ -23,6 +25,7 @@
23
25
  #include "core/cluster_options.hxx"
24
26
  #include "core/core_sdk_shim.hxx"
25
27
  #include "core/io/ip_protocol.hxx"
28
+ #include "core/io/streams.hxx"
26
29
  #include "core/origin.hxx"
27
30
  #include "core/tls_verify_mode.hxx"
28
31
  #include "core/tracing/constants.hxx"
@@ -36,6 +39,7 @@
36
39
  #include "observability_recorder.hxx"
37
40
  #include "query.hxx"
38
41
  #include "search.hxx"
42
+ #include "wait_until_ready.hxx"
39
43
 
40
44
  #include <couchbase/analytics_index_manager.hxx>
41
45
  #include <couchbase/analytics_options.hxx>
@@ -46,6 +50,7 @@
46
50
  #include <couchbase/cluster_options.hxx>
47
51
  #include <couchbase/diagnostics_options.hxx>
48
52
  #include <couchbase/diagnostics_result.hxx>
53
+ #include <couchbase/error_codes.hxx>
49
54
  #include <couchbase/fmt/error.hxx>
50
55
  #include <couchbase/fork_event.hxx>
51
56
  #include <couchbase/ip_protocol.hxx>
@@ -175,6 +180,8 @@ options_to_origin(const std::string& connection_string, cluster_options::built o
175
180
  user_options.server_group = opts.network.server_group;
176
181
 
177
182
  user_options.enable_compression = opts.compression.enabled;
183
+ user_options.compression_min_size = opts.compression.min_size;
184
+ user_options.compression_min_ratio = opts.compression.min_ratio;
178
185
 
179
186
  user_options.enable_metrics = opts.metrics.enabled;
180
187
  if (opts.metrics.enabled) {
@@ -325,6 +332,28 @@ public:
325
332
  });
326
333
  }
327
334
 
335
+ // The open notify_fork(child) starts and does not wait for. Requests issued meanwhile wait in the
336
+ // core for the bootstrap. A failed open leaves the core closed, so they then get cluster_closed.
337
+ //
338
+ // The handler captures `this`. It runs inline when open() fails or succeeds without I/O, and
339
+ // otherwise on the IO thread before do_close() joins it: do_close() closes the core first, which
340
+ // completes a pending open.
341
+ void reopen()
342
+ {
343
+ opened_future_ = opened_.get_future().share();
344
+ core_.open(options_to_origin(connection_string_, options_), [this](std::error_code ec) {
345
+ if (ec) {
346
+ CB_LOG_ERROR("Unable to reconnect instance after fork: {}", ec.message());
347
+ }
348
+ opened_.set_value();
349
+ });
350
+ // Created now, not after the bootstrap, so transactions() never sees it unset and nothing
351
+ // writes it from the IO thread. The requests its cleanup issues wait in the core for the
352
+ // bootstrap.
353
+ transactions_ =
354
+ std::make_shared<core::transactions::transactions>(core_, options_.transactions);
355
+ }
356
+
328
357
  void query(std::string statement, query_options::built options, query_handler&& handler) const
329
358
  {
330
359
  auto obs_rec = create_observability_recorder(
@@ -341,6 +370,22 @@ public:
341
370
  });
342
371
  }
343
372
 
373
+ void query_stream(std::string statement,
374
+ query_options::built options,
375
+ query_stream_handler&& handler) const
376
+ {
377
+ // Instrument the streaming operation exactly like the buffered query(): build the recorder,
378
+ // thread its operation span into the request as parent_span, and hand the recorder to the
379
+ // stream so it finishes (latency metric + span end) at the terminal.
380
+ auto obs_rec = create_observability_recorder(
381
+ core::tracing::operation::query, core::service_type::query, options.parent_span);
382
+ obs_rec->with_query_statement(statement, options);
383
+ auto request = core::impl::build_query_request(
384
+ std::move(statement), {}, std::move(options), obs_rec->operation_span());
385
+ core::impl::dispatch_query_stream(
386
+ core_, std::move(request), std::move(obs_rec), std::move(handler));
387
+ }
388
+
344
389
  void analytics_query(std::string statement,
345
390
  analytics_options::built options,
346
391
  analytics_handler&& handler) const
@@ -359,10 +404,36 @@ public:
359
404
  });
360
405
  }
361
406
 
407
+ void analytics_query_stream(std::string statement,
408
+ analytics_options::built options,
409
+ analytics_stream_handler&& handler) const
410
+ {
411
+ // Instrument the streaming operation exactly like the buffered analytics_query() (see
412
+ // query_stream above for the recorder lifetime).
413
+ auto obs_rec = create_observability_recorder(
414
+ core::tracing::operation::analytics, core::service_type::analytics, options.parent_span);
415
+ obs_rec->with_query_statement(statement, options);
416
+ auto request = core::impl::build_analytics_request(
417
+ std::move(statement), std::move(options), {}, {}, obs_rec->operation_span());
418
+ core::impl::dispatch_analytics_stream(
419
+ core_, std::move(request), std::move(obs_rec), std::move(handler));
420
+ }
421
+
362
422
  void ping(const ping_options::built& options, ping_handler&& handler) const
363
423
  {
364
424
  auto obs_rec = create_observability_recorder(
365
425
  core::tracing::operation::ping, std::nullopt, options.parent_span);
426
+ #ifdef COUCHBASE_CXX_CLIENT_BUILD_COUCHBASE2
427
+ if (core_.is_protostellar()) {
428
+ // couchbase2 is a thin gRPC client with no per-service sessions to actively probe, and RFC 77
429
+ // defines no ping semantics for it. Mirror Java/Go/.NET, which surface ping as
430
+ // feature_not_available on this protocol, rather than returning a misleading empty report.
431
+ obs_rec->finish(errc::common::feature_not_available);
432
+ return handler(error{ errc::common::feature_not_available,
433
+ "ping is not supported over the couchbase2 protocol" },
434
+ {});
435
+ }
436
+ #endif
366
437
  return core_.ping(
367
438
  options.report_id,
368
439
  {},
@@ -378,6 +449,16 @@ public:
378
449
  {
379
450
  auto obs_rec = create_observability_recorder(
380
451
  core::tracing::operation::diagnostics, std::nullopt, options.parent_span);
452
+ #ifdef COUCHBASE_CXX_CLIENT_BUILD_COUCHBASE2
453
+ if (core_.is_protostellar()) {
454
+ // No per-service sessions exist to report on over couchbase2, and the RFC 77 Diagnostics
455
+ // section is empty. Mirror Java/Go/.NET (feature_not_available) instead of an empty report.
456
+ obs_rec->finish(errc::common::feature_not_available);
457
+ return handler(error{ errc::common::feature_not_available,
458
+ "diagnostics is not supported over the couchbase2 protocol" },
459
+ {});
460
+ }
461
+ #endif
381
462
  return core_.diagnostics(
382
463
  options.report_id,
383
464
  [obs_rec = std::move(obs_rec), handler = std::move(handler)](const auto& resp) mutable {
@@ -386,6 +467,20 @@ public:
386
467
  });
387
468
  }
388
469
 
470
+ void wait_until_ready(std::chrono::milliseconds timeout,
471
+ const wait_until_ready_options::built& options,
472
+ wait_until_ready_handler&& handler) const
473
+ {
474
+ return core::impl::wait_until_ready(core_,
475
+ std::nullopt,
476
+ timeout,
477
+ options.desired_state,
478
+ core::impl::to_core_service_types(options.service_types),
479
+ [handler = std::move(handler)](std::error_code ec) mutable {
480
+ return handler(couchbase::error{ ec });
481
+ });
482
+ }
483
+
389
484
  void search(std::string index_name,
390
485
  couchbase::search_request request,
391
486
  const search_options::built& options,
@@ -466,7 +561,7 @@ public:
466
561
  } catch (...) {
467
562
  // Undo everything this prepare did, then report. Returning stopped and threadless
468
563
  // would hang ~cluster_impl, which waits on a completion only the IO thread can
469
- // deliver -- the same hazard as the fork_child/fork_parent path below. The fork
564
+ // deliver -- the same hazard as the fork_parent path below. The fork
470
565
  // must not go ahead, but the cluster stays usable and destructible.
471
566
  //
472
567
  // The io_context comes back first: restarting cleanup spawns workers that issue KV
@@ -487,21 +582,12 @@ public:
487
582
  }
488
583
  throw;
489
584
  }
490
- } else {
491
- // TODO(CXXCBC-913): disown this cluster's sockets here, instead of leaving it to the
492
- // reconnect. epoll_reactor::notify_fork(fork_child) below re-registers every
493
- // descriptor inherited from the parent into the child's new epoll instance, so
494
- // from here until those sockets are closed the child polls file descriptions the
495
- // parent is still using. Closing them is at least no longer destructive -- see
496
- // stream_impl::close(), which detaches a socket it did not open rather than
497
- // shutting it down -- but it happens on the reconnect path, asynchronously, and
498
- // only once the replaced impl is destroyed.
585
+ } else if (event == fork_event::parent) {
499
586
  io_.restart();
500
587
  try {
501
588
  io_.notify_fork(fork_event_to_asio(event));
502
589
  } catch (...) {
503
- // notify_fork() throws if re-registering a descriptor with the new
504
- // epoll instance fails. The io_context is unusable after that (asio says
590
+ // A service's notify_fork() threw. The io_context is unusable after that (asio says
505
591
  // to destroy it), but destruction itself needs a runner: do_close()
506
592
  // waits on a completion only the IO thread can deliver, so returning
507
593
  // from here stopped and threadless would hang ~cluster_impl instead of
@@ -514,6 +600,29 @@ public:
514
600
  io_thread_ = std::thread{ [&io = io_] {
515
601
  io.run();
516
602
  } };
603
+ } else {
604
+ // The sockets of this io_context share open file descriptions with the parent, and their
605
+ // pending reads, writes and timers belong to the parent's sessions. The child detaches every
606
+ // registered stream and socket, then runs the inherited core's teardown to completion. The
607
+ // teardown cannot reach the parent's connections through them.
608
+ //
609
+ // close() comes before the fixup. It sets stopped_, so if the fixup throws, ~cluster_impl
610
+ // still completes without a runner.
611
+ std::promise<void> closed;
612
+ auto closed_future = closed.get_future();
613
+ core_.close([closed = std::move(closed)]() mutable {
614
+ closed.set_value();
615
+ });
616
+ // The fixup gives the child its own reactor, and on kqueue it is the only code that repairs
617
+ // kqueue_fd_. It must come before the detach: releasing a socket removes it from the
618
+ // reactor, and until the fixup that reactor is the parent's.
619
+ io_.notify_fork(fork_event_to_asio(event));
620
+ core::io::detach_inherited_sockets(io_);
621
+ io_.restart();
622
+ io_thread_ = std::thread{ [&io = io_] {
623
+ io.run();
624
+ } };
625
+ closed_future.get();
517
626
  }
518
627
 
519
628
  // prepare was handled above, before the io_context was stopped. The child does
@@ -529,6 +638,13 @@ public:
529
638
  // Spawn new thread to avoid joining IO thread from the same thread
530
639
  std::thread([self = shared_from_this(), handler = std::move(handler)]() mutable {
531
640
  self->do_close();
641
+ // Drop the reference before signalling completion, not after. handler() is what releases
642
+ // the caller's wait, so anything this thread still owns afterwards outlives that wait. When
643
+ // this is the last reference, releasing it later means ~cluster_impl -- which starts another
644
+ // thread and joins the IO thread -- runs unsynchronised with the caller, and a caller that
645
+ // returns from main() leaves those threads running while static destructors tear down the
646
+ // gRPC and abseil singletons underneath them.
647
+ self.reset();
532
648
  handler();
533
649
  }).detach();
534
650
  }
@@ -538,14 +654,33 @@ public:
538
654
  return core_;
539
655
  }
540
656
 
541
- [[nodiscard]] auto transactions() const -> std::shared_ptr<core::transactions::transactions>
657
+ [[nodiscard]] auto core_transactions() const
658
+ -> const std::shared_ptr<core::transactions::transactions>&
542
659
  {
543
660
  return transactions_;
544
661
  }
545
662
 
663
+ [[nodiscard]] auto transactions() const -> std::shared_ptr<transactions::transactions>
664
+ {
665
+ return std::make_shared<transactions::transactions>(transactions_);
666
+ }
667
+
546
668
  private:
547
669
  void do_close()
548
670
  {
671
+ if (opened_future_.valid() &&
672
+ opened_future_.wait_for(std::chrono::seconds::zero()) != std::future_status::ready) {
673
+ // Closing the core fails the pending bootstrap and releases the requests the transactions
674
+ // cleanup holds, so neither wait below runs to bootstrap_timeout. The second core_.close()
675
+ // further down finds the core stopped and returns at once.
676
+ std::promise<void> core_stopped;
677
+ auto f = core_stopped.get_future();
678
+ core_.close([core_stopped = std::move(core_stopped)]() mutable {
679
+ core_stopped.set_value();
680
+ });
681
+ f.get();
682
+ opened_future_.wait();
683
+ }
549
684
  if (auto txns = std::move(transactions_); txns != nullptr) {
550
685
  // blocks until cleanup is finished
551
686
  txns->close();
@@ -580,7 +715,10 @@ private:
580
715
  cluster_options::built options_;
581
716
  asio::io_context io_{ ASIO_CONCURRENCY_HINT_SAFE };
582
717
  core::cluster core_{ io_ };
583
- std::shared_ptr<core::transactions::transactions> transactions_{ nullptr };
718
+ std::shared_ptr<couchbase::core::transactions::transactions> transactions_{ nullptr };
719
+ // Set by reopen(); fulfilled once its open has finished, either way. do_close() reads it.
720
+ std::promise<void> opened_{};
721
+ std::shared_future<void> opened_future_{};
584
722
  std::thread io_thread_{ [&io = io_] {
585
723
  io.run();
586
724
  } };
@@ -601,6 +739,19 @@ extract_core_cluster(const couchbase::cluster& cluster) -> const core::cluster&
601
739
  return reinterpret_cast<const std::shared_ptr<cluster_impl>*>(&cluster)->get()->core();
602
740
  }
603
741
 
742
+ /*
743
+ * This function exists only for usage in the unit tests, and might be removed at any moment.
744
+ * Avoid using it unless it is absolutely necessary.
745
+ */
746
+ auto
747
+ extract_core_transactions(const couchbase::cluster& cluster)
748
+ -> const std::shared_ptr<core::transactions::transactions>&
749
+ {
750
+ return reinterpret_cast<const std::shared_ptr<cluster_impl>*>(&cluster)
751
+ ->get()
752
+ ->core_transactions();
753
+ }
754
+
604
755
  void
605
756
  cluster::query(std::string statement, const query_options& options, query_handler&& handler) const
606
757
  {
@@ -619,6 +770,26 @@ cluster::query(std::string statement, const query_options& options) const
619
770
  return future;
620
771
  }
621
772
 
773
+ void
774
+ cluster::query_stream(std::string statement,
775
+ const query_options& options,
776
+ query_stream_handler&& handler) const
777
+ {
778
+ return impl_->query_stream(std::move(statement), options.build(), std::move(handler));
779
+ }
780
+
781
+ auto
782
+ cluster::query_stream(std::string statement, const query_options& options) const
783
+ -> std::future<std::pair<error, query_stream_result>>
784
+ {
785
+ auto barrier = std::make_shared<std::promise<std::pair<error, query_stream_result>>>();
786
+ auto future = barrier->get_future();
787
+ query_stream(std::move(statement), options, [barrier](auto err, auto result) {
788
+ barrier->set_value({ std::move(err), std::move(result) });
789
+ });
790
+ return future;
791
+ }
792
+
622
793
  void
623
794
  cluster::analytics_query(std::string statement,
624
795
  const analytics_options& options,
@@ -639,6 +810,26 @@ cluster::analytics_query(std::string statement, const analytics_options& options
639
810
  return future;
640
811
  }
641
812
 
813
+ void
814
+ cluster::analytics_query_stream(std::string statement,
815
+ const analytics_options& options,
816
+ analytics_stream_handler&& handler) const
817
+ {
818
+ return impl_->analytics_query_stream(std::move(statement), options.build(), std::move(handler));
819
+ }
820
+
821
+ auto
822
+ cluster::analytics_query_stream(std::string statement, const analytics_options& options) const
823
+ -> std::future<std::pair<error, analytics_stream_result>>
824
+ {
825
+ auto barrier = std::make_shared<std::promise<std::pair<error, analytics_stream_result>>>();
826
+ auto future = barrier->get_future();
827
+ analytics_query_stream(std::move(statement), options, [barrier](auto err, auto result) {
828
+ barrier->set_value({ std::move(err), std::move(result) });
829
+ });
830
+ return future;
831
+ }
832
+
642
833
  void
643
834
  cluster::ping(const couchbase::ping_options& options, couchbase::ping_handler&& handler) const
644
835
  {
@@ -674,6 +865,26 @@ cluster::diagnostics(const couchbase::diagnostics_options& options) const
674
865
  return barrier->get_future();
675
866
  }
676
867
 
868
+ void
869
+ cluster::wait_until_ready(std::chrono::milliseconds timeout,
870
+ const couchbase::wait_until_ready_options& options,
871
+ couchbase::wait_until_ready_handler&& handler) const
872
+ {
873
+ return impl_->wait_until_ready(timeout, options.build(), std::move(handler));
874
+ }
875
+
876
+ auto
877
+ cluster::wait_until_ready(std::chrono::milliseconds timeout,
878
+ const couchbase::wait_until_ready_options& options) const
879
+ -> std::future<error>
880
+ {
881
+ auto barrier = std::make_shared<std::promise<error>>();
882
+ wait_until_ready(timeout, options, [barrier](auto err) mutable {
883
+ barrier->set_value(std::move(err));
884
+ });
885
+ return barrier->get_future();
886
+ }
887
+
677
888
  void
678
889
  cluster::search(std::string index_name,
679
890
  search_request request,
@@ -751,34 +962,10 @@ cluster::notify_fork(fork_event event) -> void
751
962
  return;
752
963
  }
753
964
 
754
- auto new_impl = std::make_shared<cluster_impl>(impl_->connection_string(), impl_->options());
755
- impl_.reset();
756
-
757
- {
758
- auto barrier = std::make_shared<std::promise<void>>();
759
- auto future = barrier->get_future();
760
-
761
- new_impl->open([this, barrier, new_impl](const auto& err, const auto& /* c */) {
762
- if (err.ec()) {
763
- // TODO(SA): we should fall to background reconnect loop similar to Columnar build
764
- CB_LOG_ERROR("Unable to reconnect instance after fork: {}", err.ec().message());
765
- }
766
- // Adopt the new impl either way. Leaving impl_ null on failure turned the
767
- // child's next operation into a segfault, because every data-plane method
768
- // dereferences impl_ unchecked; an impl that failed to open reports
769
- // errc::network::cluster_closed instead, which is what a caller already gets
770
- // from a handle it acquired before the fork.
771
- impl_ = new_impl;
772
- // Always fulfill the barrier. Returning early here used to hang this
773
- // function forever: `barrier` is still owned by the enclosing scope below,
774
- // so the promise is never destroyed and future.get() never sees a
775
- // broken_promise either -- a failed post-fork reconnect just wedged the
776
- // caller.
777
- barrier->set_value();
778
- });
779
-
780
- future.get();
781
- }
965
+ impl_ = std::make_shared<cluster_impl>(impl_->connection_string(), impl_->options());
966
+ // Does not wait for the bootstrap: a cluster whose nodes do not answer would hold the child for
967
+ // the bootstrap timeout. The child has one thread here, so nothing reads impl_ concurrently.
968
+ impl_->reopen();
782
969
  #endif
783
970
  }
784
971