couchbase 3.7.0 → 3.8.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 (286) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -3
  3. data/ext/CMakeLists.txt +4 -1
  4. data/ext/cache/extconf_include.rb +4 -3
  5. data/ext/cache/mozilla-ca-bundle.crt +66 -93
  6. data/ext/cache/mozilla-ca-bundle.sha256 +1 -1
  7. data/ext/couchbase/CMakeLists.txt +24 -11
  8. data/ext/couchbase/cmake/APKBUILD.in +17 -1
  9. data/ext/couchbase/cmake/Bundler.cmake +9 -1
  10. data/ext/couchbase/cmake/Cache.cmake +48 -19
  11. data/ext/couchbase/cmake/CompilerOptions.cmake +3 -1
  12. data/ext/couchbase/cmake/OpenSSL.cmake +10 -2
  13. data/ext/couchbase/cmake/Packaging.cmake +48 -8
  14. data/ext/couchbase/cmake/ThirdPartyDependencies.cmake +43 -1
  15. data/ext/couchbase/cmake/build_config.hxx.in +2 -0
  16. data/ext/couchbase/cmake/couchbase-cxx-client.spec.in +18 -0
  17. data/ext/couchbase/cmake/tarball_glob.txt +10 -0
  18. data/ext/couchbase/core/app_telemetry_meter.cxx +1 -0
  19. data/ext/couchbase/core/app_telemetry_reporter.cxx +45 -43
  20. data/ext/couchbase/core/app_telemetry_reporter.hxx +4 -3
  21. data/ext/couchbase/core/bucket.cxx +128 -13
  22. data/ext/couchbase/core/bucket.hxx +12 -2
  23. data/ext/couchbase/core/cluster.cxx +304 -152
  24. data/ext/couchbase/core/cluster.hxx +32 -0
  25. data/ext/couchbase/core/cluster_credentials.cxx +25 -0
  26. data/ext/couchbase/core/cluster_credentials.hxx +5 -0
  27. data/ext/couchbase/core/cluster_label_listener.cxx +72 -0
  28. data/ext/couchbase/core/cluster_label_listener.hxx +46 -0
  29. data/ext/couchbase/core/cluster_options.hxx +4 -0
  30. data/ext/couchbase/core/deprecation_utils.hxx +26 -0
  31. data/ext/couchbase/core/error.hxx +27 -0
  32. data/ext/couchbase/core/free_form_http_request.hxx +0 -2
  33. data/ext/couchbase/core/http_component.cxx +12 -48
  34. data/ext/couchbase/core/impl/analytics.cxx +3 -2
  35. data/ext/couchbase/core/impl/analytics.hxx +2 -1
  36. data/ext/couchbase/core/impl/analytics_index_manager.cxx +249 -137
  37. data/ext/couchbase/core/impl/binary_collection.cxx +134 -58
  38. data/ext/couchbase/core/impl/bucket_manager.cxx +87 -35
  39. data/ext/couchbase/core/impl/collection.cxx +560 -245
  40. data/ext/couchbase/core/impl/collection_manager.cxx +89 -49
  41. data/ext/couchbase/core/impl/dns_srv_tracker.cxx +4 -4
  42. data/ext/couchbase/core/impl/error.cxx +20 -13
  43. data/ext/couchbase/core/impl/error.hxx +15 -10
  44. data/ext/couchbase/core/impl/get_all_replicas.hxx +1 -1
  45. data/ext/couchbase/core/impl/get_any_replica.hxx +2 -1
  46. data/ext/couchbase/core/impl/get_replica.hxx +2 -0
  47. data/ext/couchbase/core/impl/lookup_in_replica.hxx +1 -1
  48. data/ext/couchbase/core/impl/observability_recorder.cxx +161 -0
  49. data/ext/couchbase/core/impl/observability_recorder.hxx +77 -0
  50. data/ext/couchbase/core/impl/observe_seqno.hxx +2 -0
  51. data/ext/couchbase/core/impl/public_bucket.cxx +31 -7
  52. data/ext/couchbase/core/impl/public_cluster.cxx +107 -19
  53. data/ext/couchbase/core/impl/query.cxx +6 -3
  54. data/ext/couchbase/core/impl/query.hxx +3 -1
  55. data/ext/couchbase/core/impl/query_index_manager.cxx +267 -102
  56. data/ext/couchbase/core/impl/scope.cxx +53 -11
  57. data/ext/couchbase/core/impl/search.cxx +8 -4
  58. data/ext/couchbase/core/impl/search.hxx +6 -2
  59. data/ext/couchbase/core/impl/search_index_manager.cxx +131 -41
  60. data/ext/couchbase/core/impl/with_cancellation.hxx +75 -0
  61. data/ext/couchbase/core/io/config_tracker.cxx +9 -9
  62. data/ext/couchbase/core/io/config_tracker.hxx +2 -1
  63. data/ext/couchbase/core/io/http_command.hxx +98 -49
  64. data/ext/couchbase/core/io/http_context.hxx +2 -0
  65. data/ext/couchbase/core/io/http_session.cxx +23 -10
  66. data/ext/couchbase/core/io/http_session.hxx +17 -9
  67. data/ext/couchbase/core/io/http_session_manager.hxx +163 -228
  68. data/ext/couchbase/core/io/http_traits.hxx +0 -7
  69. data/ext/couchbase/core/io/mcbp_command.hxx +123 -44
  70. data/ext/couchbase/core/io/mcbp_session.cxx +251 -26
  71. data/ext/couchbase/core/io/mcbp_session.hxx +9 -1
  72. data/ext/couchbase/core/io/mcbp_traits.hxx +0 -8
  73. data/ext/couchbase/core/io/streams.cxx +3 -3
  74. data/ext/couchbase/core/io/streams.hxx +3 -2
  75. data/ext/couchbase/core/meta/features.hxx +15 -0
  76. data/ext/couchbase/core/meta/version.cxx +13 -0
  77. data/ext/couchbase/core/meta/version.hxx +3 -0
  78. data/ext/couchbase/core/metrics/constants.hxx +23 -0
  79. data/ext/couchbase/core/metrics/logging_meter.cxx +5 -5
  80. data/ext/couchbase/core/metrics/meter_wrapper.cxx +65 -63
  81. data/ext/couchbase/core/metrics/meter_wrapper.hxx +12 -10
  82. data/ext/couchbase/core/operations/document_analytics.hxx +0 -5
  83. data/ext/couchbase/core/operations/document_append.hxx +0 -4
  84. data/ext/couchbase/core/operations/document_decrement.hxx +0 -5
  85. data/ext/couchbase/core/operations/document_exists.hxx +0 -7
  86. data/ext/couchbase/core/operations/document_get.hxx +0 -7
  87. data/ext/couchbase/core/operations/document_get_all_replicas.hxx +77 -27
  88. data/ext/couchbase/core/operations/document_get_and_lock.hxx +0 -9
  89. data/ext/couchbase/core/operations/document_get_and_touch.hxx +0 -9
  90. data/ext/couchbase/core/operations/document_get_any_replica.hxx +83 -2
  91. data/ext/couchbase/core/operations/document_get_projected.hxx +0 -9
  92. data/ext/couchbase/core/operations/document_increment.hxx +0 -5
  93. data/ext/couchbase/core/operations/document_insert.hxx +0 -4
  94. data/ext/couchbase/core/operations/document_lookup_in.hxx +0 -9
  95. data/ext/couchbase/core/operations/document_lookup_in_all_replicas.hxx +46 -4
  96. data/ext/couchbase/core/operations/document_lookup_in_any_replica.hxx +121 -43
  97. data/ext/couchbase/core/operations/document_mutate_in.hxx +0 -5
  98. data/ext/couchbase/core/operations/document_prepend.hxx +0 -4
  99. data/ext/couchbase/core/operations/document_query.hxx +0 -4
  100. data/ext/couchbase/core/operations/document_remove.hxx +0 -4
  101. data/ext/couchbase/core/operations/document_replace.hxx +0 -4
  102. data/ext/couchbase/core/operations/document_search.hxx +0 -7
  103. data/ext/couchbase/core/operations/document_touch.hxx +0 -7
  104. data/ext/couchbase/core/operations/document_unlock.hxx +0 -6
  105. data/ext/couchbase/core/operations/document_upsert.hxx +0 -4
  106. data/ext/couchbase/core/operations/document_view.cxx +2 -0
  107. data/ext/couchbase/core/operations/document_view.hxx +10 -13
  108. data/ext/couchbase/core/operations/http_noop.hxx +2 -0
  109. data/ext/couchbase/core/operations/management/analytics_dataset_create.hxx +2 -0
  110. data/ext/couchbase/core/operations/management/analytics_dataset_drop.hxx +2 -0
  111. data/ext/couchbase/core/operations/management/analytics_dataset_get_all.hxx +2 -0
  112. data/ext/couchbase/core/operations/management/analytics_dataverse_create.hxx +2 -0
  113. data/ext/couchbase/core/operations/management/analytics_dataverse_drop.hxx +2 -0
  114. data/ext/couchbase/core/operations/management/analytics_get_pending_mutations.hxx +2 -0
  115. data/ext/couchbase/core/operations/management/analytics_index_create.hxx +2 -0
  116. data/ext/couchbase/core/operations/management/analytics_index_drop.hxx +2 -0
  117. data/ext/couchbase/core/operations/management/analytics_index_get_all.hxx +2 -0
  118. data/ext/couchbase/core/operations/management/analytics_link_connect.hxx +2 -0
  119. data/ext/couchbase/core/operations/management/analytics_link_create.hxx +2 -0
  120. data/ext/couchbase/core/operations/management/analytics_link_disconnect.hxx +2 -0
  121. data/ext/couchbase/core/operations/management/analytics_link_drop.hxx +2 -0
  122. data/ext/couchbase/core/operations/management/analytics_link_get_all.hxx +2 -0
  123. data/ext/couchbase/core/operations/management/analytics_link_replace.hxx +2 -0
  124. data/ext/couchbase/core/operations/management/bucket_create.hxx +2 -0
  125. data/ext/couchbase/core/operations/management/bucket_describe.hxx +2 -0
  126. data/ext/couchbase/core/operations/management/bucket_drop.hxx +2 -0
  127. data/ext/couchbase/core/operations/management/bucket_flush.hxx +2 -0
  128. data/ext/couchbase/core/operations/management/bucket_get.hxx +2 -0
  129. data/ext/couchbase/core/operations/management/bucket_get_all.hxx +2 -0
  130. data/ext/couchbase/core/operations/management/bucket_update.hxx +2 -0
  131. data/ext/couchbase/core/operations/management/change_password.hxx +2 -0
  132. data/ext/couchbase/core/operations/management/cluster_describe.hxx +2 -0
  133. data/ext/couchbase/core/operations/management/cluster_developer_preview_enable.hxx +2 -0
  134. data/ext/couchbase/core/operations/management/collection_create.hxx +2 -0
  135. data/ext/couchbase/core/operations/management/collection_drop.hxx +2 -0
  136. data/ext/couchbase/core/operations/management/collection_update.hxx +2 -0
  137. data/ext/couchbase/core/operations/management/collections_manifest_get.hxx +2 -0
  138. data/ext/couchbase/core/operations/management/error_utils.cxx +4 -1
  139. data/ext/couchbase/core/operations/management/eventing_deploy_function.hxx +2 -0
  140. data/ext/couchbase/core/operations/management/eventing_drop_function.hxx +2 -0
  141. data/ext/couchbase/core/operations/management/eventing_get_all_functions.hxx +2 -0
  142. data/ext/couchbase/core/operations/management/eventing_get_function.hxx +2 -0
  143. data/ext/couchbase/core/operations/management/eventing_get_status.hxx +2 -0
  144. data/ext/couchbase/core/operations/management/eventing_pause_function.hxx +2 -0
  145. data/ext/couchbase/core/operations/management/eventing_resume_function.hxx +2 -0
  146. data/ext/couchbase/core/operations/management/eventing_undeploy_function.hxx +2 -0
  147. data/ext/couchbase/core/operations/management/eventing_upsert_function.hxx +2 -0
  148. data/ext/couchbase/core/operations/management/freeform.hxx +2 -0
  149. data/ext/couchbase/core/operations/management/group_drop.hxx +2 -0
  150. data/ext/couchbase/core/operations/management/group_get.hxx +2 -0
  151. data/ext/couchbase/core/operations/management/group_get_all.hxx +2 -0
  152. data/ext/couchbase/core/operations/management/group_upsert.hxx +2 -0
  153. data/ext/couchbase/core/operations/management/query_index_build.hxx +2 -0
  154. data/ext/couchbase/core/operations/management/query_index_build_deferred.hxx +68 -30
  155. data/ext/couchbase/core/operations/management/query_index_create.hxx +2 -0
  156. data/ext/couchbase/core/operations/management/query_index_drop.hxx +2 -0
  157. data/ext/couchbase/core/operations/management/query_index_get_all.hxx +4 -3
  158. data/ext/couchbase/core/operations/management/query_index_get_all_deferred.hxx +2 -1
  159. data/ext/couchbase/core/operations/management/role_get_all.hxx +2 -0
  160. data/ext/couchbase/core/operations/management/scope_create.hxx +2 -0
  161. data/ext/couchbase/core/operations/management/scope_drop.hxx +2 -0
  162. data/ext/couchbase/core/operations/management/scope_get_all.hxx +2 -0
  163. data/ext/couchbase/core/operations/management/search_get_stats.hxx +2 -0
  164. data/ext/couchbase/core/operations/management/search_index_analyze_document.hxx +2 -0
  165. data/ext/couchbase/core/operations/management/search_index_control_ingest.hxx +2 -0
  166. data/ext/couchbase/core/operations/management/search_index_control_plan_freeze.hxx +2 -0
  167. data/ext/couchbase/core/operations/management/search_index_control_query.hxx +2 -0
  168. data/ext/couchbase/core/operations/management/search_index_drop.hxx +2 -0
  169. data/ext/couchbase/core/operations/management/search_index_get.hxx +2 -0
  170. data/ext/couchbase/core/operations/management/search_index_get_all.hxx +2 -0
  171. data/ext/couchbase/core/operations/management/search_index_get_documents_count.hxx +2 -0
  172. data/ext/couchbase/core/operations/management/search_index_get_stats.hxx +2 -0
  173. data/ext/couchbase/core/operations/management/search_index_upsert.hxx +2 -0
  174. data/ext/couchbase/core/operations/management/user_drop.hxx +2 -0
  175. data/ext/couchbase/core/operations/management/user_get.hxx +2 -0
  176. data/ext/couchbase/core/operations/management/user_get_all.hxx +2 -0
  177. data/ext/couchbase/core/operations/management/user_upsert.hxx +2 -0
  178. data/ext/couchbase/core/operations/management/view_index_drop.hxx +2 -0
  179. data/ext/couchbase/core/operations/management/view_index_get.hxx +2 -0
  180. data/ext/couchbase/core/operations/management/view_index_get_all.hxx +2 -0
  181. data/ext/couchbase/core/operations/management/view_index_upsert.hxx +2 -0
  182. data/ext/couchbase/core/operations/operation_traits.hxx +6 -0
  183. data/ext/couchbase/core/operations.hxx +0 -1
  184. data/ext/couchbase/core/operations_fwd.hxx +8 -0
  185. data/ext/couchbase/core/origin.cxx +67 -12
  186. data/ext/couchbase/core/origin.hxx +13 -8
  187. data/ext/couchbase/core/orphan_reporter.cxx +164 -0
  188. data/ext/couchbase/core/orphan_reporter.hxx +65 -0
  189. data/ext/couchbase/core/sasl/CMakeLists.txt +1 -0
  190. data/ext/couchbase/core/sasl/client.cc +6 -0
  191. data/ext/couchbase/core/sasl/mechanism.cc +2 -1
  192. data/ext/couchbase/core/sasl/mechanism.h +2 -1
  193. data/ext/couchbase/core/sasl/oauthbearer/oauthbearer.cc +41 -0
  194. data/ext/couchbase/core/sasl/oauthbearer/oauthbearer.h +47 -0
  195. data/ext/couchbase/core/tls_context_provider.cxx +44 -0
  196. data/ext/couchbase/core/tls_context_provider.hxx +44 -0
  197. data/ext/couchbase/core/tracing/attribute_helpers.hxx +45 -0
  198. data/ext/couchbase/core/tracing/constants.hxx +148 -68
  199. data/ext/couchbase/core/tracing/threshold_logging_options.hxx +0 -3
  200. data/ext/couchbase/core/tracing/threshold_logging_tracer.cxx +122 -170
  201. data/ext/couchbase/core/tracing/tracer_wrapper.cxx +17 -24
  202. data/ext/couchbase/core/tracing/tracer_wrapper.hxx +8 -10
  203. data/ext/couchbase/core/tracing/wrapper_sdk_tracer.cxx +114 -0
  204. data/ext/couchbase/core/tracing/wrapper_sdk_tracer.hxx +85 -0
  205. data/ext/couchbase/core/transactions/attempt_context_impl.cxx +16 -14
  206. data/ext/couchbase/core/transactions/attempt_context_impl.hxx +4 -4
  207. data/ext/couchbase/core/transactions/transactions.cxx +1 -1
  208. data/ext/couchbase/core/transactions/transactions_cleanup.cxx +1 -2
  209. data/ext/couchbase/core/utils/byteswap.hxx +12 -0
  210. data/ext/couchbase/core/utils/concurrent_fixed_priority_queue.hxx +102 -0
  211. data/ext/couchbase/core/utils/connection_string.cxx +2 -0
  212. data/ext/couchbase/couchbase/certificate_authenticator.hxx +1 -0
  213. data/ext/couchbase/couchbase/cluster.hxx +47 -0
  214. data/ext/couchbase/couchbase/cluster_options.hxx +16 -0
  215. data/ext/couchbase/couchbase/collection.hxx +60 -15
  216. data/ext/couchbase/couchbase/error_codes.hxx +48 -48
  217. data/ext/couchbase/couchbase/jwt_authenticator.hxx +52 -0
  218. data/ext/couchbase/couchbase/metrics/meter.hxx +2 -1
  219. data/ext/couchbase/couchbase/metrics/otel_meter.hxx +75 -80
  220. data/ext/couchbase/couchbase/network_options.hxx +19 -0
  221. data/ext/couchbase/couchbase/password_authenticator.hxx +1 -0
  222. data/ext/couchbase/couchbase/tracing/otel_tracer.hxx +15 -17
  223. data/ext/couchbase/couchbase/tracing/request_span.hxx +2 -2
  224. data/ext/couchbase.cxx +4 -0
  225. data/ext/extconf.rb +1 -0
  226. data/ext/rcb_analytics.cxx +157 -47
  227. data/ext/rcb_backend.cxx +118 -71
  228. data/ext/rcb_buckets.cxx +39 -16
  229. data/ext/rcb_collections.cxx +36 -12
  230. data/ext/rcb_crud.cxx +587 -294
  231. data/ext/rcb_hdr_histogram.cxx +219 -0
  232. data/ext/rcb_hdr_histogram.hxx +28 -0
  233. data/ext/rcb_multi.cxx +142 -59
  234. data/ext/rcb_observability.cxx +132 -0
  235. data/ext/rcb_observability.hxx +49 -0
  236. data/ext/rcb_query.cxx +77 -27
  237. data/ext/rcb_search.cxx +92 -31
  238. data/ext/rcb_users.cxx +69 -26
  239. data/ext/rcb_utils.cxx +91 -0
  240. data/ext/rcb_utils.hxx +141 -168
  241. data/ext/rcb_views.cxx +36 -12
  242. data/lib/active_support/cache/couchbase_store.rb +6 -6
  243. data/lib/couchbase/authenticator.rb +14 -0
  244. data/lib/couchbase/binary_collection.rb +37 -22
  245. data/lib/couchbase/bucket.rb +46 -31
  246. data/lib/couchbase/cluster.rb +146 -61
  247. data/lib/couchbase/collection.rb +257 -186
  248. data/lib/couchbase/datastructures/couchbase_list.rb +81 -50
  249. data/lib/couchbase/datastructures/couchbase_map.rb +86 -50
  250. data/lib/couchbase/datastructures/couchbase_queue.rb +64 -38
  251. data/lib/couchbase/datastructures/couchbase_set.rb +57 -41
  252. data/lib/couchbase/deprecations.rb +1 -1
  253. data/lib/couchbase/diagnostics.rb +8 -8
  254. data/lib/couchbase/errors.rb +6 -0
  255. data/lib/couchbase/management/analytics_index_manager.rb +90 -59
  256. data/lib/couchbase/management/bucket_manager.rb +73 -45
  257. data/lib/couchbase/management/collection_manager.rb +86 -43
  258. data/lib/couchbase/management/collection_query_index_manager.rb +56 -33
  259. data/lib/couchbase/management/query_index_manager.rb +88 -36
  260. data/lib/couchbase/management/scope_search_index_manager.rb +119 -52
  261. data/lib/couchbase/management/search_index_manager.rb +401 -178
  262. data/lib/couchbase/management/user_manager.rb +343 -174
  263. data/lib/couchbase/management/view_index_manager.rb +166 -73
  264. data/lib/couchbase/metrics/logging_meter.rb +108 -0
  265. data/lib/couchbase/metrics/logging_value_recorder.rb +50 -0
  266. data/lib/couchbase/metrics/meter.rb +27 -0
  267. data/lib/couchbase/metrics/noop_meter.rb +30 -0
  268. data/lib/couchbase/metrics/noop_value_recorder.rb +27 -0
  269. data/lib/couchbase/metrics/value_recorder.rb +25 -0
  270. data/lib/couchbase/options.rb +69 -3
  271. data/lib/couchbase/protostellar/cluster.rb +3 -0
  272. data/lib/couchbase/scope.rb +62 -48
  273. data/lib/couchbase/search_options.rb +18 -18
  274. data/lib/couchbase/tracing/noop_span.rb +29 -0
  275. data/lib/couchbase/tracing/noop_tracer.rb +29 -0
  276. data/lib/couchbase/tracing/request_span.rb +34 -0
  277. data/lib/couchbase/tracing/request_tracer.rb +28 -0
  278. data/lib/couchbase/tracing/threshold_logging_span.rb +112 -0
  279. data/lib/couchbase/tracing/threshold_logging_tracer.rb +231 -0
  280. data/lib/couchbase/utils/hdr_histogram.rb +55 -0
  281. data/lib/couchbase/utils/observability.rb +257 -0
  282. data/lib/couchbase/utils/observability_constants.rb +200 -0
  283. data/lib/couchbase/utils/stdlib_logger_adapter.rb +1 -3
  284. data/lib/couchbase/version.rb +1 -1
  285. data/lib/couchbase.rb +2 -2
  286. metadata +58 -6
