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
@@ -22,8 +22,30 @@
22
22
 
23
23
  namespace couchbase::core::utils
24
24
  {
25
+ namespace detail
26
+ {
27
+ /**
28
+ * Byte order of a host.
29
+ *
30
+ * Kept as a value that the conversions below take as a parameter, rather than as a preprocessor
31
+ * branch around them, so that both orders stay compilable and testable whatever host this is
32
+ * built on. Without that, the big-endian path could only ever be verified by running on a
33
+ * big-endian host, and nothing in CI does.
34
+ */
35
+ enum class host_order {
36
+ little,
37
+ big,
38
+ };
39
+
40
+ #if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \
41
+ __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
42
+ inline constexpr host_order native_order = host_order::big;
43
+ #else
44
+ inline constexpr host_order native_order = host_order::little;
45
+ #endif
46
+
25
47
  static constexpr auto
26
- byte_swap(std::uint16_t value) -> std::uint16_t
48
+ swap_bytes(std::uint16_t value) -> std::uint16_t
27
49
  {
28
50
  auto hi = static_cast<std::uint16_t>(value << 8U);
29
51
  auto lo = static_cast<std::uint16_t>(value >> 8U);
@@ -31,7 +53,7 @@ byte_swap(std::uint16_t value) -> std::uint16_t
31
53
  }
32
54
 
33
55
  static constexpr auto
34
- byte_swap(std::uint32_t value) -> std::uint32_t
56
+ swap_bytes(std::uint32_t value) -> std::uint32_t
35
57
  {
36
58
  std::uint32_t byte0 = value & 0x000000ffU;
37
59
  std::uint32_t byte1 = value & 0x0000ff00U;
@@ -41,21 +63,156 @@ byte_swap(std::uint32_t value) -> std::uint32_t
41
63
  }
42
64
 
43
65
  static constexpr auto
44
- byte_swap(std::uint64_t value) -> std::uint64_t
66
+ swap_bytes(std::uint64_t value) -> std::uint64_t
45
67
  {
46
- std::uint64_t hi = byte_swap(static_cast<std::uint32_t>(value));
47
- std::uint32_t lo = byte_swap(static_cast<std::uint32_t>(value >> 32));
68
+ std::uint64_t hi = swap_bytes(static_cast<std::uint32_t>(value));
69
+ std::uint32_t lo = swap_bytes(static_cast<std::uint32_t>(value >> 32));
48
70
  return (hi << 32) | lo;
49
71
  }
72
+ /**
73
+ * Convert a value between host order and network (big-endian) order, for a host whose byte order
74
+ * is Order.
75
+ *
76
+ * The two directions are the same operation, so one function serves both. On a big-endian host
77
+ * the value is already in network order and this is the identity; the callers pair it with a
78
+ * memcpy of the native integer, which on such a host already lays the bytes down big-endian.
79
+ */
80
+ template<host_order Order>
81
+ static constexpr auto
82
+ convert(std::uint16_t value) -> std::uint16_t
83
+ {
84
+ if constexpr (Order == host_order::big) {
85
+ return value;
86
+ } else {
87
+ return swap_bytes(value);
88
+ }
89
+ }
90
+
91
+ template<host_order Order>
92
+ static constexpr auto
93
+ convert(std::uint32_t value) -> std::uint32_t
94
+ {
95
+ if constexpr (Order == host_order::big) {
96
+ return value;
97
+ } else {
98
+ return swap_bytes(value);
99
+ }
100
+ }
101
+
102
+ template<host_order Order>
103
+ static constexpr auto
104
+ convert(std::uint64_t value) -> std::uint64_t
105
+ {
106
+ if constexpr (Order == host_order::big) {
107
+ return value;
108
+ } else {
109
+ return swap_bytes(value);
110
+ }
111
+ }
112
+ } // namespace detail
113
+
114
+ /**
115
+ * Reverse the bytes of a value on every host, whatever this host's byte order is.
116
+ *
117
+ * This is deliberately not a host/network conversion, and the two are not interchangeable. Use
118
+ * it only where the byte order of the input is fixed by something other than this host. The one
119
+ * such case in this codebase is the ${Mutation.CAS} macro, which kvengine writes as
120
+ * 'macroToString(htonll(info.cas))', so the eight bytes inside that string carry the same order
121
+ * no matter which host later reads them.
122
+ */
123
+ static constexpr auto
124
+ reverse_bytes(std::uint16_t value) -> std::uint16_t
125
+ {
126
+ return detail::swap_bytes(value);
127
+ }
128
+
129
+ static constexpr auto
130
+ reverse_bytes(std::uint32_t value) -> std::uint32_t
131
+ {
132
+ return detail::swap_bytes(value);
133
+ }
134
+
135
+ static constexpr auto
136
+ reverse_bytes(std::uint64_t value) -> std::uint64_t
137
+ {
138
+ return detail::swap_bytes(value);
139
+ }
140
+
141
+ // when 'unsigned long long' is not the same as 'std::uint64_t'
142
+ template<typename Dummy = void>
143
+ static constexpr auto
144
+ reverse_bytes(
145
+ unsigned long long value,
146
+ std::enable_if_t<!std::is_same_v<unsigned long long, std::uint64_t>, Dummy>* /* dummy */
147
+ = nullptr) -> std::uint64_t
148
+ {
149
+ return reverse_bytes(static_cast<std::uint64_t>(value));
150
+ }
151
+
152
+ /**
153
+ * Convert a value from this host's byte order to network (big-endian) order, ready to be copied
154
+ * into a wire buffer.
155
+ */
156
+ static constexpr auto
157
+ host_to_network(std::uint16_t value) -> std::uint16_t
158
+ {
159
+ return detail::convert<detail::native_order>(value);
160
+ }
161
+
162
+ static constexpr auto
163
+ host_to_network(std::uint32_t value) -> std::uint32_t
164
+ {
165
+ return detail::convert<detail::native_order>(value);
166
+ }
167
+
168
+ static constexpr auto
169
+ host_to_network(std::uint64_t value) -> std::uint64_t
170
+ {
171
+ return detail::convert<detail::native_order>(value);
172
+ }
173
+
174
+ // when 'unsigned long long' is not the same as 'std::uint64_t'
175
+ template<typename Dummy = void>
176
+ static constexpr auto
177
+ host_to_network(
178
+ unsigned long long value,
179
+ std::enable_if_t<!std::is_same_v<unsigned long long, std::uint64_t>, Dummy>* /* dummy */
180
+ = nullptr) -> std::uint64_t
181
+ {
182
+ return host_to_network(static_cast<std::uint64_t>(value));
183
+ }
184
+
185
+ /**
186
+ * Convert a value read out of a wire buffer from network (big-endian) order to this host's byte
187
+ * order. The inverse of host_to_network, and the same operation.
188
+ */
189
+ static constexpr auto
190
+ network_to_host(std::uint16_t value) -> std::uint16_t
191
+ {
192
+ return detail::convert<detail::native_order>(value);
193
+ }
194
+
195
+ static constexpr auto
196
+ network_to_host(std::uint32_t value) -> std::uint32_t
197
+ {
198
+ return detail::convert<detail::native_order>(value);
199
+ }
200
+
201
+ static constexpr auto
202
+ network_to_host(std::uint64_t value) -> std::uint64_t
203
+ {
204
+ return detail::convert<detail::native_order>(value);
205
+ }
50
206
 
51
207
  // when 'unsigned long long' is not the same as 'std::uint64_t'
52
208
  template<typename Dummy = void>
53
209
  static constexpr auto
54
- byte_swap(unsigned long long value,
55
- std::enable_if_t<!std::is_same_v<unsigned long long, std::uint64_t>, Dummy>* /* dummy */ =
56
- nullptr) -> std::uint64_t
210
+ network_to_host(
211
+ unsigned long long value,
212
+ std::enable_if_t<!std::is_same_v<unsigned long long, std::uint64_t>, Dummy>* /* dummy */
213
+ = nullptr) -> std::uint64_t
57
214
  {
58
- return byte_swap(static_cast<std::uint64_t>(value));
215
+ return network_to_host(static_cast<std::uint64_t>(value));
59
216
  }
60
217
 
61
218
  } // namespace couchbase::core::utils
