couchbase 3.8.1 → 3.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (475) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/ext/CMakeLists.txt +16 -1
  4. data/ext/cache/cpm/{CPM_0.42.0.cmake → CPM_0.43.1.cmake} +18 -2
  5. data/ext/cache/extconf_include.rb +6 -6
  6. data/ext/cache/mozilla-ca-bundle.crt +214 -155
  7. data/ext/cache/mozilla-ca-bundle.sha256 +1 -1
  8. data/ext/couchbase/CMakeLists.txt +130 -21
  9. data/ext/couchbase/cmake/APKBUILD.in +25 -4
  10. data/ext/couchbase/cmake/Bundler.cmake +143 -34
  11. data/ext/couchbase/cmake/CPM.cmake +126 -12
  12. data/ext/couchbase/cmake/Cache.cmake +7 -1
  13. data/ext/couchbase/cmake/CompilerOptions.cmake +1 -1
  14. data/ext/couchbase/cmake/CompilerWarnings.cmake +17 -6
  15. data/ext/couchbase/cmake/GrpcProtobuf.cmake +481 -0
  16. data/ext/couchbase/cmake/OpenSSL.cmake +10 -3
  17. data/ext/couchbase/cmake/Packaging.cmake +519 -65
  18. data/ext/couchbase/cmake/Protostellar.cmake +250 -0
  19. data/ext/couchbase/cmake/Sanitizers.cmake +61 -50
  20. data/ext/couchbase/cmake/StaticAnalyzers.cmake +16 -5
  21. data/ext/couchbase/cmake/TestFramework.cmake +283 -0
  22. data/ext/couchbase/cmake/TestFrameworkAddTests.cmake +51 -0
  23. data/ext/couchbase/cmake/Testing.cmake +27 -9
  24. data/ext/couchbase/cmake/ThirdPartyDependencies.cmake +141 -8
  25. data/ext/couchbase/cmake/VersionInfo.cmake +50 -0
  26. data/ext/couchbase/cmake/build_config.hxx.in +2 -1
  27. data/ext/couchbase/cmake/couchbase-cxx-client.spec.in +101 -23
  28. data/ext/couchbase/cmake/couchbase_cxx_client_static-config.cmake.in +7 -0
  29. data/ext/couchbase/cmake/couchbase_cxx_client_static.pc.in +2 -0
  30. data/ext/couchbase/cmake/gRPC_Generate.cmake +58 -0
  31. data/ext/couchbase/cmake/protobuf_Generate.cmake +69 -0
  32. data/ext/couchbase/cmake/require-git-checkout.cmake +25 -0
  33. data/ext/couchbase/cmake/tarball_glob.txt +49 -0
  34. data/ext/couchbase/core/agent_group.cxx +0 -8
  35. data/ext/couchbase/core/agent_group.hxx +0 -4
  36. data/ext/couchbase/core/analytics_stream.cxx +314 -0
  37. data/ext/couchbase/core/analytics_stream.hxx +129 -0
  38. data/ext/couchbase/core/analytics_stream_component.cxx +245 -0
  39. data/ext/couchbase/core/analytics_stream_component.hxx +67 -0
  40. data/ext/couchbase/core/app_telemetry_meter.cxx +25 -3
  41. data/ext/couchbase/core/app_telemetry_meter.hxx +77 -0
  42. data/ext/couchbase/core/app_telemetry_reporter.cxx +7 -6
  43. data/ext/couchbase/core/bucket.cxx +381 -87
  44. data/ext/couchbase/core/bucket.hxx +105 -25
  45. data/ext/couchbase/core/bucket_unit_test_api.hxx +57 -0
  46. data/ext/couchbase/core/capella.hxx +91 -0
  47. data/ext/couchbase/core/cluster.cxx +1554 -398
  48. data/ext/couchbase/core/cluster.hxx +39 -8
  49. data/ext/couchbase/core/cluster_agent.cxx +0 -8
  50. data/ext/couchbase/core/cluster_agent.hxx +0 -4
  51. data/ext/couchbase/core/cluster_options.hxx +26 -3
  52. data/ext/couchbase/core/collections_component.cxx +39 -15
  53. data/ext/couchbase/core/config_profiles.cxx +1 -1
  54. data/ext/couchbase/core/crud_component.cxx +2 -2
  55. data/ext/couchbase/core/crud_options.hxx +34 -0
  56. data/ext/couchbase/core/crypto/cbcrypto.cc +18 -13
  57. data/ext/couchbase/core/document_id_redaction.hxx +81 -0
  58. data/ext/couchbase/core/error_context/base_error_context.hxx +7 -6
  59. data/ext/couchbase/core/error_context/key_value.cxx +25 -2
  60. data/ext/couchbase/core/error_context/key_value.hxx +60 -33
  61. data/ext/couchbase/core/error_context/key_value_error_context.hxx +16 -15
  62. data/ext/couchbase/core/error_context/search.hxx +5 -0
  63. data/ext/couchbase/core/error_context/search_json.hxx +3 -0
  64. data/ext/couchbase/core/error_context/subdocument_error_context.hxx +19 -18
  65. data/ext/couchbase/core/error_context/view.hxx +5 -0
  66. data/ext/couchbase/core/free_form_http_request.cxx +237 -4
  67. data/ext/couchbase/core/free_form_http_request.hxx +41 -8
  68. data/ext/couchbase/core/http_component.cxx +300 -284
  69. data/ext/couchbase/core/http_component.hxx +0 -4
  70. data/ext/couchbase/core/impl/analytics.cxx +38 -5
  71. data/ext/couchbase/core/impl/analytics.hxx +34 -0
  72. data/ext/couchbase/core/impl/bootstrap_error.hxx +0 -3
  73. data/ext/couchbase/core/impl/collection.cxx +215 -202
  74. data/ext/couchbase/core/impl/collection_manager.cxx +1 -1
  75. data/ext/couchbase/core/impl/dns_srv_tracker.cxx +45 -18
  76. data/ext/couchbase/core/impl/error.cxx +22 -2
  77. data/ext/couchbase/core/impl/internal_analytics_stream_result.hxx +111 -0
  78. data/ext/couchbase/core/impl/internal_query_stream_result.hxx +110 -0
  79. data/ext/couchbase/core/impl/invoke_with_node_id.hxx +15 -7
  80. data/ext/couchbase/core/impl/key_value_error_category.cxx +6 -0
  81. data/ext/couchbase/core/impl/lookup_in_replica.cxx +10 -10
  82. data/ext/couchbase/core/impl/lookup_in_replica.hxx +4 -4
  83. data/ext/couchbase/core/impl/node_id.cxx +49 -13
  84. data/ext/couchbase/core/impl/observability_recorder.cxx +12 -2
  85. data/ext/couchbase/core/impl/observe_poll.cxx +63 -23
  86. data/ext/couchbase/core/impl/public_analytics_stream_result.cxx +372 -0
  87. data/ext/couchbase/core/impl/public_bucket.cxx +48 -2
  88. data/ext/couchbase/core/impl/public_cluster.cxx +325 -25
  89. data/ext/couchbase/core/impl/public_query_stream_result.cxx +380 -0
  90. data/ext/couchbase/core/impl/public_transaction_get_multi_replicas_from_preferred_server_group_result.cxx +42 -0
  91. data/ext/couchbase/core/impl/public_transaction_get_multi_result.cxx +42 -0
  92. data/ext/couchbase/core/impl/query.cxx +76 -7
  93. data/ext/couchbase/core/impl/query.hxx +36 -0
  94. data/ext/couchbase/core/impl/query_index_manager.cxx +54 -1
  95. data/ext/couchbase/core/impl/replica_utils.cxx +101 -0
  96. data/ext/couchbase/core/impl/replica_utils.hxx +64 -0
  97. data/ext/couchbase/core/impl/resolve_node_id.hxx +125 -0
  98. data/ext/couchbase/core/impl/scope.cxx +70 -0
  99. data/ext/couchbase/core/impl/search.cxx +31 -1
  100. data/ext/couchbase/core/impl/transactions.cxx +130 -0
  101. data/ext/couchbase/core/impl/wait_until_ready.cxx +439 -0
  102. data/ext/couchbase/core/impl/wait_until_ready.hxx +110 -0
  103. data/ext/couchbase/core/impl/with_bucket_config_or_timeout.hxx +180 -0
  104. data/ext/couchbase/core/impl/with_cancellation.hxx +11 -3
  105. data/ext/couchbase/core/io/configuration_belongs_to_session.hxx +66 -0
  106. data/ext/couchbase/core/io/dns_client.cxx +122 -45
  107. data/ext/couchbase/core/io/dns_codec.hxx +21 -21
  108. data/ext/couchbase/core/io/dns_config.cxx +21 -6
  109. data/ext/couchbase/core/io/http_command.hxx +149 -121
  110. data/ext/couchbase/core/io/http_error.hxx +107 -0
  111. data/ext/couchbase/core/io/http_parser.cxx +4 -0
  112. data/ext/couchbase/core/io/http_session.cxx +606 -154
  113. data/ext/couchbase/core/io/http_session.hxx +147 -30
  114. data/ext/couchbase/core/io/http_session_manager.hxx +329 -382
  115. data/ext/couchbase/core/io/http_streaming_parser.cxx +4 -0
  116. data/ext/couchbase/core/io/http_streaming_response.cxx +328 -43
  117. data/ext/couchbase/core/io/http_streaming_response.hxx +37 -3
  118. data/ext/couchbase/core/io/mcbp_buffer_pool.hxx +122 -0
  119. data/ext/couchbase/core/io/mcbp_command.hxx +150 -51
  120. data/ext/couchbase/core/io/mcbp_command_id.hxx +45 -0
  121. data/ext/couchbase/core/io/mcbp_message.cxx +9 -1
  122. data/ext/couchbase/core/io/mcbp_message.hxx +19 -0
  123. data/ext/couchbase/core/io/mcbp_output_queue.hxx +150 -0
  124. data/ext/couchbase/core/io/mcbp_parser.cxx +24 -7
  125. data/ext/couchbase/core/io/mcbp_session.cxx +316 -317
  126. data/ext/couchbase/core/io/mcbp_session.hxx +27 -18
  127. data/ext/couchbase/core/io/opaque_ring_table.hxx +145 -0
  128. data/ext/couchbase/core/io/retry_orchestrator.hxx +6 -5
  129. data/ext/couchbase/core/io/stream_deadline.hxx +50 -0
  130. data/ext/couchbase/core/io/streams.cxx +275 -14
  131. data/ext/couchbase/core/io/streams.hxx +53 -0
  132. data/ext/couchbase/core/logger/logger.cxx +36 -0
  133. data/ext/couchbase/core/logger/logger.hxx +46 -6
  134. data/ext/couchbase/core/logger/redaction.hxx +503 -0
  135. data/ext/couchbase/core/management/eventing_status.hxx +10 -0
  136. data/ext/couchbase/core/management/eventing_status_json.hxx +4 -0
  137. data/ext/couchbase/core/mcbp/big_endian.cxx +1 -1
  138. data/ext/couchbase/core/mcbp/codec.cxx +27 -18
  139. data/ext/couchbase/core/mcbp/operation_queue.cxx +2 -2
  140. data/ext/couchbase/core/mcbp/packet.hxx +2 -2
  141. data/ext/couchbase/core/mcbp/queue_request.cxx +23 -6
  142. data/ext/couchbase/core/mcbp/queue_request.hxx +21 -0
  143. data/ext/couchbase/core/meta/features.hxx +13 -0
  144. data/ext/couchbase/core/meta/version.cxx +6 -3
  145. data/ext/couchbase/core/metrics/logging_meter.cxx +5 -10
  146. data/ext/couchbase/core/metrics/meter_wrapper.cxx +63 -33
  147. data/ext/couchbase/core/metrics/meter_wrapper.hxx +55 -3
  148. data/ext/couchbase/core/operations/analytics_response_parsing.cxx +177 -0
  149. data/ext/couchbase/core/operations/analytics_response_parsing.hxx +55 -0
  150. data/ext/couchbase/core/operations/document_analytics.cxx +48 -130
  151. data/ext/couchbase/core/operations/document_analytics.hxx +14 -2
  152. data/ext/couchbase/core/operations/document_get_all_replicas.hxx +15 -7
  153. data/ext/couchbase/core/operations/document_get_any_replica.hxx +19 -8
  154. data/ext/couchbase/core/operations/document_get_projected.cxx +1 -1
  155. data/ext/couchbase/core/{impl/get_replica.cxx → operations/document_get_replica.cxx} +21 -3
  156. data/ext/couchbase/core/{impl/get_replica.hxx → operations/document_get_replica.hxx} +31 -4
  157. data/ext/couchbase/core/operations/document_lookup_in.cxx +10 -10
  158. data/ext/couchbase/core/operations/document_lookup_in_all_replicas.hxx +228 -198
  159. data/ext/couchbase/core/operations/document_lookup_in_any_replica.hxx +215 -217
  160. data/ext/couchbase/core/operations/document_query.cxx +108 -221
  161. data/ext/couchbase/core/operations/document_query.hxx +18 -4
  162. data/ext/couchbase/core/operations/document_search.cxx +52 -8
  163. data/ext/couchbase/core/operations/document_search.hxx +3 -0
  164. data/ext/couchbase/core/operations/document_view.cxx +3 -3
  165. data/ext/couchbase/core/operations/management/analytics_dataset_create.cxx +15 -8
  166. data/ext/couchbase/core/operations/management/analytics_dataset_create.hxx +4 -0
  167. data/ext/couchbase/core/operations/management/analytics_dataset_drop.cxx +11 -6
  168. data/ext/couchbase/core/operations/management/analytics_dataset_get_all.cxx +3 -2
  169. data/ext/couchbase/core/operations/management/analytics_dataverse_create.cxx +10 -5
  170. data/ext/couchbase/core/operations/management/analytics_dataverse_drop.cxx +10 -5
  171. data/ext/couchbase/core/operations/management/analytics_get_pending_mutations.cxx +2 -1
  172. data/ext/couchbase/core/operations/management/analytics_index_create.cxx +33 -8
  173. data/ext/couchbase/core/operations/management/analytics_index_drop.cxx +12 -7
  174. data/ext/couchbase/core/operations/management/analytics_index_get_all.cxx +3 -2
  175. data/ext/couchbase/core/operations/management/analytics_link_connect.cxx +11 -6
  176. data/ext/couchbase/core/operations/management/analytics_link_create.cxx +3 -3
  177. data/ext/couchbase/core/operations/management/analytics_link_disconnect.cxx +10 -4
  178. data/ext/couchbase/core/operations/management/analytics_link_drop.cxx +6 -4
  179. data/ext/couchbase/core/operations/management/analytics_link_get_all.cxx +4 -3
  180. data/ext/couchbase/core/operations/management/analytics_link_replace.cxx +3 -3
  181. data/ext/couchbase/core/operations/management/analytics_link_utils.hxx +1 -1
  182. data/ext/couchbase/core/operations/management/bucket_create.cxx +37 -38
  183. data/ext/couchbase/core/operations/management/bucket_update.cxx +26 -28
  184. data/ext/couchbase/core/operations/management/change_password.cxx +2 -0
  185. data/ext/couchbase/core/operations/management/collection_drop.cxx +5 -1
  186. data/ext/couchbase/core/operations/management/error_utils.cxx +59 -5
  187. data/ext/couchbase/core/operations/management/error_utils.hxx +29 -1
  188. data/ext/couchbase/core/operations/management/eventing_deploy_function.cxx +9 -3
  189. data/ext/couchbase/core/operations/management/eventing_drop_function.cxx +8 -3
  190. data/ext/couchbase/core/operations/management/eventing_get_all_functions.cxx +4 -2
  191. data/ext/couchbase/core/operations/management/eventing_get_function.cxx +5 -3
  192. data/ext/couchbase/core/operations/management/eventing_get_status.cxx +4 -2
  193. data/ext/couchbase/core/operations/management/eventing_pause_function.cxx +9 -3
  194. data/ext/couchbase/core/operations/management/eventing_resume_function.cxx +9 -3
  195. data/ext/couchbase/core/operations/management/eventing_undeploy_function.cxx +9 -3
  196. data/ext/couchbase/core/operations/management/eventing_upsert_function.cxx +9 -3
  197. data/ext/couchbase/core/operations/management/group_drop.cxx +3 -1
  198. data/ext/couchbase/core/operations/management/group_get.cxx +3 -1
  199. data/ext/couchbase/core/operations/management/group_upsert.cxx +11 -8
  200. data/ext/couchbase/core/operations/management/query_index_build.cxx +5 -2
  201. data/ext/couchbase/core/operations/management/query_index_create.cxx +9 -3
  202. data/ext/couchbase/core/operations/management/query_index_drop.cxx +11 -4
  203. data/ext/couchbase/core/operations/management/query_index_get_all.cxx +1 -1
  204. data/ext/couchbase/core/operations/management/query_index_get_all_deferred.cxx +1 -1
  205. data/ext/couchbase/core/operations/management/scope_drop.cxx +5 -1
  206. data/ext/couchbase/core/operations/management/scope_get_all.cxx +6 -1
  207. data/ext/couchbase/core/operations/management/search_get_stats.cxx +10 -0
  208. data/ext/couchbase/core/operations/management/search_index_analyze_document.cxx +3 -2
  209. data/ext/couchbase/core/operations/management/search_index_control_ingest.cxx +4 -3
  210. data/ext/couchbase/core/operations/management/search_index_control_plan_freeze.cxx +4 -3
  211. data/ext/couchbase/core/operations/management/search_index_control_query.cxx +4 -3
  212. data/ext/couchbase/core/operations/management/search_index_drop.cxx +2 -2
  213. data/ext/couchbase/core/operations/management/search_index_get.cxx +2 -2
  214. data/ext/couchbase/core/operations/management/search_index_get_documents_count.cxx +3 -2
  215. data/ext/couchbase/core/operations/management/search_index_get_stats.cxx +3 -1
  216. data/ext/couchbase/core/operations/management/search_index_upsert.cxx +2 -2
  217. data/ext/couchbase/core/operations/management/user_drop.cxx +3 -1
  218. data/ext/couchbase/core/operations/management/user_get.cxx +3 -1
  219. data/ext/couchbase/core/operations/management/user_upsert.cxx +12 -9
  220. data/ext/couchbase/core/operations/management/view_index_drop.cxx +1 -1
  221. data/ext/couchbase/core/operations/management/view_index_get.cxx +1 -1
  222. data/ext/couchbase/core/operations/management/view_index_upsert.cxx +1 -1
  223. data/ext/couchbase/core/operations/operation_traits.hxx +18 -0
  224. data/ext/couchbase/core/operations/query_response_parsing.cxx +211 -0
  225. data/ext/couchbase/core/operations/query_response_parsing.hxx +60 -0
  226. data/ext/couchbase/core/operations_fwd.hxx +3 -3
  227. data/ext/couchbase/core/origin.cxx +54 -26
  228. data/ext/couchbase/core/origin.hxx +12 -0
  229. data/ext/couchbase/core/orphan_reporter.cxx +2 -1
  230. data/ext/couchbase/core/platform/random.cc +7 -7
  231. data/ext/couchbase/core/protocol/client_request.cxx +2 -2
  232. data/ext/couchbase/core/protocol/client_request.hxx +38 -21
  233. data/ext/couchbase/core/protocol/client_response.cxx +11 -3
  234. data/ext/couchbase/core/protocol/client_response.hxx +27 -6
  235. data/ext/couchbase/core/protocol/cmd_append.cxx +2 -2
  236. data/ext/couchbase/core/protocol/cmd_cluster_map_change_notification.cxx +2 -2
  237. data/ext/couchbase/core/protocol/cmd_decrement.cxx +6 -6
  238. data/ext/couchbase/core/protocol/cmd_get.cxx +1 -1
  239. data/ext/couchbase/core/protocol/cmd_get_and_lock.cxx +2 -2
  240. data/ext/couchbase/core/protocol/cmd_get_and_touch.cxx +2 -2
  241. data/ext/couchbase/core/protocol/cmd_get_cluster_config.cxx +6 -4
  242. data/ext/couchbase/core/protocol/cmd_get_collection_id.cxx +2 -2
  243. data/ext/couchbase/core/protocol/cmd_get_error_map.cxx +1 -1
  244. data/ext/couchbase/core/protocol/cmd_get_meta.cxx +4 -4
  245. data/ext/couchbase/core/protocol/cmd_get_replica.cxx +1 -1
  246. data/ext/couchbase/core/protocol/cmd_hello.cxx +1 -1
  247. data/ext/couchbase/core/protocol/cmd_increment.cxx +6 -6
  248. data/ext/couchbase/core/protocol/cmd_insert.cxx +4 -4
  249. data/ext/couchbase/core/protocol/cmd_lookup_in.cxx +4 -3
  250. data/ext/couchbase/core/protocol/cmd_lookup_in_replica.cxx +4 -3
  251. data/ext/couchbase/core/protocol/cmd_mutate_in.cxx +10 -9
  252. data/ext/couchbase/core/protocol/cmd_mutate_in.hxx +10 -10
  253. data/ext/couchbase/core/protocol/cmd_observe_seqno.cxx +7 -7
  254. data/ext/couchbase/core/protocol/cmd_prepend.cxx +2 -2
  255. data/ext/couchbase/core/protocol/cmd_remove.cxx +2 -2
  256. data/ext/couchbase/core/protocol/cmd_replace.cxx +4 -4
  257. data/ext/couchbase/core/protocol/cmd_touch.cxx +1 -1
  258. data/ext/couchbase/core/protocol/cmd_upsert.cxx +4 -4
  259. data/ext/couchbase/core/protocol/datatype.hxx +118 -1
  260. data/ext/couchbase/core/protocol/frame_info_utils.cxx +1 -1
  261. data/ext/couchbase/core/protocol/magic.hxx +4 -0
  262. data/ext/couchbase/core/protocol/magic_fmt.hxx +3 -0
  263. data/ext/couchbase/core/protocol/server_request.hxx +3 -1
  264. data/ext/couchbase/core/protocol/status.cxx +1 -1
  265. data/ext/couchbase/core/protostellar/analytics_converter.hxx +171 -0
  266. data/ext/couchbase/core/protostellar/bucket_admin_converter.hxx +301 -0
  267. data/ext/couchbase/core/protostellar/collection_admin_converter.hxx +92 -0
  268. data/ext/couchbase/core/protostellar/component.cxx +2445 -0
  269. data/ext/couchbase/core/protostellar/component.hxx +391 -0
  270. data/ext/couchbase/core/{columnar/bootstrap_notification_subscriber.hxx → protostellar/compression_settings.hxx} +11 -10
  271. data/ext/couchbase/core/protostellar/credentials.cxx +233 -0
  272. data/ext/couchbase/core/protostellar/credentials.hxx +88 -0
  273. data/ext/couchbase/core/protostellar/dispatcher.cxx +57 -0
  274. data/ext/couchbase/core/protostellar/dispatcher.hxx +482 -0
  275. data/ext/couchbase/core/protostellar/error_utils.cxx +293 -0
  276. data/ext/couchbase/core/protostellar/error_utils.hxx +97 -0
  277. data/ext/couchbase/core/protostellar/json_payload.hxx +49 -0
  278. data/ext/couchbase/core/protostellar/kv_converter.cxx +70 -0
  279. data/ext/couchbase/core/protostellar/kv_converter.hxx +600 -0
  280. data/ext/couchbase/core/protostellar/query_converter.hxx +265 -0
  281. data/ext/couchbase/core/protostellar/query_index_admin_converter.hxx +291 -0
  282. data/ext/couchbase/core/protostellar/query_proto.hxx +73 -0
  283. data/ext/couchbase/core/protostellar/search_converter.hxx +244 -0
  284. data/ext/couchbase/core/protostellar/search_index_admin_converter.hxx +156 -0
  285. data/ext/couchbase/core/protostellar/view_converter.hxx +158 -0
  286. data/ext/couchbase/core/query_stream.cxx +447 -0
  287. data/ext/couchbase/core/query_stream.hxx +141 -0
  288. data/ext/couchbase/core/query_stream_component.cxx +243 -0
  289. data/ext/couchbase/core/query_stream_component.hxx +68 -0
  290. data/ext/couchbase/core/range_scan_load_balancer.cxx +15 -8
  291. data/ext/couchbase/core/range_scan_orchestrator.cxx +15 -3
  292. data/ext/couchbase/core/response_handler.hxx +41 -4
  293. data/ext/couchbase/core/row_streamer.cxx +332 -46
  294. data/ext/couchbase/core/row_streamer.hxx +31 -1
  295. data/ext/couchbase/core/row_streamer_options.hxx +55 -0
  296. data/ext/couchbase/core/sasl/client.h +3 -0
  297. data/ext/couchbase/core/search_scoring.hxx +66 -0
  298. data/ext/couchbase/core/stream_error_details.hxx +69 -0
  299. data/ext/couchbase/core/timeout_defaults.hxx +0 -1
  300. data/ext/couchbase/core/topology/capabilities.hxx +6 -0
  301. data/ext/couchbase/core/topology/capabilities_fmt.hxx +3 -0
  302. data/ext/couchbase/core/topology/configuration.cxx +21 -6
  303. data/ext/couchbase/core/topology/configuration.hxx +29 -8
  304. data/ext/couchbase/core/topology/configuration_json.hxx +3 -0
  305. data/ext/couchbase/core/topology/error_map_json.hxx +3 -1
  306. data/ext/couchbase/core/tracing/threshold_logging_tracer.cxx +70 -4
  307. data/ext/couchbase/core/tracing/threshold_logging_tracer.hxx +10 -0
  308. data/ext/couchbase/core/transactions/active_transaction_record.cxx +0 -34
  309. data/ext/couchbase/core/transactions/attempt_context_impl.cxx +362 -241
  310. data/ext/couchbase/core/transactions/attempt_context_impl.hxx +24 -3
  311. data/ext/couchbase/core/transactions/error_list.hxx +2 -2
  312. data/ext/couchbase/core/transactions/get_multi_fetch.hxx +160 -0
  313. data/ext/couchbase/core/transactions/get_multi_orchestrator.cxx +326 -125
  314. data/ext/couchbase/core/transactions/get_multi_transaction_id.hxx +62 -0
  315. data/ext/couchbase/core/transactions/internal/atr_entry.hxx +22 -2
  316. data/ext/couchbase/core/transactions/internal/transaction_context.hxx +2 -2
  317. data/ext/couchbase/core/transactions/internal/transactions_cleanup.hxx +23 -1
  318. data/ext/couchbase/core/transactions/internal/utils.hxx +50 -14
  319. data/ext/couchbase/core/transactions/staged_mutation.cxx +23 -18
  320. data/ext/couchbase/core/transactions/staged_mutation.hxx +15 -4
  321. data/ext/couchbase/core/transactions/transaction_context.cxx +55 -40
  322. data/ext/couchbase/core/transactions/transaction_get_result.hxx +16 -0
  323. data/ext/couchbase/core/transactions/transactions.cxx +3 -55
  324. data/ext/couchbase/core/transactions/transactions_cleanup.cxx +194 -66
  325. data/ext/couchbase/core/transactions/transactions_config.cxx +0 -11
  326. data/ext/couchbase/core/transactions/utils.cxx +10 -0
  327. data/ext/couchbase/core/transactions/waitable_op_list.hxx +15 -4
  328. data/ext/couchbase/core/transactions.hxx +9 -9
  329. data/ext/couchbase/core/utils/byteswap.hxx +166 -9
  330. data/ext/couchbase/core/utils/connection_string.cxx +50 -85
  331. data/ext/couchbase/core/utils/connection_string.hxx +15 -0
  332. data/ext/couchbase/core/{columnar/backoff_calculator.hxx → utils/deadline.hxx} +13 -13
  333. data/ext/couchbase/core/utils/duration_parser.cxx +1 -1
  334. data/ext/couchbase/core/utils/json_streaming_lexer.cxx +48 -5
  335. data/ext/couchbase/core/utils/json_streaming_lexer.hxx +4 -1
  336. data/ext/couchbase/core/utils/movable_function.hxx +301 -52
  337. data/ext/couchbase/core/utils/name_codec.hxx +154 -11
  338. data/ext/couchbase/core/{columnar/retry_info.hxx → utils/process_id.hxx} +18 -13
  339. data/ext/couchbase/core/utils/url_codec.cxx +12 -51
  340. data/ext/couchbase/core/websocket_codec.cxx +3 -29
  341. data/ext/couchbase/couchbase/analytics_options.hxx +21 -10
  342. data/ext/couchbase/couchbase/analytics_row.hxx +105 -0
  343. data/ext/couchbase/couchbase/analytics_stream_result.hxx +266 -0
  344. data/ext/couchbase/couchbase/boolean_query.hxx +3 -3
  345. data/ext/couchbase/couchbase/bucket.hxx +57 -0
  346. data/ext/couchbase/couchbase/cluster.hxx +216 -5
  347. data/ext/couchbase/{core/columnar/security_options.hxx → couchbase/cluster_state.hxx} +18 -14
  348. data/ext/couchbase/couchbase/codec/lenient_json_transcoder.hxx +69 -0
  349. data/ext/couchbase/couchbase/collection.hxx +234 -14
  350. data/ext/couchbase/couchbase/common_durability_options.hxx +18 -3
  351. data/ext/couchbase/couchbase/conjunction_query.hxx +1 -1
  352. data/ext/couchbase/couchbase/create_dataset_analytics_options.hxx +6 -1
  353. data/ext/couchbase/couchbase/date_range_query.hxx +2 -2
  354. data/ext/couchbase/couchbase/decrement_options.hxx +1 -1
  355. data/ext/couchbase/couchbase/disjunction_query.hxx +1 -1
  356. data/ext/couchbase/couchbase/error.hxx +32 -0
  357. data/ext/couchbase/couchbase/error_codes.hxx +32 -0
  358. data/ext/couchbase/couchbase/geo_bounding_box_query.hxx +1 -1
  359. data/ext/couchbase/couchbase/geo_distance_query.hxx +1 -1
  360. data/ext/couchbase/couchbase/geo_polygon_query.hxx +1 -1
  361. data/ext/couchbase/couchbase/get_replica_options.hxx +68 -0
  362. data/ext/couchbase/couchbase/get_replica_result.hxx +5 -3
  363. data/ext/couchbase/couchbase/get_replica_strategy.hxx +161 -0
  364. data/ext/couchbase/couchbase/get_result.hxx +1 -0
  365. data/ext/couchbase/couchbase/increment_options.hxx +1 -1
  366. data/ext/couchbase/couchbase/insert_options.hxx +1 -1
  367. data/ext/couchbase/couchbase/match_phrase_query.hxx +1 -1
  368. data/ext/couchbase/couchbase/match_query.hxx +1 -1
  369. data/ext/couchbase/couchbase/mutate_in_options.hxx +3 -3
  370. data/ext/couchbase/couchbase/network_options.hxx +1 -1
  371. data/ext/couchbase/couchbase/node_id.hxx +42 -14
  372. data/ext/couchbase/couchbase/node_id_for_options.hxx +7 -1
  373. data/ext/couchbase/couchbase/node_ids_options.hxx +8 -2
  374. data/ext/couchbase/couchbase/numeric_range_query.hxx +1 -1
  375. data/ext/couchbase/couchbase/phrase_query.hxx +1 -1
  376. data/ext/couchbase/couchbase/prefix_query.hxx +1 -1
  377. data/ext/couchbase/couchbase/query_options.hxx +23 -12
  378. data/ext/couchbase/couchbase/query_row.hxx +111 -0
  379. data/ext/couchbase/couchbase/query_stream_result.hxx +302 -0
  380. data/ext/couchbase/couchbase/query_string_query.hxx +3 -3
  381. data/ext/couchbase/couchbase/regexp_query.hxx +1 -1
  382. data/ext/couchbase/couchbase/replace_options.hxx +3 -3
  383. data/ext/couchbase/couchbase/result.hxx +14 -3
  384. data/ext/couchbase/couchbase/scan_result_item.hxx +1 -0
  385. data/ext/couchbase/couchbase/scope.hxx +85 -2
  386. data/ext/couchbase/couchbase/search_options.hxx +58 -8
  387. data/ext/couchbase/couchbase/search_scoring.hxx +94 -0
  388. data/ext/couchbase/couchbase/search_scoring_none.hxx +51 -0
  389. data/ext/couchbase/couchbase/search_scoring_reciprocal_rank_fusion.hxx +88 -0
  390. data/ext/couchbase/couchbase/search_scoring_relative_score_fusion.hxx +70 -0
  391. data/ext/couchbase/couchbase/term_range_query.hxx +1 -1
  392. data/ext/couchbase/couchbase/tracing/request_span.hxx +46 -0
  393. data/ext/couchbase/couchbase/transactions/transaction_get_multi_replicas_from_preferred_server_group_result.hxx +23 -21
  394. data/ext/couchbase/couchbase/transactions/transaction_get_multi_result.hxx +24 -19
  395. data/ext/couchbase/couchbase/transactions/transaction_get_result.hxx +17 -3
  396. data/ext/couchbase/couchbase/transactions/transactions_config.hxx +4 -2
  397. data/ext/couchbase/couchbase/transactions.hxx +27 -18
  398. data/ext/couchbase/couchbase/upsert_options.hxx +3 -3
  399. data/ext/couchbase/couchbase/vector_query.hxx +1 -1
  400. data/ext/couchbase/couchbase/wait_until_ready_options.hxx +111 -0
  401. data/ext/couchbase/couchbase/wildcard_query.hxx +1 -1
  402. data/ext/extconf.rb +15 -10
  403. data/ext/rcb_analytics.cxx +82 -102
  404. data/ext/rcb_backend.cxx +42 -36
  405. data/ext/rcb_backend.hxx +2 -0
  406. data/ext/rcb_buckets.cxx +47 -59
  407. data/ext/rcb_collections.cxx +42 -52
  408. data/ext/rcb_crud.cxx +345 -224
  409. data/ext/rcb_diagnostics.cxx +117 -27
  410. data/ext/rcb_exceptions.cxx +152 -99
  411. data/ext/rcb_exceptions.hxx +25 -0
  412. data/ext/rcb_extras.cxx +18 -19
  413. data/ext/rcb_hdr_histogram.cxx +19 -4
  414. data/ext/rcb_logger.cxx +202 -27
  415. data/ext/rcb_logger.hxx +12 -0
  416. data/ext/rcb_multi.cxx +40 -40
  417. data/ext/rcb_observability.cxx +7 -5
  418. data/ext/rcb_query.cxx +99 -142
  419. data/ext/rcb_range_scan.cxx +41 -35
  420. data/ext/rcb_search.cxx +98 -99
  421. data/ext/rcb_users.cxx +36 -56
  422. data/ext/rcb_utils.cxx +100 -37
  423. data/ext/rcb_utils.hxx +287 -33
  424. data/ext/rcb_version.cxx +1 -1
  425. data/ext/rcb_views.cxx +55 -51
  426. data/lib/active_support/cache/couchbase_store.rb +77 -12
  427. data/lib/couchbase/bucket.rb +20 -0
  428. data/lib/couchbase/cluster.rb +33 -14
  429. data/lib/couchbase/collection.rb +36 -1
  430. data/lib/couchbase/errors.rb +18 -0
  431. data/lib/couchbase/fork_hooks.rb +16 -7
  432. data/lib/couchbase/get_replica_strategy.rb +89 -0
  433. data/lib/couchbase/logger.rb +1 -1
  434. data/lib/couchbase/management/analytics_index_manager.rb +15 -15
  435. data/lib/couchbase/management/bucket_manager.rb +6 -6
  436. data/lib/couchbase/management/collection_manager.rb +6 -6
  437. data/lib/couchbase/management/query_index_manager.rb +7 -7
  438. data/lib/couchbase/management/search_index_manager.rb +13 -13
  439. data/lib/couchbase/management/user_manager.rb +10 -10
  440. data/lib/couchbase/management/view_index_manager.rb +5 -5
  441. data/lib/couchbase/options.rb +181 -44
  442. data/lib/couchbase/protostellar/bucket.rb +4 -0
  443. data/lib/couchbase/protostellar/cluster.rb +4 -0
  444. data/lib/couchbase/protostellar/collection.rb +4 -0
  445. data/lib/couchbase/protostellar/error_handling.rb +2 -1
  446. data/lib/couchbase/protostellar/request.rb +1 -0
  447. data/lib/couchbase/protostellar/request_generator/kv.rb +16 -2
  448. data/lib/couchbase/protostellar/request_generator/search.rb +17 -1
  449. data/lib/couchbase/protostellar/retry/orchestrator.rb +3 -2
  450. data/lib/couchbase/protostellar/retry/strategies/fail_fast.rb +33 -0
  451. data/lib/couchbase/protostellar/retry/strategies.rb +1 -0
  452. data/lib/couchbase/search_options.rb +95 -6
  453. data/lib/couchbase/version.rb +1 -1
  454. metadata +92 -33
  455. data/ext/0001-fix-build-for-mingw-w64-ucrt-x86_64-toolchain.patch +0 -40
  456. data/ext/couchbase/core/columnar/agent.hxx +0 -71
  457. data/ext/couchbase/core/columnar/agent_config.hxx +0 -59
  458. data/ext/couchbase/core/columnar/background_bootstrap_listener.hxx +0 -42
  459. data/ext/couchbase/core/columnar/backoff_calculator.cxx +0 -62
  460. data/ext/couchbase/core/columnar/columnar_agent.cxx +0 -147
  461. data/ext/couchbase/core/columnar/columnar_agent_config.cxx +0 -48
  462. data/ext/couchbase/core/columnar/columnar_error.cxx +0 -51
  463. data/ext/couchbase/core/columnar/database_management_options.hxx +0 -56
  464. data/ext/couchbase/core/columnar/error.hxx +0 -51
  465. data/ext/couchbase/core/columnar/error_codes.cxx +0 -107
  466. data/ext/couchbase/core/columnar/error_codes.hxx +0 -75
  467. data/ext/couchbase/core/columnar/management_component.cxx +0 -300
  468. data/ext/couchbase/core/columnar/management_component.hxx +0 -56
  469. data/ext/couchbase/core/columnar/query_component.cxx +0 -523
  470. data/ext/couchbase/core/columnar/query_component.hxx +0 -57
  471. data/ext/couchbase/core/columnar/query_options.hxx +0 -59
  472. data/ext/couchbase/core/columnar/query_result.cxx +0 -130
  473. data/ext/couchbase/core/columnar/query_result.hxx +0 -78
  474. data/ext/couchbase/core/io/config_tracker.cxx +0 -687
  475. data/ext/couchbase/core/io/config_tracker.hxx +0 -123