data/ext/rcb_crud.cxx CHANGED
@@ -17,6 +17,8 @@
17
17
 
18
18
  #include <core/cluster.hxx>
19
19
  #include <core/impl/subdoc/path_flags.hxx>
20
+ #include <core/operations/document_append.hxx>
21
+ #include <core/operations/document_decrement.hxx>
20
22
  #include <core/operations/document_exists.hxx>
21
23
  #include <core/operations/document_get.hxx>
22
24
  #include <core/operations/document_get_all_replicas.hxx>
@@ -24,11 +26,18 @@
24
26
  #include <core/operations/document_get_and_touch.hxx>
25
27
  #include <core/operations/document_get_any_replica.hxx>
26
28
  #include <core/operations/document_get_projected.hxx>
29
+ #include <core/operations/document_increment.hxx>
30
+ #include <core/operations/document_insert.hxx>
27
31
  #include <core/operations/document_lookup_in.hxx>
28
32
  #include <core/operations/document_lookup_in_all_replicas.hxx>
29
33
  #include <core/operations/document_lookup_in_any_replica.hxx>
34
+ #include <core/operations/document_mutate_in.hxx>
35
+ #include <core/operations/document_prepend.hxx>
36
+ #include <core/operations/document_remove.hxx>
37
+ #include <core/operations/document_replace.hxx>
30
38
  #include <core/operations/document_touch.hxx>