@@ -15,8 +15,6 @@
15
15
  * limitations under the License.
16
16
  */
17
17
 
18
- #include <couchbase/build_config.hxx>
19
-
20
18
  #include "connection_string.hxx"
21
19
  #include "core/logger/logger.hxx"
22
20
  #include "core/meta/version.hxx"
@@ -91,6 +89,12 @@ struct action<scheme> {
91
89
  cs.default_port = 18091;
92
90
  cs.default_mode = connection_string::bootstrap_mode::http;
93
91
  cs.tls = true;
92
+ } else if (cs.scheme == "couchbase2") {
93
+ // Protostellar: the gateway does routing, so there is no MCBP-style config bootstrap.
94
+ cs.default_port = 18098;
95
+ cs.default_mode = connection_string::bootstrap_mode::unspecified;
96
+ cs.tls = true;
97
+ cs.protocol = connection_string::protocol_type::protostellar;
94
98
  } else {
95
99
  cs.default_mode = connection_string::bootstrap_mode::unspecified;
96
100
  cs.default_port = 0;
@@ -256,37 +260,6 @@ parse_option(io::ip_protocol& receiver,
256
260
  }
257
261
  }
258
262
 
259
- #ifdef COUCHBASE_CXX_CLIENT_COLUMNAR
260
- void
261
- parse_option(std::chrono::milliseconds& receiver,
262
- const std::string& name,
263
- const std::string& value,
264
- std::vector<std::string>& warnings)
265
- {
266
- try {
267
- receiver = std::chrono::duration_cast<std::chrono::milliseconds>(
268
- parse_duration(string_codec::url_decode(value)));
269
- } catch (const duration_parse_error& dpe) {
270
- warnings.push_back(
271
- fmt::format(R"(unable to parse "{}" parameter in connection string (value: "{}"): {})",
272
- name,
273
- value,
274
- dpe.what()));
275
- } catch (const std::invalid_argument& ex1) {
276
- warnings.push_back(fmt::format(
277
- R"(unable to parse "{}" parameter in connection string (value "{}" is not a number): {})",
278
- name,
279
- value,
280
- ex1.what()));
281
- } catch (const std::out_of_range& ex2) {
282
- warnings.push_back(fmt::format(
283
- R"(unable to parse "{}" parameter in connection string (value "{}" is out of range): {})",
284
- name,
285
- value,
286
- ex2.what()));
287
- }
288
- }
289
- #else
290
263
  void
