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,391 @@
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
+ // Views are deprecated in the core API but still routable over couchbase2, so the component names
21
+ // document_view_request in its interface. Suppress the core-deprecation attribute for this header's
22
+ // includes and declarations (portable convention shared with cluster.cxx). push/pop the macro so an
23
+ // including translation unit that already defined it keeps its state restored.
24
+ #pragma push_macro("COUCHBASE_CXX_CLIENT_IGNORE_CORE_DEPRECATIONS")
25
+ #define COUCHBASE_CXX_CLIENT_IGNORE_CORE_DEPRECATIONS
26
+
27
+ // The Protostellar KV component: the couchbase2 counterpart to the MCBP data-plane. It owns the
28
+ // gRPC stubs over a channel and executes core KV operations by encoding the request (kv_converter),
29
+ // dispatching it through the gRPC<->asio bridge, and decoding the reply plus a mapped error
30
+ // context. cluster_impl routes KV ops here when the cluster was opened with couchbase2://.
31
+
32
+ #include "core/cluster_credentials.hxx"
33
+ #include "core/io/mcbp_traits.hxx"
34
+ #include "core/operations/document_analytics.hxx"
35
+ #include "core/operations/document_append.hxx"
36
+ #include "core/operations/document_decrement.hxx"
37
+ #include "core/operations/document_exists.hxx"
38
+ #include "core/operations/document_get.hxx"
39
+ #include "core/operations/document_get_and_lock.hxx"
40
+ #include "core/operations/document_get_and_touch.hxx"
41
+ #include "core/operations/document_get_projected.hxx"
42
+ #include "core/operations/document_increment.hxx"
43
+ #include "core/operations/document_insert.hxx"
44
+ #include "core/operations/document_prepend.hxx"
45
+ #include "core/operations/document_query.hxx"
46
+ #include "core/operations/document_remove.hxx"
47
+ #include "core/operations/document_replace.hxx"
48
+ #include "core/operations/document_search.hxx"
49
+ #include "core/operations/document_touch.hxx"
50
+ #include "core/operations/document_unlock.hxx"
51
+ #include "core/operations/document_upsert.hxx"
52
+ #include "core/operations/document_view.hxx"
53
+ #include "core/operations/management/bucket_create.hxx"
54
+ #include "core/operations/management/bucket_drop.hxx"
55
+ #include "core/operations/management/bucket_flush.hxx"
56
+ #include "core/operations/management/bucket_get.hxx"
57
+ #include "core/operations/management/bucket_get_all.hxx"
58
+ #include "core/operations/management/bucket_update.hxx"
59
+ #include "core/operations/management/collection_create.hxx"
60
+ #include "core/operations/management/collection_drop.hxx"
61
+ #include "core/operations/management/collection_update.hxx"
62
+ #include "core/operations/management/query_index_build_deferred.hxx"
63
+ #include "core/operations/management/query_index_create.hxx"
64
+ #include "core/operations/management/query_index_drop.hxx"
65
+ #include "core/operations/management/query_index_get_all.hxx"
66
+ #include "core/operations/management/scope_create.hxx"
67
+ #include "core/operations/management/scope_drop.hxx"
68
+ #include "core/operations/management/scope_get_all.hxx"
69
+ #include "core/operations/management/search_index_analyze_document.hxx"
70
+ #include "core/operations/management/search_index_control_ingest.hxx"
71
+ #include "core/operations/management/search_index_control_plan_freeze.hxx"
72
+ #include "core/operations/management/search_index_control_query.hxx"
73
+ #include "core/operations/management/search_index_drop.hxx"
74
+ #include "core/operations/management/search_index_get.hxx"
75
+ #include "core/operations/management/search_index_get_all.hxx"
76
+ #include "core/operations/management/search_index_get_documents_count.hxx"
77
+ #include "core/operations/management/search_index_upsert.hxx"
78
+ #include "core/protostellar/compression_settings.hxx"
79
+ #include "core/protostellar/dispatcher.hxx"
80
+ #include "core/timeout_defaults.hxx"
81
+ #include "core/utils/movable_function.hxx"
82
+
83
+ #include <asio/io_context.hpp>
84
+
85
+ #include <chrono>
86
+ #include <memory>
87
+ #include <string>
88
+
89
+ namespace couchbase::core::protostellar
90
+ {
91
+
92
+ // Per-service defaults, used when a request does not carry its own timeout. Each field is defaulted
93
+ // from timeout_defaults rather than left value-initialised: a zero here no longer means "no limit"
94
+ // but "budget already spent", so a default-constructed aggregate would reject every request that
95
+ // relies on the default instead of running it.
96
+ struct component_timeouts {
97
+ std::chrono::milliseconds key_value{ timeout_defaults::key_value_timeout };
98
+ std::chrono::milliseconds query{ timeout_defaults::query_timeout };
99
+ std::chrono::milliseconds analytics{ timeout_defaults::analytics_timeout };
100
+ std::chrono::milliseconds search{ timeout_defaults::search_timeout };
101
+ std::chrono::milliseconds view{ timeout_defaults::view_timeout };
102
+ std::chrono::milliseconds management{ timeout_defaults::management_timeout };
103
+ std::chrono::milliseconds key_value_durable{ timeout_defaults::key_value_durable_timeout };
104
+ };
105
+
106
+ // Construction parameters for `component`, grouped so that adding one is a source-compatible
107
+ // change. Every field a caller can reasonably omit carries a default, so a new trailing field
108
+ // leaves existing initialisers compiling instead of silently shifting a positional argument onto
109
+ // the wrong parameter -- which is the failure this shape exists to prevent, the constructor having
110
+ // gained and lost trailing parameters repeatedly as services were added.
111
+ struct component_config {
112
+ std::shared_ptr<grpc::Channel> channel{};
113
+ cluster_credentials credentials{};
114
+ component_timeouts timeouts{};
115
+ kv::compression_settings compression{};
116
+ };
117
+
118
+ // The core KV request types the component can execute over couchbase2. cluster_impl routes only
119
+ // these to the component; any other KV request is answered with feature_not_available.
120
+ template<typename Request>
121
+ inline constexpr bool component_supports_v = false;
122
+ template<>
123
+ inline constexpr bool component_supports_v<operations::get_request> = true;
124
+ template<>
125
+ inline constexpr bool component_supports_v<operations::get_projected_request> = true;
126
+ template<>
127
+ inline constexpr bool component_supports_v<operations::upsert_request> = true;
128
+ template<>
129
+ inline constexpr bool component_supports_v<operations::insert_request> = true;
130
+ template<>
131
+ inline constexpr bool component_supports_v<operations::replace_request> = true;
132
+ template<>
133
+ inline constexpr bool component_supports_v<operations::remove_request> = true;
134
+ template<>
135
+ inline constexpr bool component_supports_v<operations::touch_request> = true;
136
+ template<>
137
+ inline constexpr bool component_supports_v<operations::exists_request> = true;
138
+ template<>
139
+ inline constexpr bool component_supports_v<operations::get_and_lock_request> = true;
140
+ template<>
141
+ inline constexpr bool component_supports_v<operations::unlock_request> = true;
142
+ template<>
143
+ inline constexpr bool component_supports_v<operations::get_and_touch_request> = true;
144
+ template<>
145
+ inline constexpr bool component_supports_v<operations::increment_request> = true;
146
+ template<>
147
+ inline constexpr bool component_supports_v<operations::decrement_request> = true;
148
+ template<>
149
+ inline constexpr bool component_supports_v<operations::append_request> = true;
150
+ template<>
151
+ inline constexpr bool component_supports_v<operations::prepend_request> = true;
152
+
153
+ // Resolves the effective timeout for a KV operation: the request's own timeout if set, else the
154
+ // per-service default — the durable default for a synchronous-durability mutation (RFC 77
155
+ // KvDurableTimeout), the standard KV default otherwise. Free function so it is unit-testable.
156
+ //
157
+ // No lower bound is imposed on an explicit request timeout. The MCBP path raises a durable
158
+ // operation's timeout to a 1500ms floor, which it needs because it has no durable default at all
159
+ // and a durable write there inherits the 2.5s KV budget; resolving KvDurableTimeout is the
160
+ // RFC-specified mechanism for that, and neither RFC 59 nor RFC 77 states a floor. A caller who
161
+ // names a timeout gets the one they named.
162
+ [[nodiscard]] inline auto
163
+ resolve_kv_timeout(std::optional<std::chrono::milliseconds> request_timeout,
164
+ couchbase::durability_level level,
165
+ const component_timeouts& timeouts) -> std::chrono::milliseconds
166
+ {
167
+ const auto fallback =
168
+ (level == couchbase::durability_level::none) ? timeouts.key_value : timeouts.key_value_durable;
169
+ return request_timeout.value_or(fallback);
170
+ }
171
+
172
+ // The durability level a request asks for, or `none` for a request type that cannot carry one.
173
+ // Lets a caller generic over the request type apply the rule above without knowing which types
174
+ // have the member; `supports_durability_v` is the same trait the MCBP path keys its own durability
175
+ // handling on, so the two transports agree on which operations are durable.
176
+ template<class Request>
177
+ [[nodiscard]] auto
178
+ requested_durability(const Request& request) -> couchbase::durability_level
179
+ {
180
+ if constexpr (io::mcbp_traits::supports_durability_v<Request>) {
181
+ return request.durability_level;
182
+ } else {
183
+ static_cast<void>(request);
184
+ return couchbase::durability_level::none;
185
+ }
186
+ }
187
+
188
+ class component
189
+ {
190
+ public:
191
+ component(asio::io_context& io, component_config config);
192
+ component(const component&) = delete;
193
+ component(component&&) = delete;
194
+ auto operator=(const component&) -> component& = delete;
195
+ auto operator=(component&&) -> component& = delete;
196
+ // Out of line: `stubs` is incomplete here, so its deleter cannot be instantiated in this header.
197
+ ~component();
198
+
199
+ // The channel every call of this component is issued on.
200
+ [[nodiscard]] auto channel() const -> const std::shared_ptr<grpc::Channel>&;
201
+
202
+ auto execute(const operations::get_request& request,
203
+ utils::movable_function<void(operations::get_response)>&& handler) -> pending_call;
204
+ auto execute(const operations::get_projected_request& request,
205
+ utils::movable_function<void(operations::get_projected_response)>&& handler)
206
+ -> pending_call;
207
+ auto execute(const operations::upsert_request& request,
208
+ utils::movable_function<void(operations::upsert_response)>&& handler)
209
+ -> pending_call;
210
+ auto execute(const operations::insert_request& request,
211
+ utils::movable_function<void(operations::insert_response)>&& handler)
212
+ -> pending_call;
213
+ auto execute(const operations::replace_request& request,
214
+ utils::movable_function<void(operations::replace_response)>&& handler)
215
+ -> pending_call;
216
+ auto execute(const operations::remove_request& request,
217
+ utils::movable_function<void(operations::remove_response)>&& handler)
218
+ -> pending_call;
219
+ auto execute(const operations::touch_request& request,
220
+ utils::movable_function<void(operations::touch_response)>&& handler) -> pending_call;
221
+ auto execute(const operations::exists_request& request,
222
+ utils::movable_function<void(operations::exists_response)>&& handler)
223
+ -> pending_call;
224
+ auto execute(const operations::get_and_lock_request& request,
225
+ utils::movable_function<void(operations::get_and_lock_response)>&& handler)
226
+ -> pending_call;
227
+ auto execute(const operations::unlock_request& request,
228
+ utils::movable_function<void(operations::unlock_response)>&& handler)
229
+ -> pending_call;
230
+ auto execute(const operations::get_and_touch_request& request,
231
+ utils::movable_function<void(operations::get_and_touch_response)>&& handler)
232
+ -> pending_call;
233
+ auto execute(const operations::increment_request& request,
234
+ utils::movable_function<void(operations::increment_response)>&& handler)
235
+ -> pending_call;
236
+ auto execute(const operations::decrement_request& request,
237
+ utils::movable_function<void(operations::decrement_response)>&& handler)
238
+ -> pending_call;
239
+ auto execute(const operations::append_request& request,
240
+ utils::movable_function<void(operations::append_response)>&& handler)
241
+ -> pending_call;
242
+ auto execute(const operations::prepend_request& request,
243
+ utils::movable_function<void(operations::prepend_response)>&& handler)
244
+ -> pending_call;
245
+
246
+ // N1QL query over the couchbase2 server-streaming transport. Rows are buffered into the response
247
+ // when no callback is provided, or delivered incrementally to row_callback when present; the
248
+ // terminal message carries the metadata.
249
+ auto execute(const operations::query_request& request,
250
+ utils::movable_function<void(operations::query_response)>&& handler) -> pending_call;
251
+
252
+ // Analytics over the couchbase2 server-streaming transport; same shape as query.
253
+ auto execute(const operations::analytics_request& request,
254
+ utils::movable_function<void(operations::analytics_response)>&& handler)
255
+ -> pending_call;
256
+
257
+ // FTS search over the couchbase2 server-streaming transport. Hits are buffered into the response.
258
+ auto execute(const operations::search_request& request,
259
+ utils::movable_function<void(operations::search_response)>&& handler)
260
+ -> pending_call;
261
+
262
+ // Map/reduce views over the couchbase2 server-streaming transport.
263
+ auto execute(const operations::document_view_request& request,
264
+ utils::movable_function<void(operations::document_view_response)>&& handler)
265
+ -> pending_call;
266
+
267
+ // Bucket management (unary admin RPCs over admin.bucket.v1).
268
+ auto execute(
269
+ const operations::management::bucket_get_all_request& request,
270
+ utils::movable_function<void(operations::management::bucket_get_all_response)>&& handler)
271
+ -> pending_call;
272
+ auto execute(const operations::management::bucket_get_request& request,
273
+ utils::movable_function<void(operations::management::bucket_get_response)>&& handler)
274
+ -> pending_call;
275
+ auto execute(
276
+ const operations::management::bucket_create_request& request,
277
+ utils::movable_function<void(operations::management::bucket_create_response)>&& handler)
278
+ -> pending_call;
279
+ auto execute(
280
+ const operations::management::bucket_update_request& request,
281
+ utils::movable_function<void(operations::management::bucket_update_response)>&& handler)
282
+ -> pending_call;
283
+ auto execute(
284
+ const operations::management::bucket_drop_request& request,
285
+ utils::movable_function<void(operations::management::bucket_drop_response)>&& handler)
286
+ -> pending_call;
287
+ auto execute(
288
+ const operations::management::bucket_flush_request& request,
289
+ utils::movable_function<void(operations::management::bucket_flush_response)>&& handler)
290
+ -> pending_call;
291
+
292
+ // Scope/collection management (unary admin RPCs over admin.collection.v1).
293
+ auto execute(
294
+ const operations::management::scope_get_all_request& request,
295
+ utils::movable_function<void(operations::management::scope_get_all_response)>&& handler)
296
+ -> pending_call;
297
+ auto execute(
298
+ const operations::management::scope_create_request& request,
299
+ utils::movable_function<void(operations::management::scope_create_response)>&& handler)
300
+ -> pending_call;
301
+ auto execute(const operations::management::scope_drop_request& request,
302
+ utils::movable_function<void(operations::management::scope_drop_response)>&& handler)
303
+ -> pending_call;
304
+ auto execute(
305
+ const operations::management::collection_create_request& request,
306
+ utils::movable_function<void(operations::management::collection_create_response)>&& handler)
307
+ -> pending_call;
308
+ auto execute(
309
+ const operations::management::collection_update_request& request,
310
+ utils::movable_function<void(operations::management::collection_update_response)>&& handler)
311
+ -> pending_call;
312
+ auto execute(
313
+ const operations::management::collection_drop_request& request,
314
+ utils::movable_function<void(operations::management::collection_drop_response)>&& handler)
315
+ -> pending_call;
316
+
317
+ // Query index management (unary admin RPCs over admin.query.v1).
318
+ auto execute(
319
+ const operations::management::query_index_get_all_request& request,
320
+ utils::movable_function<void(operations::management::query_index_get_all_response)>&& handler)
321
+ -> pending_call;
322
+ auto execute(
323
+ const operations::management::query_index_create_request& request,
324
+ utils::movable_function<void(operations::management::query_index_create_response)>&& handler)
325
+ -> pending_call;
326
+ auto execute(
327
+ const operations::management::query_index_drop_request& request,
328
+ utils::movable_function<void(operations::management::query_index_drop_response)>&& handler)
329
+ -> pending_call;
330
+ auto execute(
331
+ const operations::management::query_index_build_deferred_request& request,
332
+ utils::movable_function<void(operations::management::query_index_build_deferred_response)>&&
333
+ handler) -> pending_call;
334
+
335
+ // Search index management (unary admin RPCs over admin.search.v1).
336
+ auto execute(
337
+ const operations::management::search_index_upsert_request& request,
338
+ utils::movable_function<void(operations::management::search_index_upsert_response)>&& handler)
339
+ -> pending_call;
340
+ auto execute(
341
+ const operations::management::search_index_get_request& request,
342
+ utils::movable_function<void(operations::management::search_index_get_response)>&& handler)
343
+ -> pending_call;
344
+ auto execute(
345
+ const operations::management::search_index_get_all_request& request,
346
+ utils::movable_function<void(operations::management::search_index_get_all_response)>&& handler)
347
+ -> pending_call;
348
+ auto execute(
349
+ const operations::management::search_index_drop_request& request,
350
+ utils::movable_function<void(operations::management::search_index_drop_response)>&& handler)
351
+ -> pending_call;
352
+ auto execute(
353
+ const operations::management::search_index_analyze_document_request& request,
354
+ utils::movable_function<void(operations::management::search_index_analyze_document_response)>&&
355
+ handler) -> pending_call;
356
+ auto execute(const operations::management::search_index_get_documents_count_request& request,
357
+ utils::movable_function<
358
+ void(operations::management::search_index_get_documents_count_response)>&& handler)
359
+ -> pending_call;
360
+ auto execute(
361
+ const operations::management::search_index_control_ingest_request& request,
362
+ utils::movable_function<void(operations::management::search_index_control_ingest_response)>&&
363
+ handler) -> pending_call;
364
+ auto execute(
365
+ const operations::management::search_index_control_query_request& request,
366
+ utils::movable_function<void(operations::management::search_index_control_query_response)>&&
367
+ handler) -> pending_call;
368
+ auto execute(const operations::management::search_index_control_plan_freeze_request& request,
369
+ utils::movable_function<
370
+ void(operations::management::search_index_control_plan_freeze_response)>&& handler)
371
+ -> pending_call;
372
+
373
+ private:
374
+ // The generated gRPC stubs are held behind an opaque pointer so the generated protobuf and gRPC
375
+ // surface stays out of every translation unit that includes this header -- none of it appears in
376
+ // the interface, and the stub count grows with every service the transport learns to speak.
377
+ struct stubs;
378
+
379
+ asio::io_context& io_;
380
+ std::unique_ptr<stubs> stubs_;
381
+ std::string authorization_;
382
+ component_timeouts timeouts_;
383
+ kv::compression_settings compression_;
384
+ // Declared last, so it is destroyed first: ~dispatcher() cancels and drains the calls issued
385
+ // through the stubs above, which must therefore still be alive while it runs.
386
+ dispatcher dispatcher_;
387
+ };
388
+
389
+ } // namespace couchbase::core::protostellar
390
+
391
+ #pragma pop_macro("COUCHBASE_CXX_CLIENT_IGNORE_CORE_DEPRECATIONS")
@@ -1,6 +1,6 @@
1
1
  /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