@@ -36,28 +36,28 @@ public:
36
36
 
37
37
  std::memcpy(&message.header.id, payload.data() + offset, sizeof(std::uint16_t));
38
38
  offset += sizeof(std::uint16_t);
39
- message.header.id = utils::byte_swap(message.header.id);
39
+ message.header.id = utils::network_to_host(message.header.id);
40
40
 
41
41
  std::uint16_t flags = 0;
42
42
  std::memcpy(&flags, payload.data() + offset, sizeof(std::uint16_t));
43
43
  offset += sizeof(std::uint16_t);
44
- message.header.flags.decode(utils::byte_swap(flags));
44
+ message.header.flags.decode(utils::network_to_host(flags));
45
45
 
46
46
  std::memcpy(&message.header.question_records, payload.data() + offset, sizeof(std::uint16_t));
47
47
  offset += sizeof(std::uint16_t);
48
- message.header.question_records = utils::byte_swap(message.header.question_records);
48
+ message.header.question_records = utils::network_to_host(message.header.question_records);
49
49
 
50
50
  std::memcpy(&message.header.answer_records, payload.data() + offset, sizeof(std::uint16_t));
51
51
  offset += sizeof(std::uint16_t);
52
- message.header.answer_records = utils::byte_swap(message.header.answer_records);
52
+ message.header.answer_records = utils::network_to_host(message.header.answer_records);
53
53
 