31
39
  #include <core/operations/document_unlock.hxx>
40
+ #include <core/operations/document_upsert.hxx>
32
41
  #include <core/utils/json.hxx>
33
42
 
34
43
  #include <couchbase/cluster.hxx>
@@ -41,6 +50,7 @@
41
50
  #include <ruby.h>
42
51
 
43
52
  #include "rcb_backend.hxx"
53
+ #include "rcb_observability.hxx"
44
54
  #include "rcb_utils.hxx"
45
55
 
46
56
  namespace couchbase
@@ -77,7 +87,8 @@ cb_Backend_document_get(VALUE self,
77
87
  VALUE scope,
78
88
  VALUE collection,
79
89
  VALUE id,
80
- VALUE options)
90
+ VALUE options,
91
+ VALUE observability_handler)
81
92
  {
82
93
  auto cluster = cb_backend_to_core_api_cluster(self);
83
94
 
@@ -96,12 +107,16 @@ cb_Backend_document_get(VALUE self,
96
107
 
97
108
  core::operations::get_request req{ doc_id };
98
109
  cb_extract_timeout(req, options);
110
+
111
+ auto parent_span = cb_create_parent_span(req, self);
112
+
99
113
  std::promise<core::operations::get_response> promise;
100
114
  auto f = promise.get_future();
101
115
  cluster.execute(req, [promise = std::move(promise)](auto&& resp) mutable {
102
116
  promise.set_value(std::forward<decltype(resp)>(resp));
103
117
  });
104
118
  auto resp = cb_wait_for_future(f);
119
+ cb_add_core_spans(observability_handler, std::move(parent_span), resp.ctx.retry_attempts());
105
120
  if (resp.ctx.ec()) {
106
121
  cb_throw_error(resp.ctx, "unable to fetch document");
107
122
  }
@@ -126,7 +141,8 @@ cb_Backend_document_get_any_replica(VALUE self,
126
141
  VALUE scope,
127
142
  VALUE collection,
128
143
  VALUE id,
129
- VALUE options)
144
+ VALUE options,
145
+ VALUE observability_handler)
130
146
  {
131
147
  auto cluster = cb_backend_to_core_api_cluster(self);
132
148
 
@@ -147,12 +163,15 @@ cb_Backend_document_get_any_replica(VALUE self,
147
163
  cb_extract_timeout(req, options);
148
164
  cb_extract_read_preference(req, options);
149
165
 
166
+ auto parent_span = cb_create_parent_span(req, self);
167
+
150
168
  std::promise<core::operations::get_any_replica_response> promise;
151
169
  auto f = promise.get_future();
152
170
  cluster.execute(req, [promise = std::move(promise)](auto&& resp) mutable {
153
171
  promise.set_value(std::forward<decltype(resp)>(resp));
154
172
  });
155
173
  auto resp = cb_wait_for_future(f);
174
+ cb_add_core_spans(observability_handler, std::move(parent_span), resp.ctx.retry_attempts());
156
175
  if (resp.ctx.ec()) {
157
176
  cb_throw_error(resp.ctx, "unable to get replica of the document");
158
177
  }
@@ -178,7 +197,8 @@ cb_Backend_document_get_all_replicas(VALUE self,
178
197
  VALUE scope,
179
198
  VALUE collection,
180
199
  VALUE id,
181
- VALUE options)
200
+ VALUE options,
201
+ VALUE observability_handler)
182
202
  {
183
203
  auto cluster = cb_backend_to_core_api_cluster(self);
184
204
 
@@ -199,12 +219,15 @@ cb_Backend_document_get_all_replicas(VALUE self,
199
219
  cb_extract_timeout(req, options);
200
220
  cb_extract_read_preference(req, options);
201
221
 
222
+ auto parent_span = cb_create_parent_span(req, self);
223
+
202
224
  std::promise<core::operations::get_all_replicas_response> promise;
203
225
  auto f = promise.get_future();
204
226
  cluster.execute(req, [promise = std::move(promise)](auto&& resp) mutable {
205
227
  promise.set_value(std::forward<decltype(resp)>(resp));
206
228
  });
207
229
  auto resp = cb_wait_for_future(f);
230
+ cb_add_core_spans(observability_handler, std::move(parent_span), resp.ctx.retry_attempts());
208
231
  if (resp.ctx.ec()) {
209
232
  cb_throw_error(resp.ctx, "unable to get all replicas for the document");
210
233
  }
@@ -235,7 +258,8 @@ cb_Backend_document_get_projected(VALUE self,
235
258
  VALUE scope,
236
259
  VALUE collection,
237
260
  VALUE id,
238
- VALUE options)
261
+ VALUE options,
262
+ VALUE observability_handler)
239
263
  {
240
264
  auto cluster = cb_backend_to_core_api_cluster(self);
241
265
 
@@ -257,6 +281,7 @@ cb_Backend_document_get_projected(VALUE self,
257
281
 
258
282
  core::operations::get_projected_request req{ doc_id };
259
283
  cb_extract_timeout(req, options);
284
+ auto parent_span = cb_create_parent_span(req, self);
260
285
  cb_extract_option_bool(req.with_expiry, options, "with_expiry");
261
286
  cb_extract_option_bool(req.preserve_array_indexes, options, "preserve_array_indexes");
262
287
  VALUE projections = Qnil;
@@ -280,6 +305,7 @@ cb_Backend_document_get_projected(VALUE self,
280
305
  promise.set_value(std::forward<decltype(resp)>(resp));
281
306
  });
282
307
  auto resp = cb_wait_for_future(f);
308
+ cb_add_core_spans(observability_handler, std::move(parent_span), resp.ctx.retry_attempts());
283
309
  if (resp.ctx.ec()) {
284
310
  cb_throw_error(resp.ctx, "unable fetch with projections");
285
311
  }
@@ -308,7 +334,8 @@ cb_Backend_document_get_and_lock(VALUE self,
308
334
  VALUE collection,
309
335
  VALUE id,
310
336
  VALUE lock_time,
311
- VALUE options)
337
+ VALUE options,
338
+ VALUE observability_handler)
312
339
  {
313
340
  auto cluster = cb_backend_to_core_api_cluster(self);
314
341
 
@@ -333,12 +360,15 @@ cb_Backend_document_get_and_lock(VALUE self,
333
360
  cb_extract_timeout(req, options);
334
361
  req.lock_time = NUM2UINT(lock_time);
335
362
 
363
+ auto parent_span = cb_create_parent_span(req, self);
364
+
336
365
  std::promise<core::operations::get_and_lock_response> promise;
337
366
  auto f = promise.get_future();
338
367
  cluster.execute(req, [promise = std::move(promise)](auto&& resp) mutable {
339
368
  promise.set_value(std::forward<decltype(resp)>(resp));
340
369
  });
341
370
  auto resp = cb_wait_for_future(f);
371
+ cb_add_core_spans(observability_handler, std::move(parent_span), resp.ctx.retry_attempts());
342
372
  if (resp.ctx.ec()) {
343
373
  cb_throw_error(resp.ctx, "unable lock and fetch");
344
374
  }
@@ -364,7 +394,8 @@ cb_Backend_document_get_and_touch(VALUE self,
364
394
  VALUE collection,
365
395
  VALUE id,
366
396
  VALUE expiry,
367
- VALUE options)
397
+ VALUE options,
398
+ VALUE observability_handler)
368
399
  {
369
400
  auto cluster = cb_backend_to_core_api_cluster(self);
370
401
 
@@ -389,12 +420,15 @@ cb_Backend_document_get_and_touch(VALUE self,
389
420
  auto [type, duration] = unpack_expiry(expiry, false);
390
421
  req.expiry = static_cast<std::uint32_t>(duration.count());
391
422
 
423
+ auto parent_span = cb_create_parent_span(req, self);
424
+
392
425
  std::promise<core::operations::get_and_touch_response> promise;
393
426
  auto f = promise.get_future();
394
427
  cluster.execute(req, [promise = std::move(promise)](auto&& resp) mutable {
395
428
  promise.set_value(std::forward<decltype(resp)>(resp));
396
429
  });
397
430
  auto resp = cb_wait_for_future(f);
431
+ cb_add_core_spans(observability_handler, std::move(parent_span), resp.ctx.retry_attempts());
398
432
  if (resp.ctx.ec()) {
399
433
  cb_throw_error(resp.ctx, "unable fetch and touch");
400
434
  }
@@ -420,7 +454,8 @@ cb_Backend_document_touch(VALUE self,
420
454
  VALUE collection,
421
455
  VALUE id,
422
456
  VALUE expiry,
423
- VALUE options)
457
+ VALUE options,
458
+ VALUE observability_handler)
424
459
  {
425
460
  auto cluster = cb_backend_to_core_api_cluster(self);
426
461
 
@@ -445,12 +480,15 @@ cb_Backend_document_touch(VALUE self,
445
480
  auto [type, duration] = unpack_expiry(expiry, false);
446
481
  req.expiry = static_cast<std::uint32_t>(duration.count());
447
482
 
483
+ auto parent_span = cb_create_parent_span(req, self);
484
+
448
485
  std::promise<core::operations::touch_response> promise;
449
486
  auto f = promise.get_future();
450
487
  cluster.execute(req, [promise = std::move(promise)](auto&& resp) mutable {
451
488
  promise.set_value(std::forward<decltype(resp)>(resp));
452
489
  });
453
490
  auto resp = cb_wait_for_future(f);
491
+ cb_add_core_spans(observability_handler, std::move(parent_span), resp.ctx.retry_attempts());
454
492
  if (resp.ctx.ec()) {
455
493
  cb_throw_error(resp.ctx, "unable to touch");
456
494
  }
@@ -473,7 +511,8 @@ cb_Backend_document_exists(VALUE self,
473
511
  VALUE scope,
474
512
  VALUE collection,
475
513
  VALUE id,
476
- VALUE options)
514
+ VALUE options,
515
+ VALUE observability_handler)
477
516
  {
478
517
  auto cluster = cb_backend_to_core_api_cluster(self);
479
518
 
@@ -496,12 +535,15 @@ cb_Backend_document_exists(VALUE self,
496
535
  core::operations::exists_request req{ doc_id };
497
536
  cb_extract_timeout(req, options);
498
537
 
538
+ auto parent_span = cb_create_parent_span(req, self);
539
+
499
540
  std::promise<core::operations::exists_response> promise;
500
541
  auto f = promise.get_future();
501
542
  cluster.execute(req, [promise = std::move(promise)](auto&& resp) mutable {
502
543
  promise.set_value(std::forward<decltype(resp)>(resp));
503
544
  });
504
545
  auto resp = cb_wait_for_future(f);
546
+ cb_add_core_spans(observability_handler, std::move(parent_span), resp.ctx.retry_attempts());
505
547
  if (resp.ctx.ec() && resp.ctx.ec() != couchbase::errc::key_value::document_not_found) {
506
548
  cb_throw_error(resp.ctx, "unable to exists");
507
549
  }
@@ -531,11 +573,13 @@ cb_Backend_document_unlock(VALUE self,
531
573
  VALUE collection,
532
574
  VALUE id,
533
575
  VALUE cas,
534
- VALUE options)
576
+ VALUE options,
577
+ VALUE observability_handler)
535
578
  {
536
579
  auto cluster = cb_backend_to_core_api_cluster(self);
537
580
 
538
581
  Check_Type(bucket, T_STRING);
582
+ Check_Type(scope, T_STRING);
539
583
  Check_Type(collection, T_STRING);
540
584
  Check_Type(id, T_STRING);
541
585
  if (!NIL_P(options)) {
@@ -548,19 +592,21 @@ cb_Backend_document_unlock(VALUE self,
548
592
  cb_string_new(scope),
549
593
  cb_string_new(collection),
550
594
  cb_string_new(id),
551
-
552
595
  };
553
596
 
554
597
  core::operations::unlock_request req{ doc_id };
555
598
  cb_extract_timeout(req, options);
556
599
  cb_extract_cas(req.cas, cas);
557
600
 
601
+ auto parent_span = cb_create_parent_span(req, self);
602
+
558
603
  std::promise<core::operations::unlock_response> promise;
559
604
  auto f = promise.get_future();
560
605
  cluster.execute(req, [promise = std::move(promise)](auto&& resp) mutable {
561
606
  promise.set_value(std::forward<decltype(resp)>(resp));
562
607
  });
563
608
  auto resp = cb_wait_for_future(f);
609
+ cb_add_core_spans(observability_handler, std::move(parent_span), resp.ctx.retry_attempts());
564
610
  if (resp.ctx.ec()) {
565
611
  cb_throw_error(resp.ctx, "unable to unlock");
566
612
  }
@@ -585,9 +631,10 @@ cb_Backend_document_upsert(VALUE self,
585
631
  VALUE id,
586
632
  VALUE content,
587
633
  VALUE flags,
588
- VALUE options)
634
+ VALUE options,
635
+ VALUE observability_handler)
589
636
  {
590
- auto cluster = cb_backend_to_public_api_cluster(self);
637
+ auto cluster = cb_backend_to_core_api_cluster(self);
591
638
 
592
639
  Check_Type(bucket, T_STRING);
593
640
  Check_Type(scope, T_STRING);
@@ -600,25 +647,51 @@ cb_Backend_document_upsert(VALUE self,
600
647
  }
601
648
 
602
649
  try {
603
- couchbase::upsert_options opts;
604
- set_timeout(opts, options);
605
- set_expiry(opts, options);
606
- set_durability(opts, options);
607
- set_preserve_expiry(opts, options);
608
-
609
- auto f = cluster.bucket(cb_string_new(bucket))
610
- .scope(cb_string_new(scope))
611
- .collection(cb_string_new(collection))
612
- .upsert(cb_string_new(id),
613
- couchbase::codec::encoded_value{ cb_binary_new(content), FIX2UINT(flags) },
614
- opts);
615
-
616
- auto [ctx, resp] = cb_wait_for_future(f);
617
- if (ctx.ec()) {
618
- cb_throw_error(ctx, "unable to upsert");
650
+ core::operations::upsert_request req{
651
+ core::document_id{
652
+ cb_string_new(bucket),
653
+ cb_string_new(scope),
654
+ cb_string_new(collection),
655
+ cb_string_new(id),
656
+ },
657
+ };
658
+ cb_extract_content(req, content);
659
+ cb_extract_flags(req, flags);
660
+ cb_extract_timeout(req, options);
661
+ cb_extract_expiry(req, options);
662
+ cb_extract_durability_level(req, options);
663
+ cb_extract_preserve_expiry(req, options);
664
+
665
+ auto parent_span = cb_create_parent_span(req, self);
666
+
667
+ std::promise<core::operations::upsert_response> promise;
668
+ auto f = promise.get_future();
669
+
670
+ if (const auto legacy_durability = extract_legacy_durability_constraints(options);
671
+ legacy_durability.has_value()) {
672
+ cluster.execute(
673
+ core::operations::upsert_request_with_legacy_durability{
674
+ std::move(req),
675
+ legacy_durability.value().first,
676
+ legacy_durability.value().second,
677
+ },
678
+ [promise = std::move(promise)](auto&& resp) mutable {
679
+ promise.set_value(std::forward<decltype(resp)>(resp));
680
+ });
681
+ } else {
682
+ cluster.execute(std::move(req), [promise = std::move(promise)](auto&& resp) mutable {
683
+ promise.set_value(std::forward<decltype(resp)>(resp));
684
+ });
619
685
  }
620
686
 
621
- return to_mutation_result_value(resp);
687
+ auto resp = cb_wait_for_future(f);
688
+ cb_add_core_spans(observability_handler, std::move(parent_span), resp.ctx.retry_attempts());
689
+ if (resp.ctx.ec()) {
690
+ cb_throw_error(resp.ctx, "unable to upsert");
691
+ }
692
+
693
+ return cb_create_mutation_result(resp);
694
+
622
695
  } catch (const std::system_error& se) {
623
696
  rb_exc_raise(cb_map_error_code(
624
697
  se.code(), fmt::format("failed to perform {}: {}", __func__, se.what()), false));
@@ -635,9 +708,10 @@ cb_Backend_document_append(VALUE self,
635
708
  VALUE collection,
636
709
  VALUE id,
637
710
  VALUE content,
638
- VALUE options)
711
+ VALUE options,
712
+ VALUE observability_handler)
639
713
  {
640
- auto cluster = cb_backend_to_public_api_cluster(self);
714
+ auto cluster = cb_backend_to_core_api_cluster(self);
641
715
 
642
716
  Check_Type(bucket, T_STRING);
643
717
  Check_Type(scope, T_STRING);
@@ -649,22 +723,48 @@ cb_Backend_document_append(VALUE self,
649
723
  }
650
724
 
651
725
  try {
652
- couchbase::append_options opts;
653
- set_timeout(opts, options);
654
- set_durability(opts, options);
655
-
656
- auto f = cluster.bucket(cb_string_new(bucket))
657
- .scope(cb_string_new(scope))
658
- .collection(cb_string_new(collection))
659
- .binary()
660
- .append(cb_string_new(id), cb_binary_new(content), opts);
661
-
662
- auto [ctx, resp] = cb_wait_for_future(f);
663
- if (ctx.ec()) {
664
- cb_throw_error(ctx, "unable to append");
726
+ core::operations::append_request req{
727
+ core::document_id{
728
+ cb_string_new(bucket),
729
+ cb_string_new(scope),
730
+ cb_string_new(collection),
731
+ cb_string_new(id),
732
+ },
733
+ };
734
+ cb_extract_content(req, content);
735
+ cb_extract_timeout(req, options);
736
+ cb_extract_durability_level(req, options);
737
+
738
+ auto parent_span = cb_create_parent_span(req, self);
739
+
740
+ std::promise<core::operations::append_response> promise;
741
+ auto f = promise.get_future();
742
+
743
+ if (const auto legacy_durability = extract_legacy_durability_constraints(options);
744
+ legacy_durability.has_value()) {
745
+ cluster.execute(
746
+ core::operations::append_request_with_legacy_durability{
747
+ std::move(req),
748
+ legacy_durability.value().first,
749
+ legacy_durability.value().second,
750
+ },
751
+ [promise = std::move(promise)](auto&& resp) mutable {
752
+ promise.set_value(std::forward<decltype(resp)>(resp));
753
+ });
754
+ } else {
755
+ cluster.execute(std::move(req), [promise = std::move(promise)](auto&& resp) mutable {
756
+ promise.set_value(std::forward<decltype(resp)>(resp));
757
+ });
665
758
  }
666
759
 
667
- return to_mutation_result_value(resp);
760
+ auto resp = cb_wait_for_future(f);
761
+ cb_add_core_spans(observability_handler, std::move(parent_span), resp.ctx.retry_attempts());
762
+ if (resp.ctx.ec()) {
763
+ cb_throw_error(resp.ctx, "unable to append");
764
+ }
765
+
766
+ return cb_create_mutation_result(resp);
767
+
668
768
  } catch (const std::system_error& se) {
669
769
  rb_exc_raise(cb_map_error_code(
670
770
  se.code(), fmt::format("failed to perform {}: {}", __func__, se.what()), false));
@@ -681,9 +781,10 @@ cb_Backend_document_prepend(VALUE self,
681
781
  VALUE collection,
682
782
  VALUE id,
683
783
  VALUE content,
684
- VALUE options)
784
+ VALUE options,
785
+ VALUE observability_handler)
685
786
  {
686
- auto cluster = cb_backend_to_public_api_cluster(self);
787
+ auto cluster = cb_backend_to_core_api_cluster(self);
687
788
 
688
789
  Check_Type(bucket, T_STRING);
689
790
  Check_Type(scope, T_STRING);
@@ -695,22 +796,47 @@ cb_Backend_document_prepend(VALUE self,
695
796
  }
696
797
 
697
798
  try {
698
- couchbase::prepend_options opts;
699
- set_timeout(opts, options);
700
- set_durability(opts, options);
701
-
702
- auto f = cluster.bucket(cb_string_new(bucket))
703
- .scope(cb_string_new(scope))
704
- .collection(cb_string_new(collection))
705
- .binary()
706
- .prepend(cb_string_new(id), cb_binary_new(content), opts);
707
-
708
- auto [ctx, resp] = cb_wait_for_future(f);
709
- if (ctx.ec()) {
710
- cb_throw_error(ctx, "unable to prepend");
799
+ core::operations::prepend_request req{
800
+ core::document_id{
801
+ cb_string_new(bucket),
802
+ cb_string_new(scope),
803
+ cb_string_new(collection),
804
+ cb_string_new(id),
805
+ },
806
+ };
807
+ cb_extract_content(req, content);
808
+ cb_extract_timeout(req, options);
809
+ cb_extract_durability_level(req, options);
810
+
811
+ auto parent_span = cb_create_parent_span(req, self);
812
+
813
+ std::promise<core::operations::prepend_response> promise;
814
+ auto f = promise.get_future();
815
+
816
+ if (const auto legacy_durability = extract_legacy_durability_constraints(options);
817
+ legacy_durability.has_value()) {
818
+ cluster.execute(
819
+ core::operations::prepend_request_with_legacy_durability{
820
+ std::move(req),
821
+ legacy_durability.value().first,
822
+ legacy_durability.value().second,
823
+ },
824
+ [promise = std::move(promise)](auto&& resp) mutable {
825
+ promise.set_value(std::forward<decltype(resp)>(resp));
826
+ });
827
+ } else {
828
+ cluster.execute(std::move(req), [promise = std::move(promise)](auto&& resp) mutable {
829
+ promise.set_value(std::forward<decltype(resp)>(resp));
830
+ });
831
+ }
832
+
833
+ auto resp = cb_wait_for_future(f);
834
+ cb_add_core_spans(observability_handler, std::move(parent_span), resp.ctx.retry_attempts());
835
+ if (resp.ctx.ec()) {
836
+ cb_throw_error(resp.ctx, "unable to prepend");
711
837
  }
712
838
 
713
- return to_mutation_result_value(resp);
839
+ return cb_create_mutation_result(resp);
714
840
  } catch (const std::system_error& se) {
715
841
  rb_exc_raise(cb_map_error_code(
716
842
  se.code(), fmt::format("failed to perform {}: {}", __func__, se.what()), false));
@@ -728,9 +854,10 @@ cb_Backend_document_replace(VALUE self,
728
854
  VALUE id,
729
855
  VALUE content,
730
856
  VALUE flags,
731
- VALUE options)
857
+ VALUE options,
858
+ VALUE observability_handler)
732
859
  {
733
- auto cluster = cb_backend_to_public_api_cluster(self);
860
+ auto cluster = cb_backend_to_core_api_cluster(self);
734
861
 
735
862
  Check_Type(bucket, T_STRING);
736
863
  Check_Type(scope, T_STRING);
@@ -743,26 +870,51 @@ cb_Backend_document_replace(VALUE self,
743
870
  }
744
871
 
745
872
  try {
746
- couchbase::replace_options opts;
747
- set_timeout(opts, options);
748
- set_expiry(opts, options);
749
- set_durability(opts, options);
750
- set_preserve_expiry(opts, options);
751
- set_cas(opts, options);
752
-
753
- auto f = cluster.bucket(cb_string_new(bucket))
754
- .scope(cb_string_new(scope))
755
- .collection(cb_string_new(collection))
756
- .replace(cb_string_new(id),
757
- couchbase::codec::encoded_value{ cb_binary_new(content), FIX2UINT(flags) },
758
- opts);
759
-
760
- auto [ctx, resp] = cb_wait_for_future(f);
761
- if (ctx.ec()) {
762
- cb_throw_error(ctx, "unable to replace");
873
+ core::operations::replace_request req{
874
+ core::document_id{
875
+ cb_string_new(bucket),
876
+ cb_string_new(scope),
877
+ cb_string_new(collection),
878
+ cb_string_new(id),
879
+ },
880
+ };
881
+ cb_extract_content(req, content);
882
+ cb_extract_flags(req, flags);
883
+ cb_extract_timeout(req, options);
884
+ cb_extract_expiry(req, options);
885
+ cb_extract_durability_level(req, options);
886
+ cb_extract_preserve_expiry(req, options);
887
+ cb_extract_cas(req, options);
888
+
889
+ auto parent_span = cb_create_parent_span(req, self);
890
+
891
+ std::promise<core::operations::replace_response> promise;
892
+ auto f = promise.get_future();
893
+
894
+ if (const auto legacy_durability = extract_legacy_durability_constraints(options);
895
+ legacy_durability.has_value()) {
896
+ cluster.execute(
897
+ core::operations::replace_request_with_legacy_durability{
898
+ std::move(req),
899
+ legacy_durability.value().first,
900
+ legacy_durability.value().second,
901
+ },
902
+ [promise = std::move(promise)](auto&& resp) mutable {
903
+ promise.set_value(std::forward<decltype(resp)>(resp));
904
+ });
905
+ } else {
906
+ cluster.execute(std::move(req), [promise = std::move(promise)](auto&& resp) mutable {
907
+ promise.set_value(std::forward<decltype(resp)>(resp));
908
+ });
763
909
  }
764
910
 
765
- return to_mutation_result_value(resp);
911
+ auto resp = cb_wait_for_future(f);
912
+ cb_add_core_spans(observability_handler, std::move(parent_span), resp.ctx.retry_attempts());
913
+ if (resp.ctx.ec()) {
914
+ cb_throw_error(resp.ctx, "unable to replace");
915
+ }
916
+ return cb_create_mutation_result(resp);
917
+
766
918
  } catch (const std::system_error& se) {
767
919
  rb_exc_raise(cb_map_error_code(
768
920
  se.code(), fmt::format("failed to perform {}: {}", __func__, se.what()), false));
@@ -780,9 +932,10 @@ cb_Backend_document_insert(VALUE self,
780
932
  VALUE id,
781
933
  VALUE content,
782
934
  VALUE flags,
783
- VALUE options)
935
+ VALUE options,
936
+ VALUE observability_handler)
784
937
  {
785
- auto cluster = cb_backend_to_public_api_cluster(self);
938
+ auto cluster = cb_backend_to_core_api_cluster(self);
786
939
 
787
940
  Check_Type(bucket, T_STRING);
788
941
  Check_Type(scope, T_STRING);
@@ -795,24 +948,48 @@ cb_Backend_document_insert(VALUE self,
795
948
  }
796
949
 
797
950
  try {
798
- couchbase::insert_options opts;
799
- set_timeout(opts, options);
800
- set_expiry(opts, options);
801
- set_durability(opts, options);
802
-
803
- auto f = cluster.bucket(cb_string_new(bucket))
804
- .scope(cb_string_new(scope))
805
- .collection(cb_string_new(collection))
806
- .insert(cb_string_new(id),
807
- couchbase::codec::encoded_value{ cb_binary_new(content), FIX2UINT(flags) },
808
- opts);
809
-
810
- auto [ctx, resp] = cb_wait_for_future(f);
811
- if (ctx.ec()) {
812
- cb_throw_error(ctx, "unable to insert");
951
+ core::operations::insert_request req{
952
+ core::document_id{
953
+ cb_string_new(bucket),
954
+ cb_string_new(scope),
955
+ cb_string_new(collection),
956
+ cb_string_new(id),
957
+ },
958
+ };
959
+ cb_extract_content(req, content);
960
+ cb_extract_flags(req, flags);
961
+ cb_extract_timeout(req, options);
962
+ cb_extract_expiry(req, options);
963
+ cb_extract_durability_level(req, options);
964
+
965
+ auto parent_span = cb_create_parent_span(req, self);
966
+
967
+ std::promise<core::operations::insert_response> promise;
968
+ auto f = promise.get_future();
969
+
970
+ if (const auto legacy_durability = extract_legacy_durability_constraints(options);
971
+ legacy_durability.has_value()) {
972
+ cluster.execute(
973
+ core::operations::insert_request_with_legacy_durability{
974
+ std::move(req),
975
+ legacy_durability.value().first,
976
+ legacy_durability.value().second,
977
+ },
978
+ [promise = std::move(promise)](auto&& resp) mutable {
979
+ promise.set_value(std::forward<decltype(resp)>(resp));
980
+ });
981
+ } else {
982
+ cluster.execute(std::move(req), [promise = std::move(promise)](auto&& resp) mutable {
983
+ promise.set_value(std::forward<decltype(resp)>(resp));
984
+ });
985
+ }
986
+ auto resp = cb_wait_for_future(f);
987
+ cb_add_core_spans(observability_handler, std::move(parent_span), resp.ctx.retry_attempts());
988
+ if (resp.ctx.ec()) {
989
+ cb_throw_error(resp.ctx, "unable to insert");
813
990
  }
991
+ return cb_create_mutation_result(resp);
814
992
 
815
- return to_mutation_result_value(resp);
816
993
  } catch (const std::system_error& se) {
817
994
  rb_exc_raise(cb_map_error_code(
818
995
  se.code(), fmt::format("failed to perform {}: {}", __func__, se.what()), false));
@@ -828,9 +1005,10 @@ cb_Backend_document_remove(VALUE self,
828
1005
  VALUE scope,
829
1006
  VALUE collection,
830
1007
  VALUE id,
831
- VALUE options)
1008
+ VALUE options,
1009
+ VALUE observability_handler)
832
1010
  {
833
- auto cluster = cb_backend_to_public_api_cluster(self);
1011
+ auto cluster = cb_backend_to_core_api_cluster(self);
834
1012
 
835
1013
  Check_Type(bucket, T_STRING);
836
1014
  Check_Type(scope, T_STRING);
@@ -841,22 +1019,46 @@ cb_Backend_document_remove(VALUE self,
841
1019
  }
842
1020
 
843
1021
  try {
844
- couchbase::remove_options opts;
845
- set_timeout(opts, options);
846
- set_durability(opts, options);
847
- set_cas(opts, options);
848
-
849
- auto f = cluster.bucket(cb_string_new(bucket))
850
- .scope(cb_string_new(scope))
851
- .collection(cb_string_new(collection))
852
- .remove(cb_string_new(id), opts);
853
-
854
- auto [ctx, resp] = cb_wait_for_future(f);
855
- if (ctx.ec()) {
856
- cb_throw_error(ctx, "unable to remove");
1022
+ core::operations::remove_request req{
1023
+ core::document_id{
1024
+ cb_string_new(bucket),
1025
+ cb_string_new(scope),
1026
+ cb_string_new(collection),
1027
+ cb_string_new(id),
1028
+ },
1029
+ };
1030
+ cb_extract_timeout(req, options);
1031
+ cb_extract_durability_level(req, options);
1032
+ cb_extract_cas(req, options);
1033
+
1034
+ auto parent_span = cb_create_parent_span(req, self);
1035
+
1036
+ std::promise<core::operations::remove_response> promise;
1037
+ auto f = promise.get_future();
1038
+
1039
+ if (const auto legacy_durability = extract_legacy_durability_constraints(options);
1040
+ legacy_durability.has_value()) {
1041
+ cluster.execute(
1042
+ core::operations::remove_request_with_legacy_durability{
1043
+ std::move(req),
1044
+ legacy_durability.value().first,
1045
+ legacy_durability.value().second,
1046
+ },
1047
+ [promise = std::move(promise)](auto&& resp) mutable {
1048
+ promise.set_value(std::forward<decltype(resp)>(resp));
1049
+ });
1050
+ } else {
1051
+ cluster.execute(std::move(req), [promise = std::move(promise)](auto&& resp) mutable {
1052
+ promise.set_value(std::forward<decltype(resp)>(resp));
1053
+ });
857
1054
  }
858
1055
 
859
- return to_mutation_result_value(resp);
1056
+ auto resp = cb_wait_for_future(f);
1057
+ cb_add_core_spans(observability_handler, std::move(parent_span), resp.ctx.retry_attempts());
1058
+ if (resp.ctx.ec()) {
1059
+ cb_throw_error(resp.ctx, "unable to remove");
1060
+ }
1061
+ return cb_create_mutation_result(resp);
860
1062
  } catch (const std::system_error& se) {
861
1063
  rb_exc_raise(cb_map_error_code(
862
1064
  se.code(), fmt::format("failed to perform {}: {}", __func__, se.what()), false));
@@ -872,9 +1074,10 @@ cb_Backend_document_increment(VALUE self,
872
1074
  VALUE scope,
873
1075
  VALUE collection,
874
1076
  VALUE id,
875
- VALUE options)
1077
+ VALUE options,
1078
+ VALUE observability_handler)
876
1079
  {
877
- auto cluster = cb_backend_to_public_api_cluster(self);
1080
+ auto cluster = cb_backend_to_core_api_cluster(self);
878
1081
 
879
1082
  Check_Type(bucket, T_STRING);
880
1083
  Check_Type(scope, T_STRING);
@@ -885,27 +1088,53 @@ cb_Backend_document_increment(VALUE self,
885
1088
  }
886
1089
 
887
1090
  try {
888
- couchbase::increment_options opts;
889
- set_timeout(opts, options);
890
- set_durability(opts, options);
891
- set_expiry(opts, options);
892
- set_delta(opts, options);
893
- set_initial_value(opts, options);
894
-
895
- auto f = cluster.bucket(cb_string_new(bucket))
896
- .scope(cb_string_new(scope))
897
- .collection(cb_string_new(collection))
898
- .binary()
899
- .increment(cb_string_new(id), opts);
900
-
901
- auto [ctx, resp] = cb_wait_for_future(f);
902
- if (ctx.ec()) {
903
- cb_throw_error(ctx, "unable to increment");
1091
+ core::operations::increment_request req{
1092
+ core::document_id{
1093
+ cb_string_new(bucket),
1094
+ cb_string_new(scope),
1095
+ cb_string_new(collection),
1096
+ cb_string_new(id),
1097
+ },
1098
+ };
1099
+
1100
+ cb_extract_timeout(req, options);
1101
+ cb_extract_expiry(req, options);
1102
+ cb_extract_option_uint64(req.delta, options, "delta");
1103
+ cb_extract_option_uint64(req.initial_value, options, "initial_value");
1104
+ cb_extract_durability_level(req, options);
1105
+
1106
+ auto parent_span = cb_create_parent_span(req, self);
1107
+
1108
+ std::promise<core::operations::increment_response> promise;
1109
+ auto f = promise.get_future();
1110
+
1111
+ if (const auto legacy_durability = extract_legacy_durability_constraints(options);
1112
+ legacy_durability.has_value()) {
1113
+ cluster.execute(
1114
+ core::operations::increment_request_with_legacy_durability{
1115
+ std::move(req),
1116
+ legacy_durability.value().first,
1117
+ legacy_durability.value().second,
1118
+ },
1119
+ [promise = std::move(promise)](auto&& resp) mutable {
1120
+ promise.set_value(std::forward<decltype(resp)>(resp));
1121
+ });
1122
+ } else {
1123
+ cluster.execute(std::move(req), [promise = std::move(promise)](auto&& resp) mutable {
1124
+ promise.set_value(std::forward<decltype(resp)>(resp));
1125
+ });
1126
+ }
1127
+
1128
+ auto resp = cb_wait_for_future(f);
1129
+ cb_add_core_spans(observability_handler, std::move(parent_span), resp.ctx.retry_attempts());
1130
+ if (resp.ctx.ec()) {
1131
+ cb_throw_error(resp.ctx, "unable to increment");
904
1132
  }
905
1133
 
906
- VALUE res = to_mutation_result_value(resp);
907
- rb_hash_aset(res, rb_id2sym(rb_intern("content")), ULL2NUM(resp.content()));
1134
+ VALUE res = cb_create_mutation_result(resp);
1135
+ rb_hash_aset(res, rb_id2sym(rb_intern("content")), ULL2NUM(resp.content));
908
1136
  return res;
1137
+
909
1138
  } catch (const std::system_error& se) {
910
1139
  rb_exc_raise(cb_map_error_code(
911
1140
  se.code(), fmt::format("failed to perform {}: {}", __func__, se.what()), false));
@@ -921,9 +1150,10 @@ cb_Backend_document_decrement(VALUE self,
921
1150
  VALUE scope,
922
1151
  VALUE collection,
923
1152
  VALUE id,
924
- VALUE options)
1153
+ VALUE options,
1154
+ VALUE observability_handler)
925
1155
  {
926
- auto cluster = cb_backend_to_public_api_cluster(self);
1156
+ auto cluster = cb_backend_to_core_api_cluster(self);
927
1157
 
928
1158
  Check_Type(bucket, T_STRING);
929
1159
  Check_Type(scope, T_STRING);
@@ -934,26 +1164,51 @@ cb_Backend_document_decrement(VALUE self,
934
1164
  }
935
1165
 
936
1166
  try {
937
- couchbase::decrement_options opts;
938
- set_timeout(opts, options);
939
- set_durability(opts, options);
940
- set_expiry(opts, options);
941
- set_delta(opts, options);
942
- set_initial_value(opts, options);
943
-
944
- auto f = cluster.bucket(cb_string_new(bucket))
945
- .scope(cb_string_new(scope))
946
- .collection(cb_string_new(collection))
947
- .binary()
948
- .decrement(cb_string_new(id), opts);
949
-
950
- auto [ctx, resp] = cb_wait_for_future(f);
951
- if (ctx.ec()) {
952
- cb_throw_error(ctx, "unable to decrement");
1167
+ core::operations::decrement_request req{
1168
+ core::document_id{
1169
+ cb_string_new(bucket),
1170
+ cb_string_new(scope),
1171
+ cb_string_new(collection),
1172
+ cb_string_new(id),
1173
+ },
1174
+ };
1175
+
1176
+ cb_extract_timeout(req, options);
1177
+ cb_extract_expiry(req, options);
1178
+ cb_extract_option_uint64(req.delta, options, "delta");
1179
+ cb_extract_option_uint64(req.initial_value, options, "initial_value");
1180
+ cb_extract_durability_level(req, options);
1181
+
1182
+ auto parent_span = cb_create_parent_span(req, self);
1183
+
1184
+ std::promise<core::operations::decrement_response> promise;
1185
+ auto f = promise.get_future();
1186
+
1187
+ if (const auto legacy_durability = extract_legacy_durability_constraints(options);
1188
+ legacy_durability.has_value()) {
1189
+ cluster.execute(
1190
+ core::operations::decrement_request_with_legacy_durability{
1191
+ std::move(req),
1192
+ legacy_durability.value().first,
1193
+ legacy_durability.value().second,
1194
+ },
1195
+ [promise = std::move(promise)](auto&& resp) mutable {
1196
+ promise.set_value(std::forward<decltype(resp)>(resp));
1197
+ });
1198
+ } else {
1199
+ cluster.execute(std::move(req), [promise = std::move(promise)](auto&& resp) mutable {
1200
+ promise.set_value(std::forward<decltype(resp)>(resp));
1201
+ });
953
1202
  }
954
1203
 
955
- VALUE res = to_mutation_result_value(resp);
956
- rb_hash_aset(res, rb_id2sym(rb_intern("content")), ULL2NUM(resp.content()));
1204
+ auto resp = cb_wait_for_future(f);
1205
+ cb_add_core_spans(observability_handler, std::move(parent_span), resp.ctx.retry_attempts());
1206
+ if (resp.ctx.ec()) {
1207
+ cb_throw_error(resp.ctx, "unable to decrement");
1208
+ }
1209
+
1210
+ VALUE res = cb_create_mutation_result(resp);
1211
+ rb_hash_aset(res, rb_id2sym(rb_intern("content")), ULL2NUM(resp.content));
957
1212
  return res;
958
1213
 
959
1214
  } catch (const std::system_error& se) {
@@ -972,7 +1227,8 @@ cb_Backend_document_lookup_in(VALUE self,
972
1227
  VALUE collection,
973
1228
  VALUE id,
974
1229
  VALUE specs,
975
- VALUE options)
1230
+ VALUE options,
1231
+ VALUE observability_handler)
976
1232
  {
977
1233
  auto cluster = cb_backend_to_core_api_cluster(self);
978
1234
 
@@ -1037,12 +1293,15 @@ cb_Backend_document_lookup_in(VALUE self,
1037
1293
  core::impl::subdoc::build_lookup_in_path_flags(xattr, false) });
1038
1294
  }
1039
1295
 
1296
+ auto parent_span = cb_create_parent_span(req, self);
1297
+
1040
1298
  std::promise<core::operations::lookup_in_response> promise;
1041
1299
  auto f = promise.get_future();
1042
1300
  cluster.execute(req, [promise = std::move(promise)](auto&& resp) mutable {
1043
1301
  promise.set_value(std::forward<decltype(resp)>(resp));
1044
1302
  });
1045
1303
  auto resp = cb_wait_for_future(f);
1304
+ cb_add_core_spans(observability_handler, std::move(parent_span), resp.ctx.retry_attempts());
1046
1305
  if (resp.ctx.ec()) {
1047
1306
  cb_throw_error(resp.ctx, "unable to perform lookup_in operation");
1048
1307
  }
@@ -1098,7 +1357,8 @@ cb_Backend_document_lookup_in_any_replica(VALUE self,
1098
1357
  VALUE collection,
1099
1358
  VALUE id,
1100
1359
  VALUE specs,
1101
- VALUE options)
1360
+ VALUE options,
1361
+ VALUE observability_handler)
1102
1362
  {
1103
1363
 
1104
1364
  auto cluster = cb_backend_to_core_api_cluster(self);
@@ -1163,12 +1423,15 @@ cb_Backend_document_lookup_in_any_replica(VALUE self,
1163
1423
  core::impl::subdoc::build_lookup_in_path_flags(xattr, false) });
1164
1424
  }
1165
1425
 
1426
+ auto parent_span = cb_create_parent_span(req, self);
1427
+
1166
1428
  std::promise<core::operations::lookup_in_any_replica_response> promise;
1167
1429
  auto f = promise.get_future();
1168
1430
  cluster.execute(req, [promise = std::move(promise)](auto&& resp) mutable {
1169
1431
  promise.set_value(std::forward<decltype(resp)>(resp));
1170
1432
  });
1171
1433
  auto resp = cb_wait_for_future(f);
1434
+ cb_add_core_spans(observability_handler, std::move(parent_span), resp.ctx.retry_attempts());
1172
1435
  if (resp.ctx.ec()) {
1173
1436
  cb_throw_error(resp.ctx, "unable to perform lookup_in_any_replica operation");
1174
1437
  }
@@ -1227,7 +1490,8 @@ cb_Backend_document_lookup_in_all_replicas(VALUE self,
1227
1490
  VALUE collection,
1228
1491
  VALUE id,
1229
1492
  VALUE specs,
1230
- VALUE options)
1493
+ VALUE options,
1494
+ VALUE observability_handler)
1231
1495
  {
1232
1496
  auto cluster = cb_backend_to_core_api_cluster(self);
1233
1497
 
@@ -1292,12 +1556,16 @@ cb_Backend_document_lookup_in_all_replicas(VALUE self,
1292
1556
  {},
1293
1557
  core::impl::subdoc::build_lookup_in_path_flags(xattr, false) });
1294
1558
  }
1559
+
1560
+ auto parent_span = cb_create_parent_span(req, self);
1561
+
1295
1562
  std::promise<core::operations::lookup_in_all_replicas_response> promise;
1296
1563
  auto f = promise.get_future();
1297
1564
  cluster.execute(req, [promise = std::move(promise)](auto&& resp) mutable {
1298
1565
  promise.set_value(std::forward<decltype(resp)>(resp));
1299
1566
  });
1300
1567
  auto resp = cb_wait_for_future(f);
1568
+ cb_add_core_spans(observability_handler, std::move(parent_span), resp.ctx.retry_attempts());
1301
1569
  if (resp.ctx.ec()) {
1302
1570
  cb_throw_error(resp.ctx, "unable to perform lookup_in_all_replicas operation");
1303
1571
  }
@@ -1365,9 +1633,10 @@ cb_Backend_document_mutate_in(VALUE self,
1365
1633
  VALUE collection,
1366
1634
  VALUE id,
1367
1635
  VALUE specs,
1368
- VALUE options)
1636
+ VALUE options,
1637
+ VALUE observability_handler)
1369
1638
  {
1370
- auto cluster = cb_backend_to_public_api_cluster(self);
1639
+ auto cluster = cb_backend_to_core_api_cluster(self);
1371
1640
 
1372
1641
  Check_Type(bucket, T_STRING);
1373
1642
  Check_Type(scope, T_STRING);
@@ -1384,15 +1653,22 @@ cb_Backend_document_mutate_in(VALUE self,
1384
1653
  }
1385
1654
 
1386
1655
  try {
1387
- couchbase::mutate_in_options opts;
1388
- set_timeout(opts, options);
1389
- set_durability(opts, options);
1390
- set_expiry(opts, options);
1391
- set_preserve_expiry(opts, options);
1392
- set_access_deleted(opts, options);
1393
- set_create_as_deleted(opts, options);
1394
- set_cas(opts, options);
1395
- set_store_semantics(opts, options);
1656
+ core::operations::mutate_in_request req{
1657
+ core::document_id{
1658
+ cb_string_new(bucket),
1659
+ cb_string_new(scope),
1660
+ cb_string_new(collection),
1661
+ cb_string_new(id),
1662
+ },
1663
+ };
1664
+ cb_extract_timeout(req, options);
1665
+ cb_extract_durability_level(req, options);
1666
+ cb_extract_expiry(req, options);
1667
+ cb_extract_preserve_expiry(req, options);
1668
+ cb_extract_option_bool(req.access_deleted, options, "access_deleted");
1669
+ cb_extract_option_bool(req.create_as_deleted, options, "create_as_deleted");
1670
+ cb_extract_cas(req, options);
1671
+ cb_extract_store_semantics(req, options);
1396
1672
 
1397
1673
  static VALUE xattr_property = rb_id2sym(rb_intern("xattr"));
1398
1674
  static VALUE create_path_property = rb_id2sym(rb_intern("create_path"));
@@ -1402,130 +1678,147 @@ cb_Backend_document_mutate_in(VALUE self,
1402
1678
  static VALUE param_property = rb_id2sym(rb_intern("param"));
1403
1679
 
1404
1680
  couchbase::mutate_in_specs cxx_specs;
1405
- auto entries_size = static_cast<std::size_t>(RARRAY_LEN(specs));
1406
- for (std::size_t i = 0; i < entries_size; ++i) {
1407
- VALUE entry = rb_ary_entry(specs, static_cast<long>(i));
1408
- cb_check_type(entry, T_HASH);
1409
- bool xattr = RTEST(rb_hash_aref(entry, xattr_property));
1410
- bool create_path = RTEST(rb_hash_aref(entry, create_path_property));
1411
- bool expand_macros = RTEST(rb_hash_aref(entry, expand_macros_property));
1412
- VALUE path = rb_hash_aref(entry, path_property);
1413
- cb_check_type(path, T_STRING);
1414
- VALUE operation = rb_hash_aref(entry, opcode_property);
1415
- cb_check_type(operation, T_SYMBOL);
1416
- VALUE param = rb_hash_aref(entry, param_property);
1417
- if (ID operation_id = rb_sym2id(operation); operation_id == rb_intern("dict_add")) {
1418
- cb_check_type(param, T_STRING);
1419
- cxx_specs.push_back(couchbase::mutate_in_specs::insert_raw(
1420
- cb_string_new(path), cb_binary_new(param), expand_macros)
1421
- .xattr(xattr)
1422
- .create_path(create_path));
1423
- } else if (operation_id == rb_intern("dict_upsert")) {
1424
- cb_check_type(param, T_STRING);
1425
-
1426
- cxx_specs.push_back(couchbase::mutate_in_specs::upsert_raw(
1427
- cb_string_new(path), cb_binary_new(param), expand_macros)
1428
- .xattr(xattr)
1429
- .create_path(create_path));
1430
- } else if (operation_id == rb_intern("remove")) {
1431
- cxx_specs.push_back(couchbase::mutate_in_specs::remove(cb_string_new(path)).xattr(xattr));
1432
- } else if (operation_id == rb_intern("replace")) {
1433
- cb_check_type(param, T_STRING);
1434
- cxx_specs.push_back(couchbase::mutate_in_specs::replace_raw(
1435
- cb_string_new(path), cb_binary_new(param), expand_macros)
1436
- .xattr(xattr));
1437
- } else if (operation_id == rb_intern("array_push_last")) {
1438
- cb_check_type(param, T_STRING);
1439
- cxx_specs.push_back(
1440
- couchbase::mutate_in_specs::array_append_raw(cb_string_new(path), cb_binary_new(param))
1441
- .xattr(xattr)
1442
- .create_path(create_path));
1443
- } else if (operation_id == rb_intern("array_push_first")) {
1444
- cb_check_type(param, T_STRING);
1445
- cxx_specs.push_back(
1446
- couchbase::mutate_in_specs::array_prepend_raw(cb_string_new(path), cb_binary_new(param))
1447
- .xattr(xattr)
1448
- .create_path(create_path));
1449
- } else if (operation_id == rb_intern("array_insert")) {
1450
- cb_check_type(param, T_STRING);
1451
- cxx_specs.push_back(
1452
- couchbase::mutate_in_specs::array_insert_raw(cb_string_new(path), cb_binary_new(param))
1453
- .xattr(xattr)
1454
- .create_path(create_path));
1455
- } else if (operation_id == rb_intern("array_add_unique")) {
1456
- cb_check_type(param, T_STRING);
1457
- cxx_specs.push_back(couchbase::mutate_in_specs::array_add_unique_raw(
1458
- cb_string_new(path), cb_binary_new(param), expand_macros)
1459
- .xattr(xattr)
1460
- .create_path(create_path));
1461
- } else if (operation_id == rb_intern("counter")) {
1462
- if (TYPE(param) == T_FIXNUM || TYPE(param) == T_BIGNUM) {
1463
- if (std::int64_t num = NUM2LL(param); num < 0) {
1464
- cxx_specs.push_back(couchbase::mutate_in_specs::decrement(cb_string_new(path), -1 * num)
1465
- .xattr(xattr)
1466
- .create_path(create_path));
1681
+ {
1682
+ auto entries_size = static_cast<std::size_t>(RARRAY_LEN(specs));
1683
+ for (std::size_t i = 0; i < entries_size; ++i) {
1684
+ VALUE entry = rb_ary_entry(specs, static_cast<long>(i));
1685
+ cb_check_type(entry, T_HASH);
1686
+ bool xattr = RTEST(rb_hash_aref(entry, xattr_property));
1687
+ bool create_path = RTEST(rb_hash_aref(entry, create_path_property));
1688
+ bool expand_macros = RTEST(rb_hash_aref(entry, expand_macros_property));
1689
+ VALUE path = rb_hash_aref(entry, path_property);
1690
+ cb_check_type(path, T_STRING);
1691
+ VALUE operation = rb_hash_aref(entry, opcode_property);
1692
+ cb_check_type(operation, T_SYMBOL);
1693
+ VALUE param = rb_hash_aref(entry, param_property);
1694
+ if (ID operation_id = rb_sym2id(operation); operation_id == rb_intern("dict_add")) {
1695
+ cb_check_type(param, T_STRING);
1696
+ cxx_specs.push_back(couchbase::mutate_in_specs::insert_raw(
1697
+ cb_string_new(path), cb_binary_new(param), expand_macros)
1698
+ .xattr(xattr)
1699
+ .create_path(create_path));
1700
+ } else if (operation_id == rb_intern("dict_upsert")) {
1701
+ cb_check_type(param, T_STRING);
1702
+
1703
+ cxx_specs.push_back(couchbase::mutate_in_specs::upsert_raw(
1704
+ cb_string_new(path), cb_binary_new(param), expand_macros)
1705
+ .xattr(xattr)
1706
+ .create_path(create_path));
1707
+ } else if (operation_id == rb_intern("remove")) {
1708
+ cxx_specs.push_back(couchbase::mutate_in_specs::remove(cb_string_new(path)).xattr(xattr));
1709
+ } else if (operation_id == rb_intern("replace")) {
1710
+ cb_check_type(param, T_STRING);
1711
+ cxx_specs.push_back(couchbase::mutate_in_specs::replace_raw(
1712
+ cb_string_new(path), cb_binary_new(param), expand_macros)
1713
+ .xattr(xattr));
1714
+ } else if (operation_id == rb_intern("array_push_last")) {
1715
+ cb_check_type(param, T_STRING);
1716
+ cxx_specs.push_back(
1717
+ couchbase::mutate_in_specs::array_append_raw(cb_string_new(path), cb_binary_new(param))
1718
+ .xattr(xattr)
1719
+ .create_path(create_path));
1720
+ } else if (operation_id == rb_intern("array_push_first")) {
1721
+ cb_check_type(param, T_STRING);
1722
+ cxx_specs.push_back(
1723
+ couchbase::mutate_in_specs::array_prepend_raw(cb_string_new(path), cb_binary_new(param))
1724
+ .xattr(xattr)
1725
+ .create_path(create_path));
1726
+ } else if (operation_id == rb_intern("array_insert")) {
1727
+ cb_check_type(param, T_STRING);
1728
+ cxx_specs.push_back(
1729
+ couchbase::mutate_in_specs::array_insert_raw(cb_string_new(path), cb_binary_new(param))
1730
+ .xattr(xattr)
1731
+ .create_path(create_path));
1732
+ } else if (operation_id == rb_intern("array_add_unique")) {
1733
+ cb_check_type(param, T_STRING);
1734
+ cxx_specs.push_back(couchbase::mutate_in_specs::array_add_unique_raw(
1735
+ cb_string_new(path), cb_binary_new(param), expand_macros)
1736
+ .xattr(xattr)
1737
+ .create_path(create_path));
1738
+ } else if (operation_id == rb_intern("counter")) {
1739
+ if (TYPE(param) == T_FIXNUM || TYPE(param) == T_BIGNUM) {
1740
+ if (std::int64_t num = NUM2LL(param); num < 0) {
1741
+ cxx_specs.push_back(
1742
+ couchbase::mutate_in_specs::decrement(cb_string_new(path), -1 * num)
1743
+ .xattr(xattr)
1744
+ .create_path(create_path));
1745
+ } else {
1746
+ cxx_specs.push_back(couchbase::mutate_in_specs::increment(cb_string_new(path), num)
1747
+ .xattr(xattr)
1748
+ .create_path(create_path));
1749
+ }
1467
1750
  } else {
1468
- cxx_specs.push_back(couchbase::mutate_in_specs::increment(cb_string_new(path), num)
1469
- .xattr(xattr)
1470
- .create_path(create_path));
1751
+ throw ruby_exception(
1752
+ exc_invalid_argument(),
1753
+ rb_sprintf("subdocument counter operation expects number, but given: %+" PRIsVALUE,
1754
+ param));
1471
1755
  }
1756
+ } else if (operation_id == rb_intern("set_doc")) {
1757
+ cb_check_type(param, T_STRING);
1758
+ cxx_specs.push_back(
1759
+ couchbase::mutate_in_specs::replace_raw("", cb_binary_new(param), expand_macros)
1760
+ .xattr(xattr));
1761
+ } else if (operation_id == rb_intern("remove_doc")) {
1762
+ cxx_specs.push_back(couchbase::mutate_in_specs::remove("").xattr(xattr));
1472
1763
  } else {
1473
1764
  throw ruby_exception(
1474
1765
  exc_invalid_argument(),
1475
- rb_sprintf("subdocument counter operation expects number, but given: %+" PRIsVALUE,
1476
- param));
1766
+ rb_sprintf("unsupported operation for subdocument mutation: %+" PRIsVALUE, operation));
1477
1767
  }
1478
- } else if (operation_id == rb_intern("set_doc")) {
1479
- cb_check_type(param, T_STRING);
1480
- cxx_specs.push_back(
1481
- couchbase::mutate_in_specs::replace_raw("", cb_binary_new(param), expand_macros)
1482
- .xattr(xattr));
1483
- } else if (operation_id == rb_intern("remove_doc")) {
1484
- cxx_specs.push_back(couchbase::mutate_in_specs::remove("").xattr(xattr));
1485
- } else {
1486
- throw ruby_exception(
1487
- exc_invalid_argument(),
1488
- rb_sprintf("unsupported operation for subdocument mutation: %+" PRIsVALUE, operation));
1489
1768
  }
1490
1769
  }
1770
+ req.specs = cxx_specs.specs();
1491
1771
 
1492
- auto f = cluster.bucket(cb_string_new(bucket))
1493
- .scope(cb_string_new(scope))
1494
- .collection(cb_string_new(collection))
1495
- .mutate_in(cb_string_new(id), cxx_specs, opts);
1772
+ auto parent_span = cb_create_parent_span(req, self);
1496
1773
 
1497
- auto [ctx, resp] = cb_wait_for_future(f);
1498
- if (ctx.ec()) {
1499
- cb_throw_error(ctx, "unable to mutate_in");
1774
+ std::promise<core::operations::mutate_in_response> promise;
1775
+ auto f = promise.get_future();
1776
+
1777
+ if (const auto legacy_durability = extract_legacy_durability_constraints(options);
1778
+ legacy_durability.has_value()) {
1779
+ cluster.execute(
1780
+ core::operations::mutate_in_request_with_legacy_durability{
1781
+ std::move(req),
1782
+ legacy_durability.value().first,
1783
+ legacy_durability.value().second,
1784
+ },
1785
+ [promise = std::move(promise)](auto&& resp) mutable {
1786
+ promise.set_value(std::forward<decltype(resp)>(resp));
1787
+ });
1788
+ } else {
1789
+ cluster.execute(std::move(req), [promise = std::move(promise)](auto&& resp) mutable {
1790
+ promise.set_value(std::forward<decltype(resp)>(resp));
1791
+ });
1792
+ }
1793
+
1794
+ auto resp = cb_wait_for_future(f);
1795
+ cb_add_core_spans(observability_handler, std::move(parent_span), resp.ctx.retry_attempts());
1796
+ if (resp.ctx.ec()) {
1797
+ cb_throw_error(resp.ctx, "unable to mutate_in");
1500
1798
  }
1501
1799
 
1502
1800
  static VALUE deleted_property = rb_id2sym(rb_intern("deleted"));
1503
1801
  static VALUE fields_property = rb_id2sym(rb_intern("fields"));
1504
1802
  static VALUE index_property = rb_id2sym(rb_intern("index"));
1505
- static VALUE cas_property = rb_id2sym(rb_intern("cas"));
1506
1803
  static VALUE value_property = rb_id2sym(rb_intern("value"));
1507
1804
 
1508
- VALUE res = to_mutation_result_value(resp);
1509
- rb_hash_aset(res, deleted_property, resp.is_deleted() ? Qtrue : Qfalse);
1510
- if (!ctx.ec()) {
1511
- rb_hash_aset(res, cas_property, cb_cas_to_num(resp.cas()));
1512
-
1513
- VALUE fields = rb_ary_new_capa(static_cast<long>(entries_size));
1514
- rb_hash_aset(res, fields_property, fields);
1515
- for (std::size_t i = 0; i < entries_size; ++i) {
1516
- VALUE entry = rb_hash_new();
1517
- rb_hash_aset(entry, index_property, ULL2NUM(i));
1518
- rb_hash_aset(entry,
1519
- path_property,
1520
- rb_hash_aref(rb_ary_entry(specs, static_cast<long>(i)), path_property));
1521
- if (resp.has_value(i)) {
1522
- auto value = resp.content_as<tao::json::value>(i);
1523
- rb_hash_aset(entry, value_property, cb_str_new(core::utils::json::generate(value)));
1524
- }
1525
- rb_ary_store(fields, static_cast<long>(i), entry);
1805
+ VALUE res = cb_create_mutation_result(resp);
1806
+ rb_hash_aset(res, deleted_property, resp.deleted ? Qtrue : Qfalse);
1807
+ VALUE fields = rb_ary_new_capa(static_cast<long>(resp.fields.size()));
1808
+ rb_hash_aset(res, fields_property, fields);
1809
+ for (std::size_t i = 0; i < resp.fields.size(); ++i) {
1810
+ VALUE entry = rb_hash_new();
1811
+ rb_hash_aset(entry, index_property, ULL2NUM(i));
1812
+ rb_hash_aset(entry,
1813
+ path_property,
1814
+ rb_hash_aref(rb_ary_entry(specs, static_cast<long>(i)), path_property));
1815
+ if (!resp.fields.at(i).value.empty()) {
1816
+ rb_hash_aset(entry, value_property, cb_str_new(resp.fields.at(i).value));
1526
1817
  }
1818
+ rb_ary_store(fields, static_cast<long>(i), entry);
1527
1819
  }
1528
1820
  return res;
1821
+
1529
1822
  } catch (const std::system_error& se) {
1530
1823
  rb_exc_raise(cb_map_error_code(
1531
1824
  se.code(), fmt::format("failed to perform {}: {}", __func__, se.what()), false));
@@ -1540,28 +1833,28 @@ cb_Backend_document_mutate_in(VALUE self,
1540
1833
  void
1541
1834
  init_crud(VALUE cBackend)
1542
1835
  {
1543
- rb_define_method(cBackend, "document_get", cb_Backend_document_get, 5);
1544
- rb_define_method(cBackend, "document_get_any_replica", cb_Backend_document_get_any_replica, 5);
1545
- rb_define_method(cBackend, "document_get_all_replicas", cb_Backend_document_get_all_replicas, 5);
1546
- rb_define_method(cBackend, "document_get_projected", cb_Backend_document_get_projected, 5);
1547
- rb_define_method(cBackend, "document_get_and_lock", cb_Backend_document_get_and_lock, 6);
1548
- rb_define_method(cBackend, "document_get_and_touch", cb_Backend_document_get_and_touch, 6);
1549
- rb_define_method(cBackend, "document_insert", cb_Backend_document_insert, 7);
1550
- rb_define_method(cBackend, "document_replace", cb_Backend_document_replace, 7);
1551
- rb_define_method(cBackend, "document_upsert", cb_Backend_document_upsert, 7);
1552
- rb_define_method(cBackend, "document_append", cb_Backend_document_append, 6);
1553
- rb_define_method(cBackend, "document_prepend", cb_Backend_document_prepend, 6);
1554
- rb_define_method(cBackend, "document_remove", cb_Backend_document_remove, 5);
1555
- rb_define_method(cBackend, "document_lookup_in", cb_Backend_document_lookup_in, 6);
1836
+ rb_define_method(cBackend, "document_get", cb_Backend_document_get, 6);
1837
+ rb_define_method(cBackend, "document_get_any_replica", cb_Backend_document_get_any_replica, 6);
1838
+ rb_define_method(cBackend, "document_get_all_replicas", cb_Backend_document_get_all_replicas, 6);
1839
+ rb_define_method(cBackend, "document_get_projected", cb_Backend_document_get_projected, 6);
1840
+ rb_define_method(cBackend, "document_get_and_lock", cb_Backend_document_get_and_lock, 7);
1841
+ rb_define_method(cBackend, "document_get_and_touch", cb_Backend_document_get_and_touch, 7);
1842
+ rb_define_method(cBackend, "document_insert", cb_Backend_document_insert, 8);
1843
+ rb_define_method(cBackend, "document_replace", cb_Backend_document_replace, 8);
1844
+ rb_define_method(cBackend, "document_upsert", cb_Backend_document_upsert, 8);
1845
+ rb_define_method(cBackend, "document_append", cb_Backend_document_append, 7);
1846
+ rb_define_method(cBackend, "document_prepend", cb_Backend_document_prepend, 7);
1847
+ rb_define_method(cBackend, "document_remove", cb_Backend_document_remove, 6);
1848
+ rb_define_method(cBackend, "document_lookup_in", cb_Backend_document_lookup_in, 7);
1556
1849
  rb_define_method(
1557
- cBackend, "document_lookup_in_any_replica", cb_Backend_document_lookup_in_any_replica, 6);
1850
+ cBackend, "document_lookup_in_any_replica", cb_Backend_document_lookup_in_any_replica, 7);
1558
1851
  rb_define_method(
1559
- cBackend, "document_lookup_in_all_replicas", cb_Backend_document_lookup_in_all_replicas, 6);
1560
- rb_define_method(cBackend, "document_mutate_in", cb_Backend_document_mutate_in, 6);
1561
- rb_define_method(cBackend, "document_touch", cb_Backend_document_touch, 6);
1562
- rb_define_method(cBackend, "document_exists", cb_Backend_document_exists, 5);
1563
- rb_define_method(cBackend, "document_unlock", cb_Backend_document_unlock, 6);
1564
- rb_define_method(cBackend, "document_increment", cb_Backend_document_increment, 5);
1565
- rb_define_method(cBackend, "document_decrement", cb_Backend_document_decrement, 5);
1852
+ cBackend, "document_lookup_in_all_replicas", cb_Backend_document_lookup_in_all_replicas, 7);
1853
+ rb_define_method(cBackend, "document_mutate_in", cb_Backend_document_mutate_in, 7);
1854
+ rb_define_method(cBackend, "document_touch", cb_Backend_document_touch, 7);
1855
+ rb_define_method(cBackend, "document_exists", cb_Backend_document_exists, 6);
1856
+ rb_define_method(cBackend, "document_unlock", cb_Backend_document_unlock, 7);
1857
+ rb_define_method(cBackend, "document_increment", cb_Backend_document_increment, 6);
1858
+ rb_define_method(cBackend, "document_decrement", cb_Backend_document_decrement, 6);
1566
1859
  }
1567
1860
  } // namespace couchbase::ruby