2
  /*
3
- * Copyright 2020-Present Couchbase, Inc.
3
+ * Copyright 2026. Couchbase, Inc.
4
4
  *
5
5
  * Licensed under the Apache License, Version 2.0 (the "License");
6
6
  * you may not use this file except in compliance with the License.
@@ -17,16 +17,17 @@
17
17
 
18
18
  #pragma once
19
19
 
20
- #include "core/impl/bootstrap_error.hxx"
20
+ #include <cstddef>
21
21
 
22
- namespace couchbase::core::columnar
22
+ namespace couchbase::core::protostellar::kv
23
23
  {
24
24
 
25
- class bootstrap_notification_subscriber
26
- {
27
- public:
28
- virtual ~bootstrap_notification_subscriber() = default;
29
- virtual void notify_bootstrap_error(const core::impl::bootstrap_error& error) = 0;
30
- virtual void notify_bootstrap_success(const std::string& session_id) = 0;
25
+ // The user's compression knobs. Defaults mirror the classic SDK (enabled; snappy applied only when
26
+ // the value is at least min_size and shrinks below min_ratio).
27
+ struct compression_settings {
28
+ bool enabled{ true };
29
+ std::size_t min_size{ 32 };
30
+ double min_ratio{ 0.83 };
31
31
  };
32
- } // namespace couchbase::core::columnar
32
+
33
+ } // namespace couchbase::core::protostellar::kv
@@ -0,0 +1,233 @@
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 "core/protostellar/credentials.hxx"
19
+
20
+ #include "core/capella_ca.hxx"
21
+ #include "core/cluster_credentials.hxx"
22
+ #include "core/cluster_options.hxx"
23
+ #include "core/logger/logger.hxx"
24
+ #include "core/mozilla_ca_bundle.hxx"
25
+ #include "core/platform/base64.h"
26
+ #include "core/protostellar/dispatcher.hxx"
27
+ #include "core/tls_verify_mode.hxx"
28
+
29
+ #include <grpcpp/create_channel.h>
30
+ #include <grpcpp/security/tls_certificate_provider.h>
31
+ #include <grpcpp/security/tls_credentials_options.h>
32
+
33
+ #include <fstream>
34
+ #include <optional>
35
+ #include <sstream>
36
+ #include <stdexcept>
37
+ #include <utility>
38
+ #include <vector>
39
+
40
+ namespace couchbase::core::protostellar
41
+ {
42
+ namespace
43
+ {
44
+ // Read a PEM file that the caller has explicitly configured. Fails closed: a configured but
45
+ // unreadable/empty trust or certificate file is an error, never a silent fall-back to the system
46
+ // trust store (which would broaden the accepted-issuer set beyond the operator's intent).
47
+ auto
48
+ read_required_file(const std::string& path) -> std::string
49
+ {
50
+ const std::ifstream stream{ path, std::ios::binary };
51
+ if (!stream) {
52
+ throw std::runtime_error("couchbase2: cannot read configured TLS file: " + path);
53
+ }
54
+ std::ostringstream buffer;
55
+ buffer << stream.rdbuf();
56
+ auto contents = buffer.str();
57
+ if (contents.empty()) {
58
+ throw std::runtime_error("couchbase2: configured TLS file is empty: " + path);
59
+ }
60
+ return contents;
61
+ }
62
+
63
+ // The default trust material, concatenated into a single PEM as gRPC's pem_root_certs expects: the
64
+ // Couchbase Capella root, plus the bundled Mozilla roots unless the operator disabled them. RFC 77
65
+ // (Bootstrapping -> Security) requires that "the set of Root CAs that SDKs trust by default for
66
+ // couchbase2 must be identical to the one used for Classic", and the Capella root is what this path
67
+ // was missing -- MCBP's configure_tls_context() adds it unconditionally whenever no explicit trust
68
+ // material is configured.
69
+ //
70
+ // Why the platform trust store is not also folded in, unlike MCBP's set_default_verify_paths():
71
+ // gRPC accepts trust material only as one PEM blob and treats a non-empty pem_root_certs as the
72
+ // entire store -- "If this parameter is empty, the default roots will be used" -- so there is
73
+ // nothing to layer onto and no incremental API to layer with. Snapshotting the platform store into
74
+ // that blob would not reproduce MCBP anyway: under OpenSSL/BoringSSL "system roots" is not a
75
+ // defined set the way the JVM's trust store or .NET's X509Chain is, but whatever the host happens
76
+ // to ship, relocatable at run time through SSL_CERT_FILE/SSL_CERT_DIR, and BoringSSL compiles in
77
+ // different default paths again. The two sets this SDK ships and can therefore guarantee are the
78
+ // Capella root and the Mozilla bundle, so those are what the default trusts. A private or corporate
79
+ // CA is configured explicitly, which replaces this set outright -- exactly as it does for MCBP.
80
+ //
81
+ // For reference, the other SDKs land in the same place by different routes: Java trusts its Capella
82
+ // root plus the JVM trust store (SecurityConfig::defaultCaCertificates), .NET accepts whatever the
83
+ // platform validated and adds its Capella root to the chain's ExtraStore, and Go trusts only
84
+ // x509.SystemCertPool() and ships no Capella root at all.
85
+ auto
86
+ default_root_certs(bool include_mozilla_bundle) -> std::string
87
+ {
88
+ std::string pem{ default_ca::capellaCaCert };
89
+ if (!pem.empty() && pem.back() != '\n') {
90
+ pem.push_back('\n');
91
+ }
92
+ if (include_mozilla_bundle) {
93
+ for (const auto& cert : default_ca::mozilla_ca_certs()) {
94
+ pem.append(cert.body);
95
+ if (pem.back() != '\n') {
96
+ pem.push_back('\n');
97
+ }
98
+ }
99
+ }
100
+ return pem;
101
+ }
102
+
103
+ // The configured client certificate/key pair for mTLS, as {private_key, certificate_chain}.
104
+ // Returns nullopt when neither is set; throws when only one is set, since a half-configured
105
+ // identity produces an opaque connect-time failure rather than a clear misconfiguration error.
106
+ auto
107
+ read_client_identity(const cluster_credentials& credentials)
108
+ -> std::optional<std::pair<std::string, std::string>>
109
+ {
110
+ const bool have_cert = !credentials.certificate_path.empty();
111
+ const bool have_key = !credentials.key_path.empty();
112
+ if (!have_cert && !have_key) {
113
+ return std::nullopt;
114
+ }
115
+ if (have_cert != have_key) {
116
+ throw std::invalid_argument("couchbase2: client certificate authentication requires both a "
117
+ "certificate and a private key; only one was configured");
118
+ }
119
+ return std::pair{ read_required_file(credentials.key_path),
120
+ read_required_file(credentials.certificate_path) };
121
+ }
122
+ } // namespace
123
+
124
+ auto
125
+ build_ssl_options(const cluster_options& options, const cluster_credentials& credentials)
126
+ -> grpc::SslCredentialsOptions
127
+ {
128
+ grpc::SslCredentialsOptions ssl;
129
+ if (!options.trust_certificate_value.empty()) {
130
+ ssl.pem_root_certs = options.trust_certificate_value;
131
+ } else if (!options.trust_certificate.empty()) {
132
+ ssl.pem_root_certs = read_required_file(options.trust_certificate);
133
+ } else {
134
+ // Never left empty: gRPC's own fallback is the GRPC_DEFAULT_SSL_ROOTS_FILE_PATH environment
135
+ // variable, else a process-wide override hook, else roots bundled in the gRPC installation --
136
+ // none of which is the platform trust store, and all of which are outside this SDK's control.
137
+ // Disabling the Mozilla bundle drops that layer only; the Capella root stays, matching MCBP,
138
+ // where disable_mozilla_ca_certificates likewise gates just the bundle loop.
139
+ ssl.pem_root_certs = default_root_certs(!options.disable_mozilla_ca_certificates);
140
+ }
141
+
142
+ if (auto identity = read_client_identity(credentials)) {
143
+ ssl.pem_private_key = identity->first;
144
+ ssl.pem_cert_chain = identity->second;
145
+ }
146
+ return ssl;
147
+ }
148
+
149
+ auto
150
+ basic_auth_value(const std::string& username, const std::string& password) -> std::string
151
+ {
152
+ return "Basic " + base64::encode(username + ":" + password);
153
+ }
154
+
155
+ auto
156
+ bearer_auth_value(const std::string& jwt_token) -> std::string
157
+ {
158
+ return "Bearer " + jwt_token;
159
+ }
160
+
161
+ auto
162
+ authorization_header(const cluster_credentials& credentials) -> std::string
163
+ {
164
+ if (credentials.uses_jwt()) {
165
+ return bearer_auth_value(credentials.jwt_token);
166
+ }
167
+ if (credentials.uses_password()) {
168
+ return basic_auth_value(credentials.username, credentials.password);
169
+ }
170
+ return {};
171
+ }
172
+
173
+ auto
174
+ tls_peer_verification_disabled(const cluster_options& options) -> bool
175
+ {
176
+ return options.enable_tls && options.tls_verify == tls_verify_mode::none;
177
+ }
178
+
179
+ auto
180
+ make_channel_credentials(const cluster_options& options, const cluster_credentials& credentials)
181
+ -> std::shared_ptr<grpc::ChannelCredentials>
182
+ {
183
+ if (!options.enable_tls) {
184
+ // Fail closed: never let username/password or a JWT ride a plaintext channel (base64 is not
185
+ // encryption). couchbase2:// implies TLS; a programmatic config that disables it while
186
+ // carrying credentials is a misconfiguration, not a downgrade we perform silently.
187
+ if (credentials.uses_password() || credentials.uses_jwt() ||
188
+ !credentials.certificate_path.empty() || !credentials.key_path.empty()) {
189
+ throw std::invalid_argument(
190
+ "couchbase2: refusing to send credentials over a plaintext channel; enable TLS");
191
+ }
192
+ return grpc::InsecureChannelCredentials();
193
+ }
194
+ if (tls_peer_verification_disabled(options)) {
195
+ // Encrypt the channel but skip server-certificate and hostname verification. Used against
196
+ // dev/test gateways whose certificate cannot be chained to a trusted CA (e.g. the CNG cert
197
+ // served by the Couchbase operator on a k8s NodePort).
198
+ //
199
+ // Warn here rather than only at the call site: this is the one point every couchbase2 channel
200
+ // passes through, including callers that build a component directly without going through
201
+ // cluster::open. A deployment that enabled this by accident has to be able to see it.
202
+ CB_LOG_WARNING("couchbase2: TLS certificate verification is DISABLED (tls_verify=none); the "
203
+ "connection is encrypted but unauthenticated and can be intercepted. Do not use "
204
+ "this outside development.");
205
+ grpc::experimental::TlsChannelCredentialsOptions tls;
206
+ tls.set_verify_server_certs(false);
207
+ tls.set_check_call_host(false);
208
+ tls.set_certificate_verifier(std::make_shared<grpc::experimental::NoOpCertificateVerifier>());
209
+ // Still present the configured client identity (mTLS) so certificate auth works even when the
210
+ // gateway's server certificate cannot be verified. Skipping server verification does not imply
211
+ // skipping our own authentication.
212
+ if (auto identity = read_client_identity(credentials)) {
213
+ tls.set_certificate_provider(
214
+ std::make_shared<grpc::experimental::StaticDataCertificateProvider>(
215
+ std::vector<grpc::experimental::IdentityKeyCertPair>{
216
+ { identity->first, identity->second } }));
217
+ tls.watch_identity_key_cert_pairs();
218
+ }
219
+ return grpc::experimental::TlsCredentials(tls);
220
+ }
221
+ return grpc::SslCredentials(build_ssl_options(options, credentials));
222
+ }
223
+
224
+ auto
225
+ make_channel(const std::string& endpoint,
226
+ const cluster_options& options,
227
+ const cluster_credentials& credentials) -> std::shared_ptr<grpc::Channel>
228
+ {
229
+ return grpc::CreateCustomChannel(
230
+ endpoint, make_channel_credentials(options, credentials), default_channel_arguments());
231
+ }
232
+
233
+ } // namespace couchbase::core::protostellar