54
54
  std::memcpy(&message.header.authority_records, payload.data() + offset, sizeof(std::uint16_t));
55
55
  offset += sizeof(std::uint16_t);
56
- message.header.authority_records = utils::byte_swap(message.header.authority_records);
56
+ message.header.authority_records = utils::network_to_host(message.header.authority_records);
57
57
 
58
58
  std::memcpy(&message.header.additional_records, payload.data() + offset, sizeof(std::uint16_t));
59
59
  offset += sizeof(std::uint16_t);
60
- message.header.additional_records = utils::byte_swap(message.header.additional_records);
60
+ message.header.additional_records = utils::network_to_host(message.header.additional_records);
61
61
 
62
62
  for (std::uint16_t idx = 0; idx < message.header.question_records; ++idx) {
63
63
  question_record qr;
@@ -66,12 +66,12 @@ public:
66
66
  std::uint16_t val = 0;
67
67
  std::memcpy(&val, payload.data() + offset, sizeof(std::uint16_t));
68
68
  offset += sizeof(std::uint16_t);
69
- val = utils::byte_swap(val);
69
+ val = utils::network_to_host(val);
70
70
  qr.type = resource_type(val);
71
71
 
72
72
  std::memcpy(&val, payload.data() + offset, sizeof(std::uint16_t));
73
73
  offset += sizeof(std::uint16_t);
74
- val = utils::byte_swap(val);
74
+ val = utils::network_to_host(val);
75
75
  qr.klass = static_cast<resource_class>(val);
76
76
 
77
77
  message.questions.emplace_back(qr);
@@ -85,22 +85,22 @@ public:
85
85
  std::uint16_t val = 0;
86
86
  std::memcpy(&val, payload.data() + offset, sizeof(std::uint16_t));
87
87
  offset += sizeof(std::uint16_t);
88
- val = utils::byte_swap(val);
88
+ val = utils::network_to_host(val);
89
89
  ar.type = resource_type(val);
90
90
 
91
91
  std::memcpy(&val, payload.data() + offset, sizeof(std::uint16_t));
92
92
  offset += sizeof(std::uint16_t);
93
- val = utils::byte_swap(val);
93
+ val = utils::network_to_host(val);
94
94
  ar.klass = resource_class(val);
95
95
 
96
96
  std::memcpy(&ar.ttl, payload.data() + offset, sizeof(std::uint32_t));
97
97
  offset += static_cast<std::uint16_t>(4U);
98
- ar.ttl = utils::byte_swap(ar.ttl);
98
+ ar.ttl = utils::network_to_host(ar.ttl);
99
99
 
100
100
  std::uint16_t size = 0;
101
101
  std::memcpy(&size, payload.data() + offset, sizeof(std::uint16_t));
102
102
  offset += sizeof(std::uint16_t);
103
- size = utils::byte_swap(size);
103
+ size = utils::network_to_host(size);
104
104
 
105
105
  if (ar.klass != resource_class::in || ar.type != resource_type::srv) {
106
106
  // ignore everything except SRV answers
@@ -110,15 +110,15 @@ public:
110
110
 
111
111
  std::memcpy(&val, payload.data() + offset, sizeof(std::uint16_t));
112
112
  offset += sizeof(std::uint16_t);
113
- ar.priority = utils::byte_swap(val);
113
+ ar.priority = utils::network_to_host(val);
114
114
 
115
115
  std::memcpy(&val, payload.data() + offset, sizeof(std::uint16_t));
116
116
  offset += sizeof(std::uint16_t);
117
- ar.weight = utils::byte_swap(val);
117
+ ar.weight = utils::network_to_host(val);
118
118
 
119
119
  std::memcpy(&val, payload.data() + offset, sizeof(std::uint16_t));
120
120
  offset += sizeof(std::uint16_t);
121
- ar.port = utils::byte_swap(val);
121
+ ar.port = utils::network_to_host(val);
122
122
 
123
123
  ar.target = get_name(payload, offset);
124
124
 
@@ -137,15 +137,15 @@ public:
137
137
  {
138
138
  std::uint16_t val;
139
139
 
140
- val = utils::byte_swap(message.header.id);
140
+ val = utils::host_to_network(message.header.id);
141
141
  std::memcpy(payload.data() + offset, &val, sizeof(std::uint16_t));
142
142
  offset += sizeof(std::uint16_t);
143
143
 
144
- val = utils::byte_swap(message.header.flags.encode());
144
+ val = utils::host_to_network(message.header.flags.encode());
145
145
  std::memcpy(payload.data() + offset, &val, sizeof(std::uint16_t));
146
146
  offset += sizeof(std::uint16_t);
147
147
 
148
- val = utils::byte_swap(static_cast<std::uint16_t>(message.questions.size()));
148
+ val = utils::host_to_network(static_cast<std::uint16_t>(message.questions.size()));
149
149
  std::memcpy(payload.data() + offset, &val, sizeof(std::uint16_t));
150
150
  offset += sizeof(std::uint16_t) +
151
151
  3 * sizeof(std::uint16_t); // answer, authority, additional are all zeros
@@ -164,11 +164,11 @@ public:
164
164
 
165
165
  std::uint16_t val;
166
166
 
167
- val = utils::byte_swap(static_cast<std::uint16_t>(question.type));
167
+ val = utils::host_to_network(static_cast<std::uint16_t>(question.type));
168
168
  std::memcpy(payload.data() + offset, &val, sizeof(std::uint16_t));
169
169
  offset += sizeof(std::uint16_t);
170
170
 
171
- val = utils::byte_swap(static_cast<std::uint16_t>(question.klass));
171
+ val = utils::host_to_network(static_cast<std::uint16_t>(question.klass));
172
172
  std::memcpy(payload.data() + offset, &val, sizeof(std::uint16_t));
173
173
  offset += sizeof(std::uint16_t);
174
174
  }
@@ -194,7 +194,7 @@ private:
194
194
  if ((len & 0b1100'0000U) != 0) {
195
195
  std::uint16_t ptr = 0;
196
196
  std::memcpy(&ptr, payload.data() + offset, sizeof(std::uint16_t));
197
- ptr = utils::byte_swap(ptr);
197
+ ptr = utils::network_to_host(ptr);
198
198
  ptr &= 0b0011'1111'1111'1111U;
199
199
  // store old offset and jump to pointer
200
200
  save_offset = offset + sizeof(std::uint16_t);
@@ -24,11 +24,10 @@
24
24
 
25
25
  #include <iphlpapi.h>
26
26
  #include <winsock2.h>
27
-
28
- #include "core/utils/join_strings.hxx"
29
27
  #endif
30
28
 
31
29
  #include "core/logger/logger.hxx"
30
+ #include "core/logger/redaction.hxx"
32
31
  #include "dns_config.hxx"
33
32
 
34
33
  #include <asio/ip/address.hpp>
@@ -36,7 +35,9 @@
36
35
  #include <filesystem>
37
36
  #include <fstream>
38
37
  #include <mutex>
38
+ #include <string>
39
39
  #include <utility>
40
+ #include <vector>
40
41
 
41
42
  namespace couchbase::core::io::dns
42
43
  {
@@ -98,8 +99,8 @@ load_resolv_conf()
98
99
 
99
100
  if (dns_servers.size() > 0) {
100
101
  CB_LOG_DEBUG("Found DNS Servers: [{}], selected nameserver: \"{}\"",
101
- couchbase::core::utils::join_strings(dns_servers, ", "),
102
- dns_servers[0]);
102
+ logger::system_data_list(dns_servers),
103
+ logger::system_data(dns_servers[0]));
103
104
  return dns_servers[0];
104
105
  }
105
106
  CB_LOG_WARNING("Unable to find DNS nameserver");
@@ -137,7 +138,8 @@ load_resolv_conf(const char* conf_path) -> std::string
137
138
  space = line.find(' ', offset);
138
139
  auto nameserver =
139
140
  (space == std::string::npos) ? line.substr(offset) : line.substr(offset, space - offset);
140
- CB_LOG_DEBUG("Selected nameserver: \"{}\" from \"{}\"", nameserver, conf_path);
141
+ CB_LOG_DEBUG(
142
+ "Selected nameserver: \"{}\" from \"{}\"", logger::system_data(nameserver), conf_path);
141
143
  return nameserver;
142
144
  }
143
145
  }
@@ -158,6 +160,19 @@ dns_config::system_config() -> const dns_config&
158
160
  #else
159
161
  auto nameserver = load_resolv_conf(default_resolv_conf_path);
160
162
  #endif
163
+ if (nameserver.empty()) {
164
+ #ifdef _WIN32
165
+ CB_LOG_WARNING("No DNS nameserver found via GetNetworkParams. DNS-SRV bootstrap is "
166
+ "disabled. Set the nameserver explicitly in the cluster options if SRV "
167
+ "records are needed.");
168
+ #else
169
+ CB_LOG_WARNING("No \"nameserver\" line found in \"{}\". DNS-SRV bootstrap is disabled. "
170
+ "Set the nameserver explicitly in the cluster options if SRV records are "
171
+ "needed.",
172
+ default_resolv_conf_path);
173
+ #endif
174
+ return;
175
+ }
161
176
  std::error_code ec;
162
177
  asio::ip::make_address(nameserver, ec);
163
178
  if (ec) {
@@ -168,7 +183,7 @@ dns_config::system_config() -> const dns_config&
168
183
  CB_LOG_WARNING("System DNS detection failed: unable to parse \"{}\" as a network address{}. "
169
184
  "DNS-SRV will not work "
170
185
  "unless nameserver is specified explicitly in the options.",
171
- nameserver,
186
+ logger::system_data(nameserver),
172
187
  extra_info);
173
188
  } else {
174
189
  instance.nameserver_ = nameserver;
@@ -21,16 +21,20 @@
21
21
 
22
22
  #include "core/app_telemetry_meter.hxx"
23
23
  #include "core/impl/bootstrap_error.hxx"
24
+ #include "core/logger/redaction.hxx"
24
25
  #include "core/metrics/meter_wrapper.hxx"
25
26
  #include "core/service_type_fmt.hxx"
26
27
  #include "core/tracing/constants.hxx"
27
28
  #include "core/tracing/tracer_wrapper.hxx"
28
29
  #include "core/utils/movable_function.hxx"
30
+ #include "http_error.hxx"
29
31
  #include "http_session.hxx"
30
32
  #include "http_traits.hxx"
31
33
 
32
34
  #include <couchbase/tracing/request_tracer.hxx>
33
35
 
36
+ #include <mutex>
37
+ #include <string_view>
34
38
  #include <utility>
35
39
 
36
40
  namespace couchbase::core::operations
@@ -52,35 +56,24 @@ struct http_command : public std::enable_shared_from_this<http_command<Request>>
52
56
  #endif
53
57
  std::shared_ptr<metrics::meter_wrapper> meter_{};
54
58
  std::shared_ptr<core::app_telemetry_meter> app_telemetry_meter_{ nullptr };
55
- std::shared_ptr<io::http_session> session_{};
59
+ // Not an owner: null once nothing else holds the session.
60
+ std::weak_ptr<io::http_session> session_{};
56
61
  handler_type handler_{};
62
+ std::mutex handler_mutex_{};
63
+ // Set by send_to() if the request had not completed, guarded by handler_mutex_. Until then
64
+ // session_for_check_in() returns null, so a completion before send_to() never pools the session.
65
+ bool sent_{ false };
66
+ // Guarded by handler_mutex_. complete() reports these, so its report does not depend on the
67
+ // session still being alive. The target fields belong to the session set_command_session()
68
+ // last assigned. The dispatched fields stay empty until send() dispatches.
69
+ std::string target_node_uuid_{};
70
+ std::string dispatched_from_{};
71
+ std::string dispatched_to_{};
72
+ std::string target_hostname_{};
73
+ std::uint16_t target_port_{};
57
74
  std::chrono::milliseconds timeout_{};
58
75
  std::string client_context_id_;
59
76
  std::shared_ptr<couchbase::tracing::request_span> parent_span_{ nullptr };
60
- #ifdef COUCHBASE_CXX_CLIENT_COLUMNAR
61
- std::chrono::milliseconds dispatch_timeout_{};
62
- asio::steady_timer dispatch_deadline_;
63
-
64
- http_command(asio::io_context& ctx,
65
- Request req,
66
- std::shared_ptr<tracing::tracer_wrapper> tracer,
67
- std::shared_ptr<metrics::meter_wrapper> meter,
68
- std::shared_ptr<core::app_telemetry_meter> app_telemetry_meter,
69
- std::chrono::milliseconds default_timeout,
70
- std::chrono::milliseconds dispatch_timeout)
71
- : deadline(ctx)
72
- , request(req)
73
- , tracer_(std::move(tracer))
74
- , meter_(std::move(meter))
75
- , app_telemetry_meter_(std::move(app_telemetry_meter))
76
- , timeout_(request.timeout.value_or(default_timeout))
77
- , client_context_id_(request.client_context_id.value_or(uuid::to_string(uuid::random())))
78
- , parent_span_(request.parent_span)
79
- , dispatch_timeout_(dispatch_timeout)
80
- , dispatch_deadline_(ctx)
81
- {
82
- }
83
- #else
84
77
  http_command(asio::io_context& ctx,
85
78
  Request req,
86
79
  std::shared_ptr<tracing::tracer_wrapper> tracer,
@@ -97,7 +90,6 @@ struct http_command : public std::enable_shared_from_this<http_command<Request>>
97
90
  , parent_span_(request.parent_span)
98
91
  {
99
92
  }
100
- #endif
101
93
 
102
94
  void start(handler_type&& handler)
103
95
  {
@@ -110,99 +102,108 @@ struct http_command : public std::enable_shared_from_this<http_command<Request>>
110
102
  #endif
111
103
 
112
104
  handler_ = std::move(handler);
113
- #ifdef COUCHBASE_CXX_CLIENT_COLUMNAR
114
- dispatch_deadline_.expires_after(dispatch_timeout_);
115
- dispatch_deadline_.async_wait([self = this->shared_from_this()](std::error_code ec) {
116
- if (ec == asio::error::operation_aborted) {
117
- return;
118
- }
119
- CB_LOG_DEBUG(R"(HTTP request timed out before dispatch: {}, client_context_id="{}")",
120
- self->request.type,
121
- self->client_context_id_);
122
- self->cancel(errc::common::unambiguous_timeout);
123
- });
124
- #endif
125
105
  deadline.expires_after(timeout_);
126
106
  deadline.async_wait([self = this->shared_from_this()](std::error_code ec) {
127
107
  if (ec == asio::error::operation_aborted) {
128
108
  return;
129
109
  }
130
- CB_LOG_DEBUG(R"(HTTP request timed out: {}, client_context_id="{}")",
131
- self->request.type,
132
- self->client_context_id_);
110
+ std::error_code timeout = errc::common::ambiguous_timeout;
133
111
  if constexpr (io::http_traits::supports_readonly_v<Request>) {
134
112
  if (self->request.readonly) {
135
- self->cancel(errc::common::unambiguous_timeout);
136
- return;
113
+ timeout = errc::common::unambiguous_timeout;
137
114
  }
138
115
  }
139
- self->cancel(errc::common::ambiguous_timeout);
116
+ if (!self->cancel(timeout)) {
117
+ return;
118
+ }
119
+ CB_LOG_DEBUG(R"(HTTP request timed out: {}, client_context_id="{}")",
120
+ self->request.type,
121
+ self->client_context_id_);
140
122
  });
141
123
  }
142
124
 
143
- void cancel(std::error_code ec)
125
+ // Stops the session, then completes the request with `ec`: the completion checks the session in,
126
+ // and check_in refuses a stopped one. Returns false, and stops nothing, when the handler was
127
+ // already taken, as by a response handled before a deadline completion already queued:
128
+ // deadline.cancel() does not retract it, and the session then belongs to the pool.
129
+ auto cancel(std::error_code ec) -> bool
144
130
  {
145
- invoke_handler(ec, {});
146
- if (session_) {
147
- session_->stop();
131
+ handler_type handler{};
132
+ std::shared_ptr<io::http_session> session;
133
+ {
134
+ const std::scoped_lock lock(handler_mutex_);
135
+ handler = std::move(handler_);
136
+ session = session_.lock();
137
+ }
138
+ if (!handler) {
139
+ return false;
140
+ }
141
+ if (session) {
142
+ session->stop();
148
143
  }
144
+ complete(std::move(handler), ec, {});
145
+ return true;
149
146
  }
150
147
 
151
- #ifdef COUCHBASE_CXX_CLIENT_COLUMNAR
152
- void invoke_handler(error_union error, io::http_response&& msg)
153
- #else
154
148
  void invoke_handler(std::error_code ec, io::http_response&& msg)
155
- #endif
156
149
  {
157
- if (handler_type handler = std::move(handler_); handler) {
158
- const auto& node_uuid = session_ ? session_->node_uuid() : "";
150
+ complete(take_handler(), ec, std::move(msg));
151
+ }
152
+
153
+ // The handler is the token for completing the request. The deadline completion runs on the
154
+ // io_context and the response on the session strand, so it is taken under handler_mutex_.
155
+ auto take_handler() -> handler_type
156
+ {
157
+ const std::scoped_lock lock(handler_mutex_);
158
+ return std::move(handler_);
159
+ }
160
+
161
+ void complete(handler_type handler, std::error_code ec, io::http_response&& msg)
162
+ {
163
+ if (handler) {
164
+ std::string node_uuid;
165
+ {
166
+ const std::scoped_lock lock(handler_mutex_);
167
+ node_uuid = target_node_uuid_;
168
+ }
159
169
  auto telemetry_recorder = app_telemetry_meter_->value_recorder(node_uuid, {});
160
170
  telemetry_recorder->update_counter(total_counter_for_service_type(request.type));
161
- #ifdef COUCHBASE_CXX_CLIENT_COLUMNAR
162
- std::error_code ec{};
163
- if (std::holds_alternative<std::error_code>(error)) {
164
- ec = std::get<std::error_code>(error);
165
- } else if (std::holds_alternative<impl::bootstrap_error>(error)) {
166
- ec = std::get<impl::bootstrap_error>(error).ec;
167
- }
168
- #endif
169
171
  if (ec == errc::common::ambiguous_timeout || ec == errc::common::unambiguous_timeout) {
170
172
  telemetry_recorder->update_counter(timedout_counter_for_service_type(request.type));
171
173
  } else if (ec == errc::common::request_canceled) {
172
174
  telemetry_recorder->update_counter(canceled_counter_for_service_type(request.type));
173
175
  }
174
176
  encoded_response_type encoded_resp{ std::move(msg) };
175
- error_context_type ctx{};
176
- #ifdef COUCHBASE_CXX_CLIENT_COLUMNAR
177
- if (!std::holds_alternative<std::monostate>(error)) {
178
- if (std::holds_alternative<impl::bootstrap_error>(error)) {
179
- auto bootstrap_error = std::get<impl::bootstrap_error>(error);
180
- if (bootstrap_error.ec == errc::common::unambiguous_timeout) {
181
- CB_LOG_DEBUG("Timeout caused by bootstrap error. code={}, ec_message={}, message={}.",
182
- bootstrap_error.ec.value(),
183
- bootstrap_error.ec.message(),
184
- bootstrap_error.error_message);
177
+ auto make_context = [&]() {
178
+ error_context_type ctx{};
179
+ ctx.ec = ec;
180
+ ctx.client_context_id = client_context_id_;
181
+ ctx.method = encoded.method;
182
+ ctx.path = encoded.path;
183
+ ctx.http_status = encoded_resp.status_code;
184
+ ctx.http_body = encoded_resp.body.data();
185
+ {
186
+ const std::scoped_lock lock(handler_mutex_);
187
+ // A request completed before any dispatch leaves last_dispatched_from/to unset.
188
+ if (!dispatched_to_.empty()) {
189
+ // A resend after a refused client certificate writes the request on a new connection.
190
+ if (const auto session = session_.lock(); session) {
191
+ if (auto [from, to] = session->dispatched_endpoints(); !to.empty()) {
192
+ dispatched_from_ = std::move(from);
193
+ dispatched_to_ = std::move(to);
194
+ }
195
+ }
196
+ ctx.last_dispatched_from = dispatched_from_;
197
+ ctx.last_dispatched_to = dispatched_to_;
185
198
  }
186
- ctx.ec = bootstrap_error.ec;
187
- } else {
188
- ctx.ec = std::get<std::error_code>(error);
199
+ ctx.hostname = target_hostname_;
200
+ ctx.port = target_port_;
189
201
  }
190
- }
191
- #else
192
- ctx.ec = ec;
193
- #endif
194
- ctx.client_context_id = client_context_id_;
195
- ctx.method = encoded.method;
196
- ctx.path = encoded.path;
197
- ctx.http_status = encoded_resp.status_code;
198
- ctx.http_body = encoded_resp.body.data();
199
- ctx.last_dispatched_from = session_->local_address();
200
- ctx.last_dispatched_to = session_->remote_address();
201
- ctx.hostname = session_->http_context().hostname;
202
- ctx.port = session_->http_context().port;
202
+ return ctx;
203
+ };
203
204
 
204
205
  // Can raise priv::retry_http_request when a retry is required
205
- auto resp = request.make_response(std::move(ctx), std::move(encoded_resp));
206
+ auto resp = io::complete_http_response(request, make_context, encoded_resp);
206
207
 
207
208
  #ifdef COUCHBASE_CXX_CLIENT_CREATE_OPERATION_SPAN_IN_CORE
208
209
  span_->end();
@@ -211,41 +212,49 @@ struct http_command : public std::enable_shared_from_this<http_command<Request>>
211
212
 
212
213
  handler(std::move(resp));
213
214
  }
214
- #ifdef COUCHBASE_CXX_CLIENT_COLUMNAR
215
- dispatch_deadline_.cancel();
216
- #endif
217
215
  deadline.cancel();
218
216
  }
219
217
 
220
218
  void send_to()
221
219
  {
222
- #ifdef COUCHBASE_CXX_CLIENT_COLUMNAR
223
- dispatch_deadline_.cancel();
224
- #endif
225
- if (!handler_) {
220
+ bool completed = false;
221
+ {
222
+ const std::scoped_lock lock(handler_mutex_);
223
+ completed = !handler_;
224
+ sent_ = !completed;
225
+ }
226
+ if (completed) {
227
+ // The completion ran with sent_ false, so session_for_check_in() gave it no session. Stopped
228
+ // here unless cancel() already stopped it; on_stop takes it off the busy list.
229
+ if (const auto session = session_.lock(); session) {
230
+ session->stop();
231
+ }
226
232
  return;
227
233
  }
228
234
  send();
229
235
  }
230
236
 
231
- void set_command_session(std::shared_ptr<io::http_session> session)
237
+ void set_command_session(const std::shared_ptr<io::http_session>& session)
232
238
  {
233
- session_.reset();
234
- session_ = std::move(session);
239
+ const std::scoped_lock lock(handler_mutex_);
240
+ session_ = session;
241
+ target_node_uuid_ = session->node_uuid();
242
+ target_hostname_ = session->http_context().hostname;
243
+ target_port_ = session->http_context().port;
235
244
  }
236
245
 
237
- [[nodiscard]] auto deadline_expiry() const -> std::chrono::time_point<std::chrono::steady_clock>
246
+ // The session the completion checks in: the one send_to() sent on, or null. A completion before
247
+ // send_to() gets null, so a session send_to() is about to stop is never pooled first.
248
+ [[nodiscard]] auto session_for_check_in() -> std::shared_ptr<io::http_session>
238
249
  {
239
- return deadline.expiry();
250
+ const std::scoped_lock lock(handler_mutex_);
251
+ return sent_ ? session_.lock() : nullptr;
240
252
  }
241
253
 
242
- #ifdef COUCHBASE_CXX_CLIENT_COLUMNAR
243
- [[nodiscard]] auto dispatch_deadline_expiry() const
244
- -> std::chrono::time_point<std::chrono::steady_clock>
254
+ [[nodiscard]] auto deadline_expiry() const -> std::chrono::time_point<std::chrono::steady_clock>
245
255
  {
246
- return dispatch_deadline_.expiry();
256
+ return deadline.expiry();
247
257
  }
248
- #endif
249
258
 
250
259
  private:
251
260
  void send()
@@ -253,25 +262,36 @@ private:
253
262
  encoded.type = request.type;
254
263
  encoded.client_context_id = client_context_id_;
255
264
  encoded.timeout = timeout_;
256
- if (auto ec = request.encode_to(encoded, session_->http_context()); ec) {
265
+ const auto session = session_.lock();
266
+ if (!session) {
267
+ return invoke_handler(errc::common::request_canceled, {});
268
+ }
269
+ if (auto ec = request.encode_to(encoded, session->http_context()); ec) {
257
270
  return invoke_handler(ec, {});
258
271
  }
259
272
  encoded.headers["client-context-id"] = client_context_id_;
260
273
 
261
274
  CB_LOG_TRACE(
262
275
  R"({} HTTP request: {}, method={}, path="{}", client_context_id="{}", timeout={}ms)",
263
- session_->log_prefix(),
276
+ session->log_prefix(),
264
277
  encoded.type,
265
278
  encoded.method,
266
- encoded.path,
279
+ logger::user_data(encoded.path),
267
280
  client_context_id_,
268
281
  timeout_.count());
269
282
 
270
- auto dispatch_span = create_dispatch_span();
283
+ auto dispatch_span = create_dispatch_span(*session);
284
+
285
+ {
286
+ const std::scoped_lock lock(handler_mutex_);
287
+ dispatched_from_ = session->local_address();
288
+ dispatched_to_ = session->remote_address();
289
+ }
271
290
 
272
- session_->write_and_subscribe(
291
+ session->write_and_subscribe(
273
292
  encoded,
274
293
  [self = this->shared_from_this(),
294
+ session,
275
295
  dispatch_span = std::move(dispatch_span),
276
296
  start = std::chrono::steady_clock::now()](std::error_code ec, io::http_response&& msg) {
277
297
  if (ec == asio::error::operation_aborted) {
@@ -284,16 +304,16 @@ private:
284
304
  {
285
305
  auto latency = std::chrono::duration_cast<std::chrono::milliseconds>(
286
306
  std::chrono::steady_clock::now() - start);
287
- self->app_telemetry_meter_->value_recorder(self->session_->node_uuid(), {})
307
+ self->app_telemetry_meter_->value_recorder(session->node_uuid(), {})
288
308
  ->record_latency(latency_for_service_type(self->request.type), latency);
289
309
  }
290
310
 
291
311
  #ifdef COUCHBASE_CXX_CLIENT_CREATE_OPERATION_SPAN_IN_CORE
292
312
  if (self->meter_) {
293
313
  metrics::metric_attributes attrs{
294
- self->request.type,
314
+ tracing::service_name_for_http_service(self->request.type),
295
315
  self->request.observability_identifier,
296
- ec,
316
+ metrics::standardized_error_type(ec),
297
317
  };
298
318
  self->meter_->record_value(std::move(attrs), start);
299
319
  }
@@ -301,12 +321,20 @@ private:
301
321
 
302
322
  self->deadline.cancel();
303
323
  CB_LOG_TRACE(R"({} HTTP response: {}, client_context_id="{}", ec={}, status={}, body={})",
304
- self->session_->log_prefix(),
324
+ session->log_prefix(),
305
325
  self->request.type,
306
326
  self->client_context_id_,
307
327
  ec.message(),
308
328
  msg.status_code,
309
- msg.status_code == 200 ? "[hidden]" : msg.body.data());
329
+ // Views, not strings: the arms have different types, so a plain ternary
330
+ // built a std::string and copied the whole body in on every non-200.
331
+ // Only the arm that carries a body is tagged. "[hidden]" is a constant the
332
+ // SDK substituted, and hashing it would leave a reader unable to tell a body
333
+ // the SDK withheld from one the redaction tool replaced.
334
+ logger::user_data_if(msg.status_code != 200,
335
+ msg.status_code == 200
336
+ ? std::string_view{ "[hidden]" }
337
+ : std::string_view{ msg.body.data() }));
310
338
  if (auto parser_ec = msg.body.ec(); !ec && parser_ec) {
311
339
  ec = parser_ec;
312
340
  }
@@ -318,7 +346,7 @@ private:
318
346
  });
319
347
  }
320
348
 
321
- [[nodiscard]] auto create_dispatch_span() const
349
+ [[nodiscard]] auto create_dispatch_span(io::http_session& session) const
322
350
  -> std::shared_ptr<couchbase::tracing::request_span>
323
351
  {
324
352
  #ifdef COUCHBASE_CXX_CLIENT_CREATE_OPERATION_SPAN_IN_CORE
@@ -331,13 +359,13 @@ private:
331
359
  if (dispatch_span->uses_tags()) {
332
360
  dispatch_span->add_tag(tracing::attributes::dispatch::network_transport, "tcp");
333
361
  dispatch_span->add_tag(tracing::attributes::dispatch::operation_id, client_context_id_);
334
- dispatch_span->add_tag(tracing::attributes::dispatch::local_id, session_->id());
362
+ dispatch_span->add_tag(tracing::attributes::dispatch::local_id, session.id());
335
363
  dispatch_span->add_tag(tracing::attributes::dispatch::server_address,
336
- session_->http_context().canonical_hostname);
364
+ session.http_context().canonical_hostname);
337
365
  dispatch_span->add_tag(tracing::attributes::dispatch::server_port,
338
- session_->http_context().canonical_port);
366
+ session.http_context().canonical_port);
339
367
 
340
- const auto& peer_endpoint = session_->remote_endpoint();
368
+ const auto& peer_endpoint = session.remote_endpoint();
341
369
  dispatch_span->add_tag(tracing::attributes::dispatch::peer_address,
342
370
  peer_endpoint.address().to_string());
343
371
  dispatch_span->add_tag(tracing::attributes::dispatch::peer_port, peer_endpoint.port());