291
264
  parse_option(tls_verify_mode& receiver,
292
265
  const std::string& name,
@@ -354,7 +327,6 @@ parse_option(std::chrono::milliseconds& receiver,
354
327
  }
355
328
  }
356
329
  }
357
- #endif
358
330
 
359
331
  void
360
332
  extract_options(connection_string& connstr)
@@ -364,55 +336,20 @@ extract_options(connection_string& connstr)
364
336
  connstr.bootstrap_nodes[0].type != connection_string::address_type::dns) {
365
337
  connstr.options.enable_dns_srv = false;
366
338
  }
339
+ // couchbase2:// never resolves DNS *SRV*: there are no _couchbaseXXX._tcp records for a gateway,
340
+ // which is addressed directly and does its own routing. This does not turn off name resolution --
341
+ // ordinary A/AAAA lookup still happens inside gRPC, which is how a CNG cluster behind a network
342
+ // load balancer is reached (one hostname, one address per instance).
343
+ //
344
+ // cluster::open() already returns into open_protostellar() before reaching the DNS SRV branch, so
345
+ // this changes no behaviour today; it keeps the parsed options honest -- to_json() reports
346
+ // enable_dns_srv in diagnostics -- and stops the option becoming live if that ordering changes.
347
+ // Placed with the rule above, before the parameter loop, so an explicit enable_dns_srv= still
348
+ // wins, same as the single-node rule it sits next to.
349
+ if (connstr.protocol == connection_string::protocol_type::protostellar) {
350
+ connstr.options.enable_dns_srv = false;
351
+ }
367
352
  for (const auto& [name, value] : connstr.params) {
368
- #ifdef COUCHBASE_CXX_CLIENT_COLUMNAR
369
- if (name == "security.trust_only_pem_file") {
370
- /**
371
- * Set the trust cert path
372
- */
373
- parse_option(connstr.options.trust_certificate, name, value, connstr.warnings);
374
- } else if (name == "security.disable_server_certificate_verification") {
375
- /**
376
- * Disable TLS server cert verification if set to true.
377
- */
378
- if (value == "true" || value == "yes" || value == "on" || value == "1") {
379
- connstr.options.tls_verify = tls_verify_mode::none;
380
- } else if (value == "false" || value == "no" || value == "off" || value == "0") {
381
- connstr.options.tls_verify = tls_verify_mode::peer;
382
- } else {
383
- connstr.warnings.push_back(fmt::format(
384
- R"(unable to parse "{}" parameter in connection string (value "{}" cannot be interpreted as a boolean))",
385
- name,
386
- value));
387
- }
388
-
389
- } else if (name == "timeout.connect_timeout") {
390
- /**
391
- * The period of time allocated to complete bootstrap
392
- */
393
- parse_option(connstr.options.bootstrap_timeout, name, value, connstr.warnings);
394
- } else if (name == "timeout.dispatch_timeout") {
395
- /**
396
- * Number of seconds to wait before timing out a Query or N1QL request by the client.
397
- */
398
- parse_option(connstr.options.dispatch_timeout, name, value, connstr.warnings);
399
- } else if (name == "timeout.query_timeout") {
400
- /**
401
- * Number of seconds to wait before timing out a Query or N1QL request by the client.
402
- */
403
- parse_option(connstr.options.query_timeout, name, value, connstr.warnings);
404
- } else if (name == "timeout.resolve_timeout") {
405
- /**
406
- * The period of time to resolve DNS name of the node to IP address
407
- */
408
- parse_option(connstr.options.resolve_timeout, name, value, connstr.warnings);
409
- } else if (name == "timeout.socket_connect_timeout") {
410
- /**
411
- * Number of seconds the client should wait while attempting to connect to a node’s KV service
412
- * via a socket. Initial connection, reconnecting, node added, etc.
413
- */
414
- parse_option(connstr.options.connect_timeout, name, value, connstr.warnings);
415
- #else
416
353
  if (name == "kv_connect_timeout") {
417
354
  /**
418
355
  * Number of seconds the client should wait while attempting to connect to a node’s KV service
@@ -484,7 +421,6 @@ extract_options(connection_string& connstr)
484
421
  if (force_ipv4) {
485
422
  connstr.options.use_ip_protocol = io::ip_protocol::force_ipv4;
486
423
  }
487
- #endif
488
424
  } else if (name == "ip_protocol") {
489
425
  /**
490
426
  * Controls preference of IP protocol for name resolution
@@ -524,7 +460,6 @@ extract_options(connection_string& connstr)
524
460
  parse_option(connstr.options.enable_clustermap_notification, name, value, connstr.warnings);
525
461
  } else if (name == "disable_mozilla_ca_certificates") {
526
462
  parse_option(connstr.options.disable_mozilla_ca_certificates, name, value, connstr.warnings);
527
- #ifndef COUCHBASE_CXX_CLIENT_COLUMNAR
528
463
  } else if (name == "max_http_connections") {
529
464
  /**
530
465
  * The maximum number of HTTP connections allowed on a per-host and per-port basis. 0
@@ -581,7 +516,6 @@ extract_options(connection_string& connstr)
581
516
  parse_option(connstr.options.tls_disable_v1_2, name, value, connstr.warnings);
582
517
  } else if (name == "server_group") {
583
518
  parse_option(connstr.options.server_group, name, value, connstr.warnings);
584
- #endif
585
519
  } else if (name == "enable_app_telemetry") {
586
520
  parse_option(connstr.options.enable_app_telemetry, name, value, connstr.warnings);
587
521
  } else if (name == "app_telemetry_endpoint") {
@@ -592,12 +526,42 @@ extract_options(connection_string& connstr)
592
526
  parse_option(connstr.options.allow_enterprise_analytics, name, value, connstr.warnings);
593
527
  } else if (name == "enable_lazy_connections") {
594
528
  parse_option(connstr.options.enable_lazy_connections, name, value, connstr.warnings);
529
+ } else if (name == "log_redaction") {
530
+ parse_option(connstr.options.log_redaction, name, value, connstr.warnings);
595
531
  } else {
596
532
  connstr.warnings.push_back(
597
533
  fmt::format(R"(unknown parameter "{}" in connection string (value "{}"))", name, value));
598
534
  }
599
535
  }
600
536
  }
537
+ // couchbase2:// addresses one CNG endpoint. The gateway performs routing, so there is no node list
538
+ // to rotate through and no MCBP bootstrap mode to select per node. Reject strings that ask for
539
+ // either instead of silently honouring only the first host. couchbase-jvm-clients does the same,
540
+ // though it validates at transport construction (CoreProtostellar) rather than while parsing; here
541
+ // connection_string already carries an error field, so failing at the parse boundary keeps the
542
+ // diagnosis next to the input that caused it.
543
+ void
544
+ validate_protostellar(connection_string& connstr)
545
+ {
546
+ if (connstr.error.has_value() ||
547
+ connstr.protocol != connection_string::protocol_type::protostellar) {
548
+ return;
549
+ }
550
+ if (connstr.bootstrap_nodes.size() != 1) {
551
+ connstr.error =
552
+ fmt::format(R"(connection string with scheme "couchbase2" must have exactly one host, )"
553
+ R"(but got {}: "{}")",
554
+ connstr.bootstrap_nodes.size(),
555
+ connstr.input);
556
+ return;
557
+ }
558
+ if (connstr.bootstrap_nodes[0].mode != connection_string::bootstrap_mode::unspecified) {
559
+ connstr.error =
560
+ fmt::format(R"(connection string with scheme "couchbase2" does not accept a bootstrap mode )"
561
+ R"(suffix, because the gateway does not use MCBP or HTTP config bootstrap: "{}")",
562
+ connstr.input);
563
+ }
564
+ }
601
565
  } // namespace
602
566
 
603
567
  auto
@@ -630,6 +594,7 @@ parse_connection_string(const std::string& input, cluster_options options) -> co
630
594
  }
631
595
  }
632
596
  extract_options(res);
597
+ validate_protostellar(res);
633
598
  return res;
634
599
  }
635
600
  } // namespace couchbase::core::utils
@@ -34,6 +34,13 @@ struct connection_string {
34
34
  http,
35
35
  };
36
36
 
37
+ // Which client protocol the scheme selects. The classic MCBP stack (couchbase/couchbases/
38
+ // http/https) versus the Protostellar gRPC transport (couchbase2).
39
+ enum class protocol_type {
40
+ mcbp,
41
+ protostellar,
42
+ };
43
+
37
44
  enum class address_type {
38
45
  ipv4,
39
46
  ipv6,
@@ -68,9 +75,17 @@ struct connection_string {
68
75
  std::optional<std::string> default_bucket_name{};
69
76
  bootstrap_mode default_mode{ connection_string::bootstrap_mode::gcccp };
70
77
  std::uint16_t default_port{ 11210 };
78
+ protocol_type protocol{ protocol_type::mcbp };
71
79
 
72
80
  std::vector<std::string> warnings{};
73
81
  std::optional<std::string> error{};
82
+
83
+ // True for the couchbase2:// (Protostellar) transport. The upper layer branches on this to
84
+ // pick the gRPC client instead of the MCBP stack.
85
+ [[nodiscard]] auto uses_protostellar() const -> bool
86
+ {
87
+ return protocol == protocol_type::protostellar;
88
+ }
74
89
  };
75
90
 
76
91
  auto
@@ -1,6 +1,6 @@
1
1
  /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
2
  /*
3
- * Copyright 2024. Couchbase, Inc.
3
+ * Copyright 2026-Present 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,18 +17,18 @@
17
17
 
18
18
  #pragma once
19
19
 
20
+ #include <algorithm>
20
21
  #include <chrono>
21
- #include <functional>
22
22
 
23
- namespace couchbase::core::columnar
23
+ namespace couchbase::core::utils
24
24
  {
25
- using backoff_calculator = std::function<std::chrono::milliseconds(std::size_t retry_attempts)>;
26
-
27
- auto
28
- exponential_backoff_with_full_jitter(std::chrono::milliseconds min_backoff,
29
- std::chrono::milliseconds max_backoff,
30
- double backoff_factor) -> backoff_calculator;
31
-
32
- auto
33
- default_backoff_calculator(std::size_t retry_attempts) -> std::chrono::milliseconds;
34
- } // namespace couchbase::core::columnar
25
+ // The time from now until `deadline`, as a request timeout. At least a millisecond: a zero timeout
26
+ // means "use the default".
27
+ inline auto
28
+ remaining_until(std::chrono::steady_clock::time_point deadline) -> std::chrono::milliseconds
29
+ {
30
+ return std::max(std::chrono::duration_cast<std::chrono::milliseconds>(
31
+ deadline - std::chrono::steady_clock::now()),
32
+ std::chrono::milliseconds{ 1 });
33
+ }
34
+ } // namespace couchbase::core::utils
@@ -40,7 +40,7 @@ leading_int(std::string& s, std::int64_t& v) -> bool
40
40
  return false;
41
41
  }
42
42
 
43
- v = v * 10 + static_cast<std::int64_t>(c) - '0';
43
+ v = (v * 10) + static_cast<std::int64_t>(c) - '0';
44
44
 
45
45
  if (v < 0) {
46
46
  return false;
@@ -52,9 +52,10 @@ noop_on_meta_header_complete(std::error_code /* ec */, std::string&& /* meta_hea
52
52
  #define STATE_MARKER_ROWSET (reinterpret_cast<void*>(2))
53
53
 
54
54
  struct streaming_lexer_impl {
55
- streaming_lexer_impl(jsonsl_t lexer, jsonsl_jpr_t pointer)
55
+ streaming_lexer_impl(jsonsl_t lexer, jsonsl_jpr_t pointer, std::size_t max_buffer)
56
56
  : lexer_(lexer)
57
57
  , pointer_(pointer)
58
+ , max_buffer_(max_buffer)
58
59
  {
59
60
  }
60
61
 
@@ -90,8 +91,8 @@ struct streaming_lexer_impl {
90
91
  state->data = STATE_MARKER_ROOT;
91
92
  }
92
93
 
93
- [[nodiscard]] auto get_buffer_region(std::size_t pos,
94
- std::size_t desired = 0) const -> std::string_view
94
+ [[nodiscard]] auto get_buffer_region(std::size_t pos, std::size_t desired = 0) const
95
+ -> std::string_view
95
96
  {
96
97
  if (min_pos_ > pos) {
97
98
  /* swallowed */
@@ -149,6 +150,8 @@ struct streaming_lexer_impl {
149
150
  std::function<void(std::error_code, std::size_t, std::string&&)> on_complete_{ noop_on_complete };
150
151
  std::function<stream_control(std::string&&)> on_row_{ noop_on_row };
151
152
  bool root_has_been_validated_{ false };
153
+ std::size_t max_buffer_{ 0 };
154
+ bool aborted_{ false };
152
155
  };
153
156
  } // namespace detail
154
157
 
@@ -264,6 +267,10 @@ error_callback(jsonsl_t lexer,
264
267
  return 0;
265
268
  }
266
269
 
270
+ // NOLINTBEGIN(misc-const-correctness): these are jsonsl stack callbacks whose signatures must match
271
+ // jsonsl_stack_callback exactly (void(jsonsl_t, jsonsl_action_t, struct jsonsl_state_st*, const
272
+ // char*)); the state pointer cannot be const or the assignment to action_callback_* would be
273
+ // ill-formed.
267
274
  void
268
275
  meta_header_complete_callback(jsonsl_t lexer,
269
276
  jsonsl_action_t /* action */,
@@ -307,6 +314,9 @@ trailer_pop_callback(jsonsl_t lexer,
307
314
  impl->on_meta_header_complete_ = detail::noop_on_meta_header_complete;
308
315
 
309
316
  impl->on_complete_({}, impl->number_of_rows_, std::move(impl->meta_buffer_));
317
+ // Reset so trailing bytes after a well-formed document (which would drive error_callback) cannot
318
+ // fire a second terminal, mirroring the reset applied to on_meta_header_complete_ above.
319
+ impl->on_complete_ = detail::noop_on_complete;
310
320
  }
311
321
 
312
322
  void
@@ -399,9 +409,12 @@ initial_action_push_callback(jsonsl_t lexer,
399
409
  state->data = STATE_MARKER_ROWSET;
400
410
  }
401
411
  }
412
+ // NOLINTEND(misc-const-correctness)
402
413
  } // namespace
403
414
 
404
- json::streaming_lexer::streaming_lexer(const std::string& pointer_expression, std::uint32_t depth)
415
+ json::streaming_lexer::streaming_lexer(const std::string& pointer_expression,
416
+ std::uint32_t depth,
417
+ std::size_t max_buffer)
405
418
  {
406
419
  jsonsl_error_t error = JSONSL_ERROR_SUCCESS;
407
420
  jsonsl_jpr_t ptr = jsonsl_jpr_new(pointer_expression.c_str(), &error);
@@ -413,7 +426,7 @@ json::streaming_lexer::streaming_lexer(const std::string& pointer_expression, st
413
426
  jsonsl_strerror(error));
414
427
  }
415
428
 
416
- impl_ = std::make_shared<detail::streaming_lexer_impl>(jsonsl_new(512), ptr);
429
+ impl_ = std::make_shared<detail::streaming_lexer_impl>(jsonsl_new(512), ptr, max_buffer);
417
430
  impl_->lexer_->data = impl_.get();
418
431
  impl_->lexer_->action_callback_PUSH = initial_action_push_callback;
419
432
  impl_->lexer_->action_callback_POP = initial_action_pop_callback;
@@ -426,7 +439,37 @@ json::streaming_lexer::streaming_lexer(const std::string& pointer_expression, st
426
439
  void
427
440
  streaming_lexer::feed(std::string_view data)
428
441
  {
442
+ if (impl_->aborted_) {
443
+ return;
444
+ }
445
+
446
+ /* Enforce the single-row / trailer buffer ceiling BEFORE appending, so a huge chunk that has not
447
+ * yet been parsed cannot grow buffer_ (and OOM the process) before the ceiling is detected. The
448
+ * un-consumed portion is everything buffered since the last keep_position_ trim — buffer_.size()
449
+ * minus the bytes already consumed — plus the incoming chunk about to be appended.
450
+ *
451
+ * This bounds the trailing metadata too: after the last row, keep_position_
452
+ * stops advancing, so the accumulating trailer counts as un-consumed and trips
453
+ * this same ceiling. Rows and trailer are therefore each capped at max_buffer_.
454
+ */
455
+ if (impl_->max_buffer_ != 0) {
456
+ const auto consumed = impl_->keep_position_ - impl_->min_pos_;
457
+ const auto unconsumed = impl_->buffer_.size() > consumed ? impl_->buffer_.size() - consumed : 0;
458
+ if (unconsumed + data.size() > impl_->max_buffer_) {
459
+ impl_->aborted_ = true;
460
+ impl_->error_ = errc::streaming_json_lexer::generic;
461
+
462
+ impl_->on_meta_header_complete_(impl_->error_, {});
463
+ impl_->on_meta_header_complete_ = detail::noop_on_meta_header_complete;
464
+
465
+ impl_->on_complete_(impl_->error_, impl_->number_of_rows_, {});
466
+ impl_->on_complete_ = detail::noop_on_complete;
467
+ return;
468
+ }
469
+ }
470
+
429
471
  impl_->buffer_.append(data);
472
+
430
473
  jsonsl_feed(impl_->lexer_, data.data(), data.size());
431
474
 
432
475
  /* Do we need to cut off some bytes? */
@@ -23,6 +23,7 @@
23
23
 
24
24
  #include "movable_function.hxx"
25
25
 
26
+ #include <cstddef>
26
27
  #include <cstdint>
27
28
  #include <functional>
28
29
  #include <memory>
@@ -50,7 +51,9 @@ public:
50
51
  *
51
52
  * @throws std::invalid_argument if pointer cannot be created from the expression.
52
53
  */
53
- streaming_lexer(const std::string& pointer_expression, std::uint32_t depth);
54
+ streaming_lexer(const std::string& pointer_expression,
55
+ std::uint32_t depth,
56
+ std::size_t max_buffer = 0);
54
57
 
55
58
  void feed(std::string_view data);
56
59