couchbase 3.0.2 → 3.0.3

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 (136) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/ext/CMakeLists.txt +3 -0
  4. data/ext/build_version.hxx.in +1 -1
  5. data/ext/cmake/CompilerWarnings.cmake +1 -0
  6. data/ext/cmake/PreventInSourceBuilds.cmake +4 -1
  7. data/ext/couchbase/bucket.hxx +28 -2
  8. data/ext/couchbase/cluster.hxx +8 -2
  9. data/ext/couchbase/couchbase.cxx +955 -511
  10. data/ext/couchbase/error_context/analytics.hxx +46 -0
  11. data/ext/couchbase/error_context/http.hxx +44 -0
  12. data/ext/couchbase/error_context/key_value.hxx +47 -0
  13. data/ext/couchbase/error_context/query.hxx +46 -0
  14. data/ext/couchbase/error_context/search.hxx +47 -0
  15. data/ext/couchbase/error_context/view.hxx +47 -0
  16. data/ext/couchbase/io/dns_codec.hxx +1 -2
  17. data/ext/couchbase/io/http_command.hxx +16 -3
  18. data/ext/couchbase/io/http_context.hxx +1 -1
  19. data/ext/couchbase/io/http_session.hxx +12 -6
  20. data/ext/couchbase/io/http_session_manager.hxx +25 -24
  21. data/ext/couchbase/io/mcbp_session.hxx +8 -2
  22. data/ext/couchbase/io/retry_context.hxx +1 -1
  23. data/ext/couchbase/operations/analytics_dataset_create.hxx +19 -12
  24. data/ext/couchbase/operations/analytics_dataset_drop.hxx +18 -10
  25. data/ext/couchbase/operations/analytics_dataset_get_all.hxx +16 -10
  26. data/ext/couchbase/operations/analytics_dataverse_create.hxx +18 -11
  27. data/ext/couchbase/operations/analytics_dataverse_drop.hxx +17 -11
  28. data/ext/couchbase/operations/analytics_get_pending_mutations.hxx +17 -10
  29. data/ext/couchbase/operations/analytics_index_create.hxx +17 -11
  30. data/ext/couchbase/operations/analytics_index_drop.hxx +16 -10
  31. data/ext/couchbase/operations/analytics_index_get_all.hxx +14 -10
  32. data/ext/couchbase/operations/analytics_link_connect.hxx +15 -9
  33. data/ext/couchbase/operations/analytics_link_disconnect.hxx +16 -10
  34. data/ext/couchbase/operations/bucket_create.hxx +33 -10
  35. data/ext/couchbase/operations/bucket_drop.hxx +9 -8
  36. data/ext/couchbase/operations/bucket_flush.hxx +8 -8
  37. data/ext/couchbase/operations/bucket_get.hxx +15 -10
  38. data/ext/couchbase/operations/bucket_get_all.hxx +14 -7
  39. data/ext/couchbase/operations/bucket_settings.hxx +16 -0
  40. data/ext/couchbase/operations/bucket_update.hxx +32 -10
  41. data/ext/couchbase/operations/cluster_developer_preview_enable.hxx +6 -6
  42. data/ext/couchbase/operations/collection_create.hxx +19 -13
  43. data/ext/couchbase/operations/collection_drop.hxx +18 -12
  44. data/ext/couchbase/operations/collections_manifest_get.hxx +5 -10
  45. data/ext/couchbase/operations/document_analytics.hxx +39 -17
  46. data/ext/couchbase/operations/document_append.hxx +5 -10
  47. data/ext/couchbase/operations/document_decrement.hxx +5 -10
  48. data/ext/couchbase/operations/document_exists.hxx +4 -6
  49. data/ext/couchbase/operations/document_get.hxx +6 -10
  50. data/ext/couchbase/operations/document_get_and_lock.hxx +4 -9
  51. data/ext/couchbase/operations/document_get_and_touch.hxx +4 -9
  52. data/ext/couchbase/operations/document_get_projected.hxx +21 -14
  53. data/ext/couchbase/operations/document_increment.hxx +5 -10
  54. data/ext/couchbase/operations/document_insert.hxx +5 -10
  55. data/ext/couchbase/operations/document_lookup_in.hxx +4 -9
  56. data/ext/couchbase/operations/document_mutate_in.hxx +7 -12
  57. data/ext/couchbase/operations/document_prepend.hxx +5 -10
  58. data/ext/couchbase/operations/document_query.hxx +45 -28
  59. data/ext/couchbase/operations/document_remove.hxx +5 -10
  60. data/ext/couchbase/operations/document_replace.hxx +5 -10
  61. data/ext/couchbase/operations/document_search.hxx +37 -16
  62. data/ext/couchbase/operations/document_touch.hxx +4 -9
  63. data/ext/couchbase/operations/document_unlock.hxx +4 -9
  64. data/ext/couchbase/operations/document_upsert.hxx +5 -10
  65. data/ext/couchbase/operations/document_view.hxx +29 -13
  66. data/ext/couchbase/operations/group_drop.hxx +7 -7
  67. data/ext/couchbase/operations/group_get.hxx +14 -10
  68. data/ext/couchbase/operations/group_get_all.hxx +14 -8
  69. data/ext/couchbase/operations/group_upsert.hxx +15 -9
  70. data/ext/couchbase/operations/http_noop.hxx +5 -5
  71. data/ext/couchbase/operations/mcbp_noop.hxx +3 -9
  72. data/ext/couchbase/operations/query_index_build_deferred.hxx +15 -9
  73. data/ext/couchbase/operations/query_index_create.hxx +16 -10
  74. data/ext/couchbase/operations/query_index_drop.hxx +16 -10
  75. data/ext/couchbase/operations/query_index_get_all.hxx +13 -7
  76. data/ext/couchbase/operations/role_get_all.hxx +14 -8
  77. data/ext/couchbase/operations/scope_create.hxx +19 -13
  78. data/ext/couchbase/operations/scope_drop.hxx +17 -11
  79. data/ext/couchbase/operations/scope_get_all.hxx +15 -10
  80. data/ext/couchbase/operations/search_get_stats.hxx +5 -5
  81. data/ext/couchbase/operations/search_index_analyze_document.hxx +25 -13
  82. data/ext/couchbase/operations/search_index_control_ingest.hxx +23 -11
  83. data/ext/couchbase/operations/search_index_control_plan_freeze.hxx +23 -11
  84. data/ext/couchbase/operations/search_index_control_query.hxx +23 -11
  85. data/ext/couchbase/operations/search_index_drop.hxx +22 -10
  86. data/ext/couchbase/operations/search_index_get.hxx +22 -10
  87. data/ext/couchbase/operations/search_index_get_all.hxx +13 -7
  88. data/ext/couchbase/operations/search_index_get_documents_count.hxx +24 -13
  89. data/ext/couchbase/operations/search_index_get_stats.hxx +16 -10
  90. data/ext/couchbase/operations/search_index_upsert.hxx +23 -11
  91. data/ext/couchbase/operations/user_drop.hxx +8 -8
  92. data/ext/couchbase/operations/user_get.hxx +14 -10
  93. data/ext/couchbase/operations/user_get_all.hxx +14 -8
  94. data/ext/couchbase/operations/user_upsert.hxx +15 -9
  95. data/ext/couchbase/operations/view_index_drop.hxx +7 -7
  96. data/ext/couchbase/operations/view_index_get.hxx +15 -9
  97. data/ext/couchbase/operations/view_index_get_all.hxx +15 -9
  98. data/ext/couchbase/operations/view_index_upsert.hxx +8 -8
  99. data/ext/couchbase/origin.hxx +1 -0
  100. data/ext/couchbase/platform/terminate_handler.cc +12 -8
  101. data/ext/couchbase/protocol/client_request.hxx +2 -1
  102. data/ext/couchbase/protocol/client_response.hxx +18 -15
  103. data/ext/couchbase/protocol/cmd_exists.hxx +1 -0
  104. data/ext/couchbase/protocol/cmd_get.hxx +1 -1
  105. data/ext/couchbase/protocol/cmd_mutate_in.hxx +3 -4
  106. data/ext/couchbase/protocol/enhanced_error_info.hxx +28 -0
  107. data/ext/couchbase/utils/connection_string.hxx +1 -1
  108. data/ext/couchbase/version.hxx +1 -1
  109. data/ext/extconf.rb +1 -1
  110. data/ext/test/test_native_binary_operations.cxx +18 -18
  111. data/ext/test/test_native_diagnostics.cxx +2 -2
  112. data/ext/test/test_native_trivial_crud.cxx +2 -2
  113. data/ext/third_party/json/include/tao/json/external/pegtl/internal/file_reader.hpp +1 -5
  114. data/lib/active_support/cache/couchbase_store.rb +362 -0
  115. data/lib/couchbase.rb +2 -0
  116. data/lib/couchbase/authenticator.rb +26 -0
  117. data/lib/couchbase/binary_collection.rb +1 -0
  118. data/lib/couchbase/bucket.rb +1 -0
  119. data/lib/couchbase/cluster.rb +51 -27
  120. data/lib/couchbase/collection.rb +19 -4
  121. data/lib/couchbase/collection_options.rb +10 -0
  122. data/lib/couchbase/configuration.rb +57 -0
  123. data/lib/couchbase/datastructures.rb +6 -0
  124. data/lib/couchbase/errors.rb +111 -3
  125. data/lib/couchbase/management.rb +27 -0
  126. data/lib/couchbase/management/bucket_manager.rb +9 -2
  127. data/lib/couchbase/management/collection_manager.rb +1 -1
  128. data/lib/couchbase/management/user_manager.rb +18 -2
  129. data/lib/couchbase/options.rb +33 -23
  130. data/lib/couchbase/railtie.rb +45 -0
  131. data/lib/couchbase/scope.rb +44 -3
  132. data/lib/couchbase/utils.rb +21 -0
  133. data/lib/couchbase/utils/time.rb +52 -0
  134. data/lib/couchbase/version.rb +1 -1
  135. data/lib/rails/generators/couchbase/config/config_generator.rb +27 -0
  136. metadata +19 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4674765d2d910949acdc81040062ecdcf6b5089297e33bbfc02c3c1cf705b60c
4
- data.tar.gz: d24c030c9b3a6620d8b7740af911a5b8640f6d98b857719e50df7981a4be46ce
3
+ metadata.gz: 850654b24f508816010fe6558dc0b5e50bd6a4a54667c17d929988762ea836c6
4
+ data.tar.gz: 4e6f334a34c80ec64fa15a8fbf16f22a913bded0e10aed76e5870db6ded5a17b
5
5
  SHA512:
6
- metadata.gz: 97e0ea2efa94117e1e3738951c86cd1d3176a5304de3e70221916fa3245c96d5d932e10558eb254e06a3047e2adaa3cc97c8e77290876d7422a3d62ecec91fe6
7
- data.tar.gz: dd31e90a9bf872e1edcc03eab14796122bb201e84a42d7bb68d8630bed55612deb01ebc363465209316d5d2030e210bf404035491f60e259d216240937216b7b
6
+ metadata.gz: d1e7b161fe8fbca8d8ca8d524014f6be1eb0fd7dffb3295f18ee6aa2b20997c2ff0277b90011a3330892e3173038b0667e73e791b945ee7490bda7a9abebe52d
7
+ data.tar.gz: b72cb74eb7f1a34fd0ed0421af78d1a322f2dde47f615466cf9aaf80e3a5f7f4420110650b400a515f4b0f4ada98c388b00b0feff5b416e1216e59c58299500f
data/README.md CHANGED
@@ -20,12 +20,12 @@ Please attach version information to ticket/post. To obtain this information use
20
20
 
21
21
  ## Installation
22
22
 
23
- The library tested with the MRI 2.5, 2.6 and 2.7. Supported platforms are Linux and MacOS.
23
+ The library tested with the MRI 2.5, 2.6, 2.7 and 3.0. Supported platforms are Linux and MacOS.
24
24
 
25
25
  Add this line to your application's Gemfile:
26
26
 
27
27
  ```ruby
28
- gem "couchbase", "3.0.2"
28
+ gem "couchbase", "3.0.3"
29
29
  ```
30
30
 
31
31
  And then execute:
data/ext/CMakeLists.txt CHANGED
@@ -6,6 +6,9 @@ include(cmake/StandardProjectSettings.cmake)
6
6
  # 'library' to set the c++ standard / compile-time options requested
7
7
  add_library(project_options INTERFACE)
8
8
  target_compile_features(project_options INTERFACE cxx_std_17)
9
+ if(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
10
+ target_compile_options(project_options INTERFACE -fdeclspec)
11
+ endif()
9
12
 
10
13
  # 'library' to use the warnings specified in CompilerWarnings.cmake
11
14
  add_library(project_warnings INTERFACE)
@@ -26,5 +26,5 @@ constexpr auto BACKEND_CXX_COMPILER = "@CMAKE_CXX_COMPILER_ID@ @CMAKE_CXX_COMPIL
26
26
  constexpr auto BACKEND_C_COMPILER = "@CMAKE_C_COMPILER_ID@ @CMAKE_C_COMPILER_VERSION@";
27
27
  constexpr auto BACKEND_SYSTEM = "@CMAKE_SYSTEM@";
28
28
  constexpr auto BACKEND_SYSTEM_PROCESSOR = "@CMAKE_SYSTEM_PROCESSOR@";
29
- constexpr auto BACKEND_GIT_REVISION = "9d2e94b96a3537e8bfc8c9ca88a1c855db6ec977";
29
+ constexpr auto BACKEND_GIT_REVISION = "bcb5da39fd4dfd3bd7ce917abc89faf1fbcd7d5f";
30
30
  } // namespace couchbase
@@ -66,6 +66,7 @@ function(set_project_warnings project_name)
66
66
  -Wduplicated-branches # warn if if / else branches have duplicated code
67
67
  -Wlogical-op # warn about logical operations being used where bitwise were probably wanted
68
68
  -Wuseless-cast # warn if you perform a cast to the same type
69
+ -Wdeprecated-declarations # warn if [[deprecated]] elements being used
69
70
  )
70
71
 
71
72
  if(MSVC)
@@ -5,6 +5,9 @@ function(AssureOutOfSourceBuilds)
5
5
  get_filename_component(srcdir "${CMAKE_SOURCE_DIR}" REALPATH)
6
6
  get_filename_component(bindir "${CMAKE_BINARY_DIR}" REALPATH)
7
7
 
8
+ message(STATUS "CMAKE_SOURCE_DIR=${srcdir}")
9
+ message(STATUS "CMAKE_BINARY_DIR=${bindir}")
10
+
8
11
  # disallow in-source builds
9
12
  if("${srcdir}" STREQUAL "${bindir}")
10
13
  message("######################################################")
@@ -15,4 +18,4 @@ function(AssureOutOfSourceBuilds)
15
18
  endif()
16
19
  endfunction()
17
20
 
18
- assureoutofsourcebuilds()
21
+ AssureOutOfSourceBuilds()
@@ -242,7 +242,28 @@ class bucket : public std::enable_shared_from_this<bucket>
242
242
  auto cmd = std::make_shared<operations::mcbp_command<bucket, Request>>(ctx_, shared_from_this(), request);
243
243
  cmd->start([cmd, handler = std::forward<Handler>(handler)](std::error_code ec, std::optional<io::mcbp_message> msg) mutable {
244
244
  using encoded_response_type = typename Request::encoded_response_type;
245
- handler(make_response(ec, cmd->request, msg ? encoded_response_type(*msg) : encoded_response_type{}));
245
+ auto resp = msg ? encoded_response_type(*msg) : encoded_response_type{};
246
+ error_context::key_value ctx{};
247
+ ctx.id = cmd->request.id;
248
+ ctx.opaque = resp.opaque();
249
+ ctx.ec = ec;
250
+ if (ctx.ec && ctx.opaque == 0) {
251
+ ctx.opaque = cmd->request.opaque;
252
+ }
253
+ if (msg) {
254
+ ctx.status_code = resp.status();
255
+ }
256
+ ctx.retry_attempts = cmd->request.retries.retry_attempts;
257
+ ctx.retry_reasons = cmd->request.retries.reasons;
258
+ if (cmd->session_) {
259
+ ctx.last_dispatched_from = cmd->session_->local_address();
260
+ ctx.last_dispatched_to = cmd->session_->remote_address();
261
+ if (msg) {
262
+ ctx.error_map_info = cmd->session_->decode_error_code(msg->header.status());
263
+ }
264
+ }
265
+ ctx.enhanced_error_info = resp.error_info();
266
+ handler(make_response(std::move(ctx), cmd->request, std::move(resp)));
246
267
  });
247
268
  if (config_) {
248
269
  map_and_send(cmd);
@@ -287,7 +308,12 @@ class bucket : public std::enable_shared_from_this<bucket>
287
308
  cmd->manager_, cmd, io::retry_reason::node_not_available, std::make_error_code(error::common_errc::request_canceled));
288
309
  }
289
310
  }
290
- cmd->send_to(sessions_.at(static_cast<std::size_t>(index)));
311
+ auto session = sessions_.at(static_cast<std::size_t>(index));
312
+ if (session->is_stopped()) {
313
+ return io::retry_orchestrator::maybe_retry(
314
+ cmd->manager_, cmd, io::retry_reason::node_not_available, std::make_error_code(error::common_errc::request_canceled));
315
+ }
316
+ cmd->send_to(session);
291
317
  }
292
318
 
293
319
  template<typename Request>
@@ -151,7 +151,11 @@ class cluster
151
151
  {
152
152
  auto bucket = buckets_.find(request.id.bucket);
153
153
  if (bucket == buckets_.end()) {
154
- return handler(operations::make_response(std::make_error_code(error::common_errc::bucket_not_found), request, {}));
154
+ error_context::key_value ctx{};
155
+ ctx.id = request.id;
156
+ ctx.ec = std::make_error_code(error::common_errc::bucket_not_found);
157
+ using response_type = typename Request::encoded_response_type;
158
+ return handler(operations::make_response(std::move(ctx), request, response_type{}));
155
159
  }
156
160
  return bucket->second->execute(request, std::forward<Handler>(handler));
157
161
  }
@@ -161,7 +165,9 @@ class cluster
161
165
  {
162
166
  auto session = session_manager_->check_out(Request::type, origin_.credentials());
163
167
  if (!session) {
164
- return handler(operations::make_response(std::make_error_code(error::common_errc::service_not_available), request, {}));
168
+ typename Request::error_context_type ctx{};
169
+ ctx.ec = std::make_error_code(error::common_errc::service_not_available);
170
+ return handler(operations::make_response(std::move(ctx), request, {}));
165
171
  }
166
172
  auto cmd = std::make_shared<operations::http_command<Request>>(ctx_, request);
167
173
  cmd->send_to(session, [this, session, handler = std::forward<Handler>(handler)](typename Request::response_type resp) mutable {
@@ -18,8 +18,8 @@
18
18
  #include <build_info.hxx>
19
19
  #include <version.hxx>
20
20
 
21
+ #include <asio.hpp>
21
22
  #include <openssl/crypto.h>
22
- #include <asio/version.hpp>
23
23
 
24
24
  #include <spdlog/spdlog.h>
25
25
  #include <spdlog/cfg/env.h>
@@ -41,12 +41,12 @@
41
41
  #include <ruby/version.h>
42
42
  #endif
43
43
 
44
- #if !defined(RB_METHOD_DEFINITION_DECL)
45
- #define VALUE_FUNC(f) reinterpret_cast<VALUE (*)(ANYARGS)>(f)
46
- #define INT_FUNC(f) reinterpret_cast<int (*)(ANYARGS)>(f)
47
- #else
44
+ #if defined(RB_METHOD_DEFINITION_DECL) || RUBY_API_VERSION_MAJOR == 3
48
45
  #define VALUE_FUNC(f) (f)
49
46
  #define INT_FUNC(f) (f)
47
+ #else
48
+ #define VALUE_FUNC(f) reinterpret_cast<VALUE (*)(ANYARGS)>(f)
49
+ #define INT_FUNC(f) reinterpret_cast<int (*)(ANYARGS)>(f)
50
50
  #endif
51
51
 
52
52
  static void
@@ -63,7 +63,8 @@ init_versions(VALUE mCouchbase)
63
63
 
64
64
  std::string ver;
65
65
  ver = fmt::format("{}.{}.{}", couchbase::BACKEND_VERSION_MAJOR, couchbase::BACKEND_VERSION_MINOR, couchbase::BACKEND_VERSION_PATCH);
66
- rb_hash_aset(cb_Version, rb_id2sym(rb_intern("backend")), rb_str_freeze(rb_str_new(ver.c_str(), static_cast<long>(ver.size()))));
66
+ rb_hash_aset(
67
+ cb_Version, rb_id2sym(rb_intern("backend")), rb_str_freeze(rb_external_str_new(ver.c_str(), static_cast<long>(ver.size()))));
67
68
  rb_hash_aset(cb_Version, rb_id2sym(rb_intern("build_timestamp")), rb_str_freeze(rb_str_new_cstr(couchbase::BACKEND_BUILD_TIMESTAMP)));
68
69
  rb_hash_aset(cb_Version, rb_id2sym(rb_intern("revision")), rb_str_freeze(rb_str_new_cstr(couchbase::BACKEND_GIT_REVISION)));
69
70
  rb_hash_aset(cb_Version, rb_id2sym(rb_intern("platform")), rb_str_freeze(rb_str_new_cstr(couchbase::BACKEND_SYSTEM)));
@@ -72,16 +73,19 @@ init_versions(VALUE mCouchbase)
72
73
  rb_hash_aset(cb_Version, rb_id2sym(rb_intern("cxx")), rb_str_freeze(rb_str_new_cstr(couchbase::BACKEND_CXX_COMPILER)));
73
74
  #if defined(HAVE_RUBY_VERSION_H)
74
75
  ver = fmt::format("{}.{}.{}", RUBY_API_VERSION_MAJOR, RUBY_API_VERSION_MINOR, RUBY_API_VERSION_TEENY);
75
- rb_hash_aset(cb_Version, rb_id2sym(rb_intern("ruby")), rb_str_freeze(rb_str_new(ver.c_str(), static_cast<long>(ver.size()))));
76
+ rb_hash_aset(cb_Version, rb_id2sym(rb_intern("ruby")), rb_str_freeze(rb_external_str_new(ver.c_str(), static_cast<long>(ver.size()))));
76
77
  #endif
77
78
  ver = fmt::format("{}.{}.{}", SPDLOG_VER_MAJOR, SPDLOG_VER_MINOR, SPDLOG_VER_PATCH);
78
- rb_hash_aset(cb_Version, rb_id2sym(rb_intern("spdlog")), rb_str_freeze(rb_str_new(ver.c_str(), static_cast<long>(ver.size()))));
79
+ rb_hash_aset(
80
+ cb_Version, rb_id2sym(rb_intern("spdlog")), rb_str_freeze(rb_external_str_new(ver.c_str(), static_cast<long>(ver.size()))));
79
81
  ver = fmt::format("{}.{}.{}", VERSION_SPLIT_(ASIO_VERSION));
80
- rb_hash_aset(cb_Version, rb_id2sym(rb_intern("asio")), rb_str_freeze(rb_str_new(ver.c_str(), static_cast<long>(ver.size()))));
82
+ rb_hash_aset(cb_Version, rb_id2sym(rb_intern("asio")), rb_str_freeze(rb_external_str_new(ver.c_str(), static_cast<long>(ver.size()))));
81
83
  ver = fmt::format("{}.{}.{}", SNAPPY_MAJOR, SNAPPY_MINOR, SNAPPY_PATCHLEVEL);
82
- rb_hash_aset(cb_Version, rb_id2sym(rb_intern("snappy")), rb_str_freeze(rb_str_new(ver.c_str(), static_cast<long>(ver.size()))));
84
+ rb_hash_aset(
85
+ cb_Version, rb_id2sym(rb_intern("snappy")), rb_str_freeze(rb_external_str_new(ver.c_str(), static_cast<long>(ver.size()))));
83
86
  ver = fmt::format("{}.{}.{}", HTTP_PARSER_VERSION_MAJOR, HTTP_PARSER_VERSION_MINOR, HTTP_PARSER_VERSION_PATCH);
84
- rb_hash_aset(cb_Version, rb_id2sym(rb_intern("http_parser")), rb_str_freeze(rb_str_new(ver.c_str(), static_cast<long>(ver.size()))));
87
+ rb_hash_aset(
88
+ cb_Version, rb_id2sym(rb_intern("http_parser")), rb_str_freeze(rb_external_str_new(ver.c_str(), static_cast<long>(ver.size()))));
85
89
  rb_hash_aset(cb_Version, rb_id2sym(rb_intern("openssl_headers")), rb_str_freeze(rb_str_new_cstr(OPENSSL_VERSION_TEXT)));
86
90
  #if defined(OPENSSL_VERSION)
87
91
  rb_hash_aset(cb_Version, rb_id2sym(rb_intern("openssl_runtime")), rb_str_freeze(rb_str_new_cstr(OpenSSL_version(OPENSSL_VERSION))));
@@ -584,6 +588,303 @@ cb__map_error_code(std::error_code ec, const std::string& message)
584
588
  return rb_exc_new_cstr(eBackendError, fmt::format("{}: {}", message, ec.message()).c_str());
585
589
  }
586
590
 
591
+ static VALUE
592
+ cb__map_error_code(const couchbase::error_context::key_value& ctx, const std::string& message)
593
+ {
594
+ VALUE exc = cb__map_error_code(ctx.ec, message);
595
+ VALUE error_context = rb_hash_new();
596
+ std::string error(fmt::format("{}, {}", ctx.ec.value(), ctx.ec.message()));
597
+ rb_hash_aset(error_context, rb_id2sym(rb_intern("error")), rb_external_str_new(error.data(), static_cast<long>(error.size())));
598
+ rb_hash_aset(error_context, rb_id2sym(rb_intern("id")), rb_external_str_new(ctx.id.key.data(), static_cast<long>(ctx.id.key.size())));
599
+ rb_hash_aset(error_context,
600
+ rb_id2sym(rb_intern("collection")),
601
+ rb_external_str_new(ctx.id.collection.data(), static_cast<long>(ctx.id.collection.size())));
602
+ rb_hash_aset(
603
+ error_context, rb_id2sym(rb_intern("bucket")), rb_external_str_new(ctx.id.bucket.data(), static_cast<long>(ctx.id.bucket.size())));
604
+ rb_hash_aset(error_context, rb_id2sym(rb_intern("opaque")), ULONG2NUM(ctx.opaque));
605
+ if (ctx.status_code) {
606
+ std::string status(fmt::format("{}", ctx.status_code.value()));
607
+ rb_hash_aset(error_context, rb_id2sym(rb_intern("status")), rb_external_str_new(status.data(), static_cast<long>(status.size())));
608
+ }
609
+ if (ctx.error_map_info) {
610
+ VALUE error_map_info = rb_hash_new();
611
+ rb_hash_aset(error_map_info,
612
+ rb_id2sym(rb_intern("name")),
613
+ rb_external_str_new(ctx.error_map_info->name.data(), static_cast<long>(ctx.error_map_info->name.size())));
614
+ rb_hash_aset(
615
+ error_map_info,
616
+ rb_id2sym(rb_intern("desc")),
617
+ rb_external_str_new(ctx.error_map_info->description.data(), static_cast<long>(ctx.error_map_info->description.size())));
618
+ rb_hash_aset(error_context, rb_id2sym(rb_intern("error_map_info")), error_map_info);
619
+ }
620
+ if (ctx.enhanced_error_info) {
621
+ VALUE enhanced_error_info = rb_hash_new();
622
+ rb_hash_aset(
623
+ enhanced_error_info,
624
+ rb_id2sym(rb_intern("reference")),
625
+ rb_external_str_new(ctx.enhanced_error_info->reference.data(), static_cast<long>(ctx.enhanced_error_info->reference.size())));
626
+ rb_hash_aset(
627
+ enhanced_error_info,
628
+ rb_id2sym(rb_intern("context")),
629
+ rb_external_str_new(ctx.enhanced_error_info->context.data(), static_cast<long>(ctx.enhanced_error_info->context.size())));
630
+ rb_hash_aset(error_context, rb_id2sym(rb_intern("extended_error_info")), enhanced_error_info);
631
+ }
632
+ if (ctx.retry_attempts > 0) {
633
+ rb_hash_aset(error_context, rb_id2sym(rb_intern("retry_attempts")), INT2FIX(ctx.retry_attempts));
634
+ if (!ctx.retry_reasons.empty()) {
635
+ VALUE retry_reasons = rb_ary_new_capa(static_cast<long>(ctx.retry_reasons.size()));
636
+ for (const auto& reason : ctx.retry_reasons) {
637
+ auto reason_str = fmt::format("{}", reason);
638
+ rb_ary_push(retry_reasons, rb_id2sym(rb_intern(reason_str.c_str())));
639
+ }
640
+ rb_hash_aset(error_context, rb_id2sym(rb_intern("retry_reasons")), retry_reasons);
641
+ }
642
+ }
643
+ if (ctx.last_dispatched_to) {
644
+ rb_hash_aset(error_context,
645
+ rb_id2sym(rb_intern("last_dispatched_to")),
646
+ rb_external_str_new(ctx.last_dispatched_to->data(), static_cast<long>(ctx.last_dispatched_to->size())));
647
+ }
648
+ if (ctx.last_dispatched_from) {
649
+ rb_hash_aset(error_context,
650
+ rb_id2sym(rb_intern("last_dispatched_from")),
651
+ rb_external_str_new(ctx.last_dispatched_from->data(), static_cast<long>(ctx.last_dispatched_from->size())));
652
+ }
653
+ rb_iv_set(exc, "@context", error_context);
654
+ return exc;
655
+ }
656
+
657
+ static VALUE
658
+ cb__map_error_code(const couchbase::error_context::query& ctx, const std::string& message)
659
+ {
660
+ VALUE exc = cb__map_error_code(ctx.ec, message);
661
+ VALUE error_context = rb_hash_new();
662
+ std::string error(fmt::format("{}, {}", ctx.ec.value(), ctx.ec.message()));
663
+ rb_hash_aset(error_context, rb_id2sym(rb_intern("error")), rb_external_str_new(error.data(), static_cast<long>(error.size())));
664
+ rb_hash_aset(error_context,
665
+ rb_id2sym(rb_intern("client_context_id")),
666
+ rb_external_str_new(ctx.client_context_id.data(), static_cast<long>(ctx.client_context_id.size())));
667
+ rb_hash_aset(
668
+ error_context, rb_id2sym(rb_intern("statement")), rb_external_str_new(ctx.statement.data(), static_cast<long>(ctx.statement.size())));
669
+ if (ctx.parameters) {
670
+ rb_hash_aset(error_context,
671
+ rb_id2sym(rb_intern("parameters")),
672
+ rb_external_str_new(ctx.parameters->data(), static_cast<long>(ctx.parameters->size())));
673
+ }
674
+ rb_hash_aset(error_context, rb_id2sym(rb_intern("http_status")), INT2FIX(ctx.http_status));
675
+ rb_hash_aset(
676
+ error_context, rb_id2sym(rb_intern("http_body")), rb_external_str_new(ctx.http_body.data(), static_cast<long>(ctx.http_body.size())));
677
+ if (ctx.retry_attempts > 0) {
678
+ rb_hash_aset(error_context, rb_id2sym(rb_intern("retry_attempts")), INT2FIX(ctx.retry_attempts));
679
+ if (!ctx.retry_reasons.empty()) {
680
+ VALUE retry_reasons = rb_ary_new_capa(static_cast<long>(ctx.retry_reasons.size()));
681
+ for (const auto& reason : ctx.retry_reasons) {
682
+ auto reason_str = fmt::format("{}", reason);
683
+ rb_ary_push(retry_reasons, rb_id2sym(rb_intern(reason_str.c_str())));
684
+ }
685
+ rb_hash_aset(error_context, rb_id2sym(rb_intern("retry_reasons")), retry_reasons);
686
+ }
687
+ }
688
+ if (ctx.last_dispatched_to) {
689
+ rb_hash_aset(error_context,
690
+ rb_id2sym(rb_intern("last_dispatched_to")),
691
+ rb_external_str_new(ctx.last_dispatched_to->data(), static_cast<long>(ctx.last_dispatched_to->size())));
692
+ }
693
+ if (ctx.last_dispatched_from) {
694
+ rb_hash_aset(error_context,
695
+ rb_id2sym(rb_intern("last_dispatched_from")),
696
+ rb_external_str_new(ctx.last_dispatched_from->data(), static_cast<long>(ctx.last_dispatched_from->size())));
697
+ }
698
+ rb_iv_set(exc, "@context", error_context);
699
+ return exc;
700
+ }
701
+
702
+ static VALUE
703
+ cb__map_error_code(const couchbase::error_context::analytics& ctx, const std::string& message)
704
+ {
705
+ VALUE exc = cb__map_error_code(ctx.ec, message);
706
+ VALUE error_context = rb_hash_new();
707
+ std::string error(fmt::format("{}, {}", ctx.ec.value(), ctx.ec.message()));
708
+ rb_hash_aset(error_context, rb_id2sym(rb_intern("error")), rb_external_str_new(error.data(), static_cast<long>(error.size())));
709
+ rb_hash_aset(error_context,
710
+ rb_id2sym(rb_intern("client_context_id")),
711
+ rb_external_str_new(ctx.client_context_id.data(), static_cast<long>(ctx.client_context_id.size())));
712
+ rb_hash_aset(
713
+ error_context, rb_id2sym(rb_intern("statement")), rb_external_str_new(ctx.statement.data(), static_cast<long>(ctx.statement.size())));
714
+ if (ctx.parameters) {
715
+ rb_hash_aset(error_context,
716
+ rb_id2sym(rb_intern("parameters")),
717
+ rb_external_str_new(ctx.parameters->data(), static_cast<long>(ctx.parameters->size())));
718
+ }
719
+ rb_hash_aset(error_context, rb_id2sym(rb_intern("http_status")), INT2FIX(ctx.http_status));
720
+ rb_hash_aset(
721
+ error_context, rb_id2sym(rb_intern("http_body")), rb_external_str_new(ctx.http_body.data(), static_cast<long>(ctx.http_body.size())));
722
+ if (ctx.retry_attempts > 0) {
723
+ rb_hash_aset(error_context, rb_id2sym(rb_intern("retry_attempts")), INT2FIX(ctx.retry_attempts));
724
+ if (!ctx.retry_reasons.empty()) {
725
+ VALUE retry_reasons = rb_ary_new_capa(static_cast<long>(ctx.retry_reasons.size()));
726
+ for (const auto& reason : ctx.retry_reasons) {
727
+ auto reason_str = fmt::format("{}", reason);
728
+ rb_ary_push(retry_reasons, rb_id2sym(rb_intern(reason_str.c_str())));
729
+ }
730
+ rb_hash_aset(error_context, rb_id2sym(rb_intern("retry_reasons")), retry_reasons);
731
+ }
732
+ }
733
+ if (ctx.last_dispatched_to) {
734
+ rb_hash_aset(error_context,
735
+ rb_id2sym(rb_intern("last_dispatched_to")),
736
+ rb_external_str_new(ctx.last_dispatched_to->data(), static_cast<long>(ctx.last_dispatched_to->size())));
737
+ }
738
+ if (ctx.last_dispatched_from) {
739
+ rb_hash_aset(error_context,
740
+ rb_id2sym(rb_intern("last_dispatched_from")),
741
+ rb_external_str_new(ctx.last_dispatched_from->data(), static_cast<long>(ctx.last_dispatched_from->size())));
742
+ }
743
+ rb_iv_set(exc, "@context", error_context);
744
+ return exc;
745
+ }
746
+
747
+ static VALUE
748
+ cb__map_error_code(const couchbase::error_context::view& ctx, const std::string& message)
749
+ {
750
+ VALUE exc = cb__map_error_code(ctx.ec, message);
751
+ VALUE error_context = rb_hash_new();
752
+ std::string error(fmt::format("{}, {}", ctx.ec.value(), ctx.ec.message()));
753
+ rb_hash_aset(error_context, rb_id2sym(rb_intern("error")), rb_external_str_new(error.data(), static_cast<long>(error.size())));
754
+ rb_hash_aset(error_context,
755
+ rb_id2sym(rb_intern("client_context_id")),
756
+ rb_external_str_new(ctx.client_context_id.data(), static_cast<long>(ctx.client_context_id.size())));
757
+ rb_hash_aset(error_context,
758
+ rb_id2sym(rb_intern("design_document_name")),
759
+ rb_external_str_new(ctx.design_document_name.data(), static_cast<long>(ctx.design_document_name.size())));
760
+ rb_hash_aset(
761
+ error_context, rb_id2sym(rb_intern("view_name")), rb_external_str_new(ctx.view_name.data(), static_cast<long>(ctx.view_name.size())));
762
+ if (!ctx.query_string.empty()) {
763
+ VALUE parameters = rb_ary_new_capa(static_cast<long>(ctx.query_string.size()));
764
+ for (const auto& param : ctx.query_string) {
765
+ rb_ary_push(parameters, rb_external_str_new(param.data(), static_cast<long>(param.size())));
766
+ }
767
+ rb_hash_aset(error_context, rb_id2sym(rb_intern("parameters")), parameters);
768
+ }
769
+ rb_hash_aset(error_context, rb_id2sym(rb_intern("http_status")), INT2FIX(ctx.http_status));
770
+ rb_hash_aset(
771
+ error_context, rb_id2sym(rb_intern("http_body")), rb_external_str_new(ctx.http_body.data(), static_cast<long>(ctx.http_body.size())));
772
+ if (ctx.retry_attempts > 0) {
773
+ rb_hash_aset(error_context, rb_id2sym(rb_intern("retry_attempts")), INT2FIX(ctx.retry_attempts));
774
+ if (!ctx.retry_reasons.empty()) {
775
+ VALUE retry_reasons = rb_ary_new_capa(static_cast<long>(ctx.retry_reasons.size()));
776
+ for (const auto& reason : ctx.retry_reasons) {
777
+ auto reason_str = fmt::format("{}", reason);
778
+ rb_ary_push(retry_reasons, rb_id2sym(rb_intern(reason_str.c_str())));
779
+ }
780
+ rb_hash_aset(error_context, rb_id2sym(rb_intern("retry_reasons")), retry_reasons);
781
+ }
782
+ }
783
+ if (ctx.last_dispatched_to) {
784
+ rb_hash_aset(error_context,
785
+ rb_id2sym(rb_intern("last_dispatched_to")),
786
+ rb_external_str_new(ctx.last_dispatched_to->data(), static_cast<long>(ctx.last_dispatched_to->size())));
787
+ }
788
+ if (ctx.last_dispatched_from) {
789
+ rb_hash_aset(error_context,
790
+ rb_id2sym(rb_intern("last_dispatched_from")),
791
+ rb_external_str_new(ctx.last_dispatched_from->data(), static_cast<long>(ctx.last_dispatched_from->size())));
792
+ }
793
+ rb_iv_set(exc, "@context", error_context);
794
+ return exc;
795
+ }
796
+
797
+ static VALUE
798
+ cb__map_error_code(const couchbase::error_context::http& ctx, const std::string& message)
799
+ {
800
+ VALUE exc = cb__map_error_code(ctx.ec, message);
801
+ VALUE error_context = rb_hash_new();
802
+ std::string error(fmt::format("{}, {}", ctx.ec.value(), ctx.ec.message()));
803
+ rb_hash_aset(error_context, rb_id2sym(rb_intern("error")), rb_external_str_new(error.data(), static_cast<long>(error.size())));
804
+ rb_hash_aset(error_context,
805
+ rb_id2sym(rb_intern("client_context_id")),
806
+ rb_external_str_new(ctx.client_context_id.data(), static_cast<long>(ctx.client_context_id.size())));
807
+ rb_hash_aset(
808
+ error_context, rb_id2sym(rb_intern("method")), rb_external_str_new(ctx.method.data(), static_cast<long>(ctx.method.size())));
809
+ rb_hash_aset(error_context, rb_id2sym(rb_intern("path")), rb_external_str_new(ctx.path.data(), static_cast<long>(ctx.path.size())));
810
+ rb_hash_aset(error_context, rb_id2sym(rb_intern("http_status")), INT2FIX(ctx.http_status));
811
+ rb_hash_aset(
812
+ error_context, rb_id2sym(rb_intern("http_body")), rb_external_str_new(ctx.http_body.data(), static_cast<long>(ctx.http_body.size())));
813
+ if (ctx.retry_attempts > 0) {
814
+ rb_hash_aset(error_context, rb_id2sym(rb_intern("retry_attempts")), INT2FIX(ctx.retry_attempts));
815
+ if (!ctx.retry_reasons.empty()) {
816
+ VALUE retry_reasons = rb_ary_new_capa(static_cast<long>(ctx.retry_reasons.size()));
817
+ for (const auto& reason : ctx.retry_reasons) {
818
+ auto reason_str = fmt::format("{}", reason);
819
+ rb_ary_push(retry_reasons, rb_id2sym(rb_intern(reason_str.c_str())));
820
+ }
821
+ rb_hash_aset(error_context, rb_id2sym(rb_intern("retry_reasons")), retry_reasons);
822
+ }
823
+ }
824
+ if (ctx.last_dispatched_to) {
825
+ rb_hash_aset(error_context,
826
+ rb_id2sym(rb_intern("last_dispatched_to")),
827
+ rb_external_str_new(ctx.last_dispatched_to->data(), static_cast<long>(ctx.last_dispatched_to->size())));
828
+ }
829
+ if (ctx.last_dispatched_from) {
830
+ rb_hash_aset(error_context,
831
+ rb_id2sym(rb_intern("last_dispatched_from")),
832
+ rb_external_str_new(ctx.last_dispatched_from->data(), static_cast<long>(ctx.last_dispatched_from->size())));
833
+ }
834
+ rb_iv_set(exc, "@context", error_context);
835
+ return exc;
836
+ }
837
+
838
+ static VALUE
839
+ cb__map_error_code(const couchbase::error_context::search& ctx, const std::string& message)
840
+ {
841
+ VALUE exc = cb__map_error_code(ctx.ec, message);
842
+ VALUE error_context = rb_hash_new();
843
+ std::string error(fmt::format("{}, {}", ctx.ec.value(), ctx.ec.message()));
844
+ rb_hash_aset(error_context, rb_id2sym(rb_intern("error")), rb_external_str_new(error.data(), static_cast<long>(error.size())));
845
+ rb_hash_aset(error_context,
846
+ rb_id2sym(rb_intern("client_context_id")),
847
+ rb_external_str_new(ctx.client_context_id.data(), static_cast<long>(ctx.client_context_id.size())));
848
+ rb_hash_aset(error_context,
849
+ rb_id2sym(rb_intern("index_name")),
850
+ rb_external_str_new(ctx.index_name.data(), static_cast<long>(ctx.index_name.size())));
851
+ if (ctx.query) {
852
+ rb_hash_aset(
853
+ error_context, rb_id2sym(rb_intern("query")), rb_external_str_new(ctx.query->data(), static_cast<long>(ctx.query->size())));
854
+ }
855
+ if (ctx.parameters) {
856
+ rb_hash_aset(error_context,
857
+ rb_id2sym(rb_intern("parameters")),
858
+ rb_external_str_new(ctx.parameters->data(), static_cast<long>(ctx.parameters->size())));
859
+ }
860
+ rb_hash_aset(error_context, rb_id2sym(rb_intern("http_status")), INT2FIX(ctx.http_status));
861
+ rb_hash_aset(
862
+ error_context, rb_id2sym(rb_intern("http_body")), rb_external_str_new(ctx.http_body.data(), static_cast<long>(ctx.http_body.size())));
863
+ if (ctx.retry_attempts > 0) {
864
+ rb_hash_aset(error_context, rb_id2sym(rb_intern("retry_attempts")), INT2FIX(ctx.retry_attempts));
865
+ if (!ctx.retry_reasons.empty()) {
866
+ VALUE retry_reasons = rb_ary_new_capa(static_cast<long>(ctx.retry_reasons.size()));
867
+ for (const auto& reason : ctx.retry_reasons) {
868
+ auto reason_str = fmt::format("{}", reason);
869
+ rb_ary_push(retry_reasons, rb_id2sym(rb_intern(reason_str.c_str())));
870
+ }
871
+ rb_hash_aset(error_context, rb_id2sym(rb_intern("retry_reasons")), retry_reasons);
872
+ }
873
+ }
874
+ if (ctx.last_dispatched_to) {
875
+ rb_hash_aset(error_context,
876
+ rb_id2sym(rb_intern("last_dispatched_to")),
877
+ rb_external_str_new(ctx.last_dispatched_to->data(), static_cast<long>(ctx.last_dispatched_to->size())));
878
+ }
879
+ if (ctx.last_dispatched_from) {
880
+ rb_hash_aset(error_context,
881
+ rb_id2sym(rb_intern("last_dispatched_from")),
882
+ rb_external_str_new(ctx.last_dispatched_from->data(), static_cast<long>(ctx.last_dispatched_from->size())));
883
+ }
884
+ rb_iv_set(exc, "@context", error_context);
885
+ return exc;
886
+ }
887
+
587
888
  static VALUE
588
889
  cb_Backend_open(VALUE self, VALUE connection_string, VALUE credentials, VALUE options)
589
890
  {
@@ -628,6 +929,24 @@ cb_Backend_open(VALUE self, VALUE connection_string, VALUE credentials, VALUE op
628
929
  if (NIL_P(certificate_path) || NIL_P(key_path)) {
629
930
  auth.username.assign(RSTRING_PTR(username), static_cast<size_t>(RSTRING_LEN(username)));
630
931
  auth.password.assign(RSTRING_PTR(password), static_cast<size_t>(RSTRING_LEN(password)));
932
+ VALUE allowed_mechanisms = rb_hash_aref(options, rb_id2sym(rb_intern("allowed_sasl_mechanisms")));
933
+ if (!NIL_P(allowed_mechanisms)) {
934
+ Check_Type(allowed_mechanisms, T_ARRAY);
935
+ auto allowed_mechanisms_size = static_cast<size_t>(RARRAY_LEN(allowed_mechanisms));
936
+ auth.allowed_sasl_mechanisms.reserve(allowed_mechanisms_size);
937
+ for (size_t i = 0; i < allowed_mechanisms_size; ++i) {
938
+ VALUE mechanism = rb_ary_entry(allowed_mechanisms, static_cast<long>(i));
939
+ if (mechanism == rb_id2sym(rb_intern("scram_sha512"))) {
940
+ auth.allowed_sasl_mechanisms.emplace_back("SCRAM-SHA512");
941
+ } else if (mechanism == rb_id2sym(rb_intern("scram_sha256"))) {
942
+ auth.allowed_sasl_mechanisms.emplace_back("SCRAM-SHA256");
943
+ } else if (mechanism == rb_id2sym(rb_intern("scram_sha1"))) {
944
+ auth.allowed_sasl_mechanisms.emplace_back("SCRAM-SHA1");
945
+ } else if (mechanism == rb_id2sym(rb_intern("plain"))) {
946
+ auth.allowed_sasl_mechanisms.emplace_back("PLAIN");
947
+ }
948
+ }
949
+ }
631
950
  } else {
632
951
  if (!connstr.tls) {
633
952
  exc = rb_exc_new_cstr(
@@ -638,7 +957,7 @@ cb_Backend_open(VALUE self, VALUE connection_string, VALUE credentials, VALUE op
638
957
  auth.certificate_path.assign(RSTRING_PTR(certificate_path), static_cast<size_t>(RSTRING_LEN(certificate_path)));
639
958
  auth.key_path.assign(RSTRING_PTR(key_path), static_cast<size_t>(RSTRING_LEN(key_path)));
640
959
  }
641
- couchbase::origin origin(auth, std::move(connstr));
960
+ couchbase::origin origin(auth, connstr);
642
961
  auto barrier = std::make_shared<std::promise<std::error_code>>();
643
962
  auto f = barrier->get_future();
644
963
  backend->cluster->open(origin, [barrier](std::error_code ec) mutable { barrier->set_value(ec); });
@@ -688,8 +1007,8 @@ cb_Backend_diagnostics(VALUE self, VALUE report_id)
688
1007
  auto resp = f.get();
689
1008
 
690
1009
  VALUE res = rb_hash_new();
691
- rb_hash_aset(res, rb_id2sym(rb_intern("id")), rb_str_new(resp.id.data(), static_cast<long>(resp.id.size())));
692
- rb_hash_aset(res, rb_id2sym(rb_intern("sdk")), rb_str_new(resp.sdk.data(), static_cast<long>(resp.sdk.size())));
1010
+ rb_hash_aset(res, rb_id2sym(rb_intern("id")), rb_external_str_new(resp.id.data(), static_cast<long>(resp.id.size())));
1011
+ rb_hash_aset(res, rb_id2sym(rb_intern("sdk")), rb_external_str_new(resp.sdk.data(), static_cast<long>(resp.sdk.size())));
693
1012
  rb_hash_aset(res, rb_id2sym(rb_intern("version")), INT2FIX(resp.version));
694
1013
  VALUE services = rb_hash_new();
695
1014
  rb_hash_aset(res, rb_id2sym(rb_intern("services")), services);
@@ -722,9 +1041,11 @@ cb_Backend_diagnostics(VALUE self, VALUE report_id)
722
1041
  if (svc.last_activity) {
723
1042
  rb_hash_aset(service, rb_id2sym(rb_intern("last_activity_us")), LL2NUM(svc.last_activity->count()));
724
1043
  }
725
- rb_hash_aset(service, rb_id2sym(rb_intern("id")), rb_str_new(svc.id.data(), static_cast<long>(svc.id.size())));
726
- rb_hash_aset(service, rb_id2sym(rb_intern("remote")), rb_str_new(svc.remote.data(), static_cast<long>(svc.remote.size())));
727
- rb_hash_aset(service, rb_id2sym(rb_intern("local")), rb_str_new(svc.local.data(), static_cast<long>(svc.local.size())));
1044
+ rb_hash_aset(service, rb_id2sym(rb_intern("id")), rb_external_str_new(svc.id.data(), static_cast<long>(svc.id.size())));
1045
+ rb_hash_aset(
1046
+ service, rb_id2sym(rb_intern("remote")), rb_external_str_new(svc.remote.data(), static_cast<long>(svc.remote.size())));
1047
+ rb_hash_aset(
1048
+ service, rb_id2sym(rb_intern("local")), rb_external_str_new(svc.local.data(), static_cast<long>(svc.local.size())));
728
1049
  VALUE state = Qnil;
729
1050
  switch (svc.state) {
730
1051
  case couchbase::diag::endpoint_state::disconnected:
@@ -741,8 +1062,9 @@ cb_Backend_diagnostics(VALUE self, VALUE report_id)
741
1062
  break;
742
1063
  }
743
1064
  if (svc.details) {
744
- rb_hash_aset(
745
- service, rb_id2sym(rb_intern("details")), rb_str_new(svc.details->data(), static_cast<long>(svc.details->size())));
1065
+ rb_hash_aset(service,
1066
+ rb_id2sym(rb_intern("details")),
1067
+ rb_external_str_new(svc.details->data(), static_cast<long>(svc.details->size())));
746
1068
  }
747
1069
  rb_hash_aset(service, rb_id2sym(rb_intern("state")), state);
748
1070
  rb_ary_push(endpoints, service);
@@ -1182,8 +1504,8 @@ cb_Backend_ping(VALUE self, VALUE bucket, VALUE options)
1182
1504
  auto resp = f.get();
1183
1505
 
1184
1506
  VALUE res = rb_hash_new();
1185
- rb_hash_aset(res, rb_id2sym(rb_intern("id")), rb_str_new(resp.id.data(), static_cast<long>(resp.id.size())));
1186
- rb_hash_aset(res, rb_id2sym(rb_intern("sdk")), rb_str_new(resp.sdk.data(), static_cast<long>(resp.sdk.size())));
1507
+ rb_hash_aset(res, rb_id2sym(rb_intern("id")), rb_external_str_new(resp.id.data(), static_cast<long>(resp.id.size())));
1508
+ rb_hash_aset(res, rb_id2sym(rb_intern("sdk")), rb_external_str_new(resp.sdk.data(), static_cast<long>(resp.sdk.size())));
1187
1509
  rb_hash_aset(res, rb_id2sym(rb_intern("version")), INT2FIX(resp.version));
1188
1510
  services = rb_hash_new();
1189
1511
  rb_hash_aset(res, rb_id2sym(rb_intern("services")), services);
@@ -1214,9 +1536,11 @@ cb_Backend_ping(VALUE self, VALUE bucket, VALUE options)
1214
1536
  for (const auto& svc : svcs.second) {
1215
1537
  VALUE service = rb_hash_new();
1216
1538
  rb_hash_aset(service, rb_id2sym(rb_intern("latency")), LL2NUM(svc.latency.count()));
1217
- rb_hash_aset(service, rb_id2sym(rb_intern("id")), rb_str_new(svc.id.data(), static_cast<long>(svc.id.size())));
1218
- rb_hash_aset(service, rb_id2sym(rb_intern("remote")), rb_str_new(svc.remote.data(), static_cast<long>(svc.remote.size())));
1219
- rb_hash_aset(service, rb_id2sym(rb_intern("local")), rb_str_new(svc.local.data(), static_cast<long>(svc.local.size())));
1539
+ rb_hash_aset(service, rb_id2sym(rb_intern("id")), rb_external_str_new(svc.id.data(), static_cast<long>(svc.id.size())));
1540
+ rb_hash_aset(
1541
+ service, rb_id2sym(rb_intern("remote")), rb_external_str_new(svc.remote.data(), static_cast<long>(svc.remote.size())));
1542
+ rb_hash_aset(
1543
+ service, rb_id2sym(rb_intern("local")), rb_external_str_new(svc.local.data(), static_cast<long>(svc.local.size())));
1220
1544
  VALUE state = Qnil;
1221
1545
  switch (svc.state) {
1222
1546
  case couchbase::diag::ping_state::ok:
@@ -1228,8 +1552,9 @@ cb_Backend_ping(VALUE self, VALUE bucket, VALUE options)
1228
1552
  case couchbase::diag::ping_state::error:
1229
1553
  state = rb_id2sym(rb_intern("error"));
1230
1554
  if (svc.error) {
1231
- rb_hash_aset(
1232
- service, rb_id2sym(rb_intern("error")), rb_str_new(svc.error->data(), static_cast<long>(svc.error->size())));
1555
+ rb_hash_aset(service,
1556
+ rb_id2sym(rb_intern("error")),
1557
+ rb_external_str_new(svc.error->data(), static_cast<long>(svc.error->size())));
1233
1558
  }
1234
1559
  break;
1235
1560
  }
@@ -1274,13 +1599,13 @@ cb_Backend_document_get(VALUE self, VALUE bucket, VALUE collection, VALUE id, VA
1274
1599
  auto f = barrier->get_future();
1275
1600
  backend->cluster->execute(req, [barrier](couchbase::operations::get_response&& resp) mutable { barrier->set_value(resp); });
1276
1601
  auto resp = f.get();
1277
- if (resp.ec) {
1278
- exc = cb__map_error_code(resp.ec, fmt::format(R"(unable fetch "{}" (opaque={}))", doc_id, resp.opaque));
1602
+ if (resp.ctx.ec) {
1603
+ exc = cb__map_error_code(resp.ctx, "unable to fetch document");
1279
1604
  break;
1280
1605
  }
1281
1606
 
1282
1607
  VALUE res = rb_hash_new();
1283
- rb_hash_aset(res, rb_id2sym(rb_intern("content")), rb_str_new(resp.value.data(), static_cast<long>(resp.value.size())));
1608
+ rb_hash_aset(res, rb_id2sym(rb_intern("content")), rb_external_str_new(resp.value.data(), static_cast<long>(resp.value.size())));
1284
1609
  rb_hash_aset(res, rb_id2sym(rb_intern("cas")), ULL2NUM(resp.cas));
1285
1610
  rb_hash_aset(res, rb_id2sym(rb_intern("flags")), UINT2NUM(resp.flags));
1286
1611
  return res;
@@ -1332,12 +1657,11 @@ cb_Backend_document_get_multi(VALUE self, VALUE keys, VALUE options)
1332
1657
  for (auto& barrier : barriers) {
1333
1658
  auto resp = barrier->get_future().get();
1334
1659
  VALUE entry = rb_hash_new();
1335
- if (resp.ec) {
1336
- rb_hash_aset(entry,
1337
- rb_id2sym(rb_intern("error")),
1338
- cb__map_error_code(resp.ec, fmt::format(R"(unable fetch "{}" (opaque={}))", resp.id, resp.opaque)));
1660
+ if (resp.ctx.ec) {
1661
+ rb_hash_aset(entry, rb_id2sym(rb_intern("error")), cb__map_error_code(resp.ctx, "unable to (multi)fetch document"));
1339
1662
  }
1340
- rb_hash_aset(entry, rb_id2sym(rb_intern("content")), rb_str_new(resp.value.data(), static_cast<long>(resp.value.size())));
1663
+ rb_hash_aset(
1664
+ entry, rb_id2sym(rb_intern("content")), rb_external_str_new(resp.value.data(), static_cast<long>(resp.value.size())));
1341
1665
  rb_hash_aset(entry, rb_id2sym(rb_intern("cas")), ULL2NUM(resp.cas));
1342
1666
  rb_hash_aset(entry, rb_id2sym(rb_intern("flags")), UINT2NUM(resp.flags));
1343
1667
  rb_ary_push(res, entry);
@@ -1410,13 +1734,13 @@ cb_Backend_document_get_projected(VALUE self, VALUE bucket, VALUE collection, VA
1410
1734
  backend->cluster->execute(req,
1411
1735
  [barrier](couchbase::operations::get_projected_response&& resp) mutable { barrier->set_value(resp); });
1412
1736
  auto resp = f.get();
1413
- if (resp.ec) {
1414
- exc = cb__map_error_code(resp.ec, fmt::format(R"(unable fetch with projections "{}" (opaque={}))", doc_id, resp.opaque));
1737
+ if (resp.ctx.ec) {
1738
+ exc = cb__map_error_code(resp.ctx, "unable fetch with projections");
1415
1739
  break;
1416
1740
  }
1417
1741
 
1418
1742
  VALUE res = rb_hash_new();
1419
- rb_hash_aset(res, rb_id2sym(rb_intern("content")), rb_str_new(resp.value.data(), static_cast<long>(resp.value.size())));
1743
+ rb_hash_aset(res, rb_id2sym(rb_intern("content")), rb_external_str_new(resp.value.data(), static_cast<long>(resp.value.size())));
1420
1744
  rb_hash_aset(res, rb_id2sym(rb_intern("cas")), ULL2NUM(resp.cas));
1421
1745
  rb_hash_aset(res, rb_id2sym(rb_intern("flags")), UINT2NUM(resp.flags));
1422
1746
  if (resp.expiry) {
@@ -1466,13 +1790,13 @@ cb_Backend_document_get_and_lock(VALUE self, VALUE bucket, VALUE collection, VAL
1466
1790
  backend->cluster->execute(req,
1467
1791
  [barrier](couchbase::operations::get_and_lock_response&& resp) mutable { barrier->set_value(resp); });
1468
1792
  auto resp = f.get();
1469
- if (resp.ec) {
1470
- exc = cb__map_error_code(resp.ec, fmt::format(R"(unable lock and fetch "{}" (opaque={}))", doc_id, resp.opaque));
1793
+ if (resp.ctx.ec) {
1794
+ exc = cb__map_error_code(resp.ctx, "unable lock and fetch");
1471
1795
  break;
1472
1796
  }
1473
1797
 
1474
1798
  VALUE res = rb_hash_new();
1475
- rb_hash_aset(res, rb_id2sym(rb_intern("content")), rb_str_new(resp.value.data(), static_cast<long>(resp.value.size())));
1799
+ rb_hash_aset(res, rb_id2sym(rb_intern("content")), rb_external_str_new(resp.value.data(), static_cast<long>(resp.value.size())));
1476
1800
  rb_hash_aset(res, rb_id2sym(rb_intern("cas")), ULL2NUM(resp.cas));
1477
1801
  rb_hash_aset(res, rb_id2sym(rb_intern("flags")), UINT2NUM(resp.flags));
1478
1802
  return res;
@@ -1519,13 +1843,13 @@ cb_Backend_document_get_and_touch(VALUE self, VALUE bucket, VALUE collection, VA
1519
1843
  backend->cluster->execute(req,
1520
1844
  [barrier](couchbase::operations::get_and_touch_response&& resp) mutable { barrier->set_value(resp); });
1521
1845
  auto resp = f.get();
1522
- if (resp.ec) {
1523
- exc = cb__map_error_code(resp.ec, fmt::format(R"(unable fetch and touch "{}" (opaque={}))", doc_id, resp.opaque));
1846
+ if (resp.ctx.ec) {
1847
+ exc = cb__map_error_code(resp.ctx, "unable fetch and touch");
1524
1848
  break;
1525
1849
  }
1526
1850
 
1527
1851
  VALUE res = rb_hash_new();
1528
- rb_hash_aset(res, rb_id2sym(rb_intern("content")), rb_str_new(resp.value.data(), static_cast<long>(resp.value.size())));
1852
+ rb_hash_aset(res, rb_id2sym(rb_intern("content")), rb_external_str_new(resp.value.data(), static_cast<long>(resp.value.size())));
1529
1853
  rb_hash_aset(res, rb_id2sym(rb_intern("cas")), ULL2NUM(resp.cas));
1530
1854
  rb_hash_aset(res, rb_id2sym(rb_intern("flags")), UINT2NUM(resp.flags));
1531
1855
  return res;
@@ -1542,11 +1866,11 @@ cb__extract_mutation_result(Response resp)
1542
1866
  rb_hash_aset(res, rb_id2sym(rb_intern("cas")), ULL2NUM(resp.cas));
1543
1867
  VALUE token = rb_hash_new();
1544
1868
  rb_hash_aset(token, rb_id2sym(rb_intern("partition_uuid")), ULL2NUM(resp.token.partition_uuid));
1545
- rb_hash_aset(token, rb_id2sym(rb_intern("sequence_number")), ULONG2NUM(resp.token.sequence_number));
1869
+ rb_hash_aset(token, rb_id2sym(rb_intern("sequence_number")), ULL2NUM(resp.token.sequence_number));
1546
1870
  rb_hash_aset(token, rb_id2sym(rb_intern("partition_id")), UINT2NUM(resp.token.partition_id));
1547
1871
  rb_hash_aset(token,
1548
1872
  rb_id2sym(rb_intern("bucket_name")),
1549
- rb_str_new(resp.token.bucket_name.c_str(), static_cast<long>(resp.token.bucket_name.size())));
1873
+ rb_external_str_new(resp.token.bucket_name.c_str(), static_cast<long>(resp.token.bucket_name.size())));
1550
1874
  rb_hash_aset(res, rb_id2sym(rb_intern("mutation_token")), token);
1551
1875
  return res;
1552
1876
  }
@@ -1588,8 +1912,8 @@ cb_Backend_document_touch(VALUE self, VALUE bucket, VALUE collection, VALUE id,
1588
1912
  auto f = barrier->get_future();
1589
1913
  backend->cluster->execute(req, [barrier](couchbase::operations::touch_response&& resp) mutable { barrier->set_value(resp); });
1590
1914
  auto resp = f.get();
1591
- if (resp.ec) {
1592
- exc = cb__map_error_code(resp.ec, fmt::format(R"(unable to touch "{}" (opaque={}))", doc_id, resp.opaque));
1915
+ if (resp.ctx.ec) {
1916
+ exc = cb__map_error_code(resp.ctx, "unable to touch");
1593
1917
  break;
1594
1918
  }
1595
1919
 
@@ -1636,8 +1960,8 @@ cb_Backend_document_exists(VALUE self, VALUE bucket, VALUE collection, VALUE id,
1636
1960
  auto f = barrier->get_future();
1637
1961
  backend->cluster->execute(req, [barrier](couchbase::operations::exists_response&& resp) mutable { barrier->set_value(resp); });
1638
1962
  auto resp = f.get();
1639
- if (resp.ec) {
1640
- exc = cb__map_error_code(resp.ec, fmt::format(R"(unable to exists "{}" (opaque={}))", doc_id, resp.opaque));
1963
+ if (resp.ctx.ec) {
1964
+ exc = cb__map_error_code(resp.ctx, "unable to exists");
1641
1965
  break;
1642
1966
  }
1643
1967
 
@@ -1713,8 +2037,8 @@ cb_Backend_document_unlock(VALUE self, VALUE bucket, VALUE collection, VALUE id,
1713
2037
  auto f = barrier->get_future();
1714
2038
  backend->cluster->execute(req, [barrier](couchbase::operations::unlock_response&& resp) mutable { barrier->set_value(resp); });
1715
2039
  auto resp = f.get();
1716
- if (resp.ec) {
1717
- exc = cb__map_error_code(resp.ec, fmt::format(R"(unable to unlock "{}" (opaque={}))", doc_id, resp.opaque));
2040
+ if (resp.ctx.ec) {
2041
+ exc = cb__map_error_code(resp.ctx, "unable to unlock");
1718
2042
  break;
1719
2043
  }
1720
2044
 
@@ -1778,8 +2102,8 @@ cb_Backend_document_upsert(VALUE self, VALUE bucket, VALUE collection, VALUE id,
1778
2102
  auto f = barrier->get_future();
1779
2103
  backend->cluster->execute(req, [barrier](couchbase::operations::upsert_response&& resp) mutable { barrier->set_value(resp); });
1780
2104
  auto resp = f.get();
1781
- if (resp.ec) {
1782
- exc = cb__map_error_code(resp.ec, fmt::format(R"(unable to upsert "{}" (opaque={}))", doc_id, resp.opaque));
2105
+ if (resp.ctx.ec) {
2106
+ exc = cb__map_error_code(resp.ctx, "unable to upsert");
1783
2107
  break;
1784
2108
  }
1785
2109
 
@@ -1850,10 +2174,8 @@ cb_Backend_document_upsert_multi(VALUE self, VALUE id_content, VALUE options)
1850
2174
  for (auto& barrier : barriers) {
1851
2175
  auto resp = barrier->get_future().get();
1852
2176
  VALUE entry = cb__extract_mutation_result(resp);
1853
- if (resp.ec) {
1854
- rb_hash_aset(entry,
1855
- rb_id2sym(rb_intern("error")),
1856
- cb__map_error_code(resp.ec, fmt::format(R"(unable upsert "{}" (opaque={}))", resp.id, resp.opaque)));
2177
+ if (resp.ctx.ec) {
2178
+ rb_hash_aset(entry, rb_id2sym(rb_intern("error")), cb__map_error_code(resp.ctx, "unable (multi)upsert"));
1857
2179
  }
1858
2180
  rb_ary_push(res, entry);
1859
2181
  }
@@ -1904,8 +2226,8 @@ cb_Backend_document_append(VALUE self, VALUE bucket, VALUE collection, VALUE id,
1904
2226
  auto f = barrier->get_future();
1905
2227
  backend->cluster->execute(req, [barrier](couchbase::operations::append_response&& resp) mutable { barrier->set_value(resp); });
1906
2228
  auto resp = f.get();
1907
- if (resp.ec) {
1908
- exc = cb__map_error_code(resp.ec, fmt::format(R"(unable to append to "{}" (opaque={}))", doc_id, resp.opaque));
2229
+ if (resp.ctx.ec) {
2230
+ exc = cb__map_error_code(resp.ctx, "unable to append");
1909
2231
  break;
1910
2232
  }
1911
2233
 
@@ -1956,8 +2278,8 @@ cb_Backend_document_prepend(VALUE self, VALUE bucket, VALUE collection, VALUE id
1956
2278
  auto f = barrier->get_future();
1957
2279
  backend->cluster->execute(req, [barrier](couchbase::operations::prepend_response&& resp) mutable { barrier->set_value(resp); });
1958
2280
  auto resp = f.get();
1959
- if (resp.ec) {
1960
- exc = cb__map_error_code(resp.ec, fmt::format(R"(unable to prepend to "{}" (opaque={}))", doc_id, resp.opaque));
2281
+ if (resp.ctx.ec) {
2282
+ exc = cb__map_error_code(resp.ctx, "unable to prepend");
1961
2283
  break;
1962
2284
  }
1963
2285
 
@@ -2027,8 +2349,8 @@ cb_Backend_document_replace(VALUE self, VALUE bucket, VALUE collection, VALUE id
2027
2349
  auto f = barrier->get_future();
2028
2350
  backend->cluster->execute(req, [barrier](couchbase::operations::replace_response&& resp) mutable { barrier->set_value(resp); });
2029
2351
  auto resp = f.get();
2030
- if (resp.ec) {
2031
- exc = cb__map_error_code(resp.ec, fmt::format(R"(unable to replace "{}" (opaque={}))", doc_id, resp.opaque));
2352
+ if (resp.ctx.ec) {
2353
+ exc = cb__map_error_code(resp.ctx, "unable to replace");
2032
2354
  break;
2033
2355
  }
2034
2356
 
@@ -2090,8 +2412,8 @@ cb_Backend_document_insert(VALUE self, VALUE bucket, VALUE collection, VALUE id,
2090
2412
  auto f = barrier->get_future();
2091
2413
  backend->cluster->execute(req, [barrier](couchbase::operations::insert_response&& resp) mutable { barrier->set_value(resp); });
2092
2414
  auto resp = f.get();
2093
- if (resp.ec) {
2094
- exc = cb__map_error_code(resp.ec, fmt::format(R"(unable to insert "{}" (opaque={}))", doc_id, resp.opaque));
2415
+ if (resp.ctx.ec) {
2416
+ exc = cb__map_error_code(resp.ctx, "unable to insert");
2095
2417
  break;
2096
2418
  }
2097
2419
 
@@ -2148,8 +2470,8 @@ cb_Backend_document_remove(VALUE self, VALUE bucket, VALUE collection, VALUE id,
2148
2470
  auto f = barrier->get_future();
2149
2471
  backend->cluster->execute(req, [barrier](couchbase::operations::remove_response&& resp) mutable { barrier->set_value(resp); });
2150
2472
  auto resp = f.get();
2151
- if (resp.ec) {
2152
- exc = cb__map_error_code(resp.ec, fmt::format(R"(unable to remove "{}" (opaque={}))", doc_id, resp.opaque));
2473
+ if (resp.ctx.ec) {
2474
+ exc = cb__map_error_code(resp.ctx, "unable to remove");
2153
2475
  break;
2154
2476
  }
2155
2477
  return cb__extract_mutation_result(resp);
@@ -2215,10 +2537,8 @@ cb_Backend_document_remove_multi(VALUE self, VALUE id_cas, VALUE options)
2215
2537
  for (auto& barrier : barriers) {
2216
2538
  auto resp = barrier->get_future().get();
2217
2539
  VALUE entry = cb__extract_mutation_result(resp);
2218
- if (resp.ec) {
2219
- rb_hash_aset(entry,
2220
- rb_id2sym(rb_intern("error")),
2221
- cb__map_error_code(resp.ec, fmt::format(R"(unable remove "{}" (opaque={}))", resp.id, resp.opaque)));
2540
+ if (resp.ctx.ec) {
2541
+ rb_hash_aset(entry, rb_id2sym(rb_intern("error")), cb__map_error_code(resp.ctx, "unable (multi)remove"));
2222
2542
  }
2223
2543
  rb_ary_push(res, entry);
2224
2544
  }
@@ -2292,8 +2612,8 @@ cb_Backend_document_increment(VALUE self, VALUE bucket, VALUE collection, VALUE
2292
2612
  auto f = barrier->get_future();
2293
2613
  backend->cluster->execute(req, [barrier](couchbase::operations::increment_response&& resp) mutable { barrier->set_value(resp); });
2294
2614
  auto resp = f.get();
2295
- if (resp.ec) {
2296
- exc = cb__map_error_code(resp.ec, fmt::format(R"(unable to increment "{}" by {} (opaque={}))", doc_id, req.delta, resp.opaque));
2615
+ if (resp.ctx.ec) {
2616
+ exc = cb__map_error_code(resp.ctx.ec, fmt::format(R"(unable to increment by {})", req.delta));
2297
2617
  break;
2298
2618
  }
2299
2619
  VALUE res = cb__extract_mutation_result(resp);
@@ -2367,8 +2687,8 @@ cb_Backend_document_decrement(VALUE self, VALUE bucket, VALUE collection, VALUE
2367
2687
  auto f = barrier->get_future();
2368
2688
  backend->cluster->execute(req, [barrier](couchbase::operations::decrement_response&& resp) mutable { barrier->set_value(resp); });
2369
2689
  auto resp = f.get();
2370
- if (resp.ec) {
2371
- exc = cb__map_error_code(resp.ec, fmt::format(R"(unable to decrement "{}" by {} (opaque={}))", doc_id, req.delta, resp.opaque));
2690
+ if (resp.ctx.ec) {
2691
+ exc = cb__map_error_code(resp.ctx, fmt::format(R"(unable to decrement by {})", req.delta));
2372
2692
  break;
2373
2693
  }
2374
2694
  VALUE res = cb__extract_mutation_result(resp);
@@ -2626,8 +2946,8 @@ cb_Backend_document_lookup_in(VALUE self, VALUE bucket, VALUE collection, VALUE
2626
2946
  auto f = barrier->get_future();
2627
2947
  backend->cluster->execute(req, [barrier](couchbase::operations::lookup_in_response&& resp) mutable { barrier->set_value(resp); });
2628
2948
  auto resp = f.get();
2629
- if (resp.ec) {
2630
- exc = cb__map_error_code(resp.ec, fmt::format(R"(unable fetch "{}" (opaque={}))", doc_id, resp.opaque));
2949
+ if (resp.ctx.ec) {
2950
+ exc = cb__map_error_code(resp.ctx, "unable fetch");
2631
2951
  break;
2632
2952
  }
2633
2953
 
@@ -2642,11 +2962,12 @@ cb_Backend_document_lookup_in(VALUE self, VALUE bucket, VALUE collection, VALUE
2642
2962
  VALUE entry = rb_hash_new();
2643
2963
  rb_hash_aset(entry, rb_id2sym(rb_intern("index")), ULL2NUM(i));
2644
2964
  rb_hash_aset(entry, rb_id2sym(rb_intern("exists")), resp.fields[i].exists ? Qtrue : Qfalse);
2645
- rb_hash_aset(
2646
- entry, rb_id2sym(rb_intern("path")), rb_str_new(resp.fields[i].path.data(), static_cast<long>(resp.fields[i].path.size())));
2965
+ rb_hash_aset(entry,
2966
+ rb_id2sym(rb_intern("path")),
2967
+ rb_external_str_new(resp.fields[i].path.data(), static_cast<long>(resp.fields[i].path.size())));
2647
2968
  rb_hash_aset(entry,
2648
2969
  rb_id2sym(rb_intern("value")),
2649
- rb_str_new(resp.fields[i].value.data(), static_cast<long>(resp.fields[i].value.size())));
2970
+ rb_external_str_new(resp.fields[i].value.data(), static_cast<long>(resp.fields[i].value.size())));
2650
2971
  cb__map_subdoc_status(resp.fields[i].status, i, resp.fields[i].path, entry);
2651
2972
  if (resp.fields[i].opcode == couchbase::protocol::subdoc_opcode::get && resp.fields[i].path.empty()) {
2652
2973
  rb_hash_aset(entry, rb_id2sym(rb_intern("type")), rb_id2sym(rb_intern("get_doc")));
@@ -2805,14 +3126,14 @@ cb_Backend_document_mutate_in(VALUE self, VALUE bucket, VALUE collection, VALUE
2805
3126
  auto f = barrier->get_future();
2806
3127
  backend->cluster->execute(req, [barrier](couchbase::operations::mutate_in_response&& resp) mutable { barrier->set_value(resp); });
2807
3128
  auto resp = f.get();
2808
- if (resp.ec) {
2809
- exc = cb__map_error_code(resp.ec, fmt::format(R"(unable to mutate "{}" (opaque={}))", doc_id, resp.opaque));
3129
+ if (resp.ctx.ec) {
3130
+ exc = cb__map_error_code(resp.ctx, "unable to mutate");
2810
3131
  break;
2811
3132
  }
2812
3133
 
2813
3134
  VALUE res = cb__extract_mutation_result(resp);
2814
3135
  if (resp.first_error_index) {
2815
- rb_hash_aset(res, rb_id2sym(rb_intern("first_error_index")), ULONG2NUM(resp.first_error_index.value()));
3136
+ rb_hash_aset(res, rb_id2sym(rb_intern("first_error_index")), ULL2NUM(resp.first_error_index.value()));
2816
3137
  }
2817
3138
  if (resp.deleted) {
2818
3139
  rb_hash_aset(res, rb_id2sym(rb_intern("deleted")), Qtrue);
@@ -2822,18 +3143,19 @@ cb_Backend_document_mutate_in(VALUE self, VALUE bucket, VALUE collection, VALUE
2822
3143
  for (size_t i = 0; i < resp.fields.size(); ++i) {
2823
3144
  VALUE entry = rb_hash_new();
2824
3145
  rb_hash_aset(entry, rb_id2sym(rb_intern("index")), ULL2NUM(i));
2825
- rb_hash_aset(
2826
- entry, rb_id2sym(rb_intern("path")), rb_str_new(resp.fields[i].path.data(), static_cast<long>(resp.fields[i].path.size())));
3146
+ rb_hash_aset(entry,
3147
+ rb_id2sym(rb_intern("path")),
3148
+ rb_external_str_new(resp.fields[i].path.data(), static_cast<long>(resp.fields[i].path.size())));
2827
3149
  if (resp.fields[i].status == couchbase::protocol::status::success ||
2828
3150
  resp.fields[i].status == couchbase::protocol::status::subdoc_success_deleted) {
2829
3151
  if (resp.fields[i].opcode == couchbase::protocol::subdoc_opcode::counter) {
2830
- if (resp.fields[i].value.size() > 0) {
2831
- rb_hash_aset(entry, rb_id2sym(rb_intern("value")), LONG2NUM(std::stoll(resp.fields[i].value)));
3152
+ if (!resp.fields[i].value.empty()) {
3153
+ rb_hash_aset(entry, rb_id2sym(rb_intern("value")), LL2NUM(std::stoll(resp.fields[i].value)));
2832
3154
  }
2833
3155
  } else {
2834
3156
  rb_hash_aset(entry,
2835
3157
  rb_id2sym(rb_intern("value")),
2836
- rb_str_new(resp.fields[i].value.data(), static_cast<long>(resp.fields[i].value.size())));
3158
+ rb_external_str_new(resp.fields[i].value.data(), static_cast<long>(resp.fields[i].value.size())));
2837
3159
  }
2838
3160
  }
2839
3161
  cb__map_subdoc_status(resp.fields[i].status, i, resp.fields[i].path, entry);
@@ -3022,22 +3344,12 @@ cb_Backend_document_query(VALUE self, VALUE statement, VALUE options)
3022
3344
  auto f = barrier->get_future();
3023
3345
  backend->cluster->execute_http(req, [barrier](couchbase::operations::query_response&& resp) mutable { barrier->set_value(resp); });
3024
3346
  auto resp = f.get();
3025
- if (resp.ec) {
3347
+ if (resp.ctx.ec) {
3026
3348
  if (resp.payload.meta_data.errors && !resp.payload.meta_data.errors->empty()) {
3027
3349
  const auto& first_error = resp.payload.meta_data.errors->front();
3028
- exc = cb__map_error_code(resp.ec,
3029
- fmt::format(R"(unable to query (client_context_id="{}"): "{}{}" ({}: {}))",
3030
- req.client_context_id,
3031
- req.statement.substr(0, 100),
3032
- req.statement.size() > 100 ? "..." : "",
3033
- first_error.code,
3034
- first_error.message));
3350
+ exc = cb__map_error_code(resp.ctx, fmt::format(R"(unable to query ({}: {}))", first_error.code, first_error.message));
3035
3351
  } else {
3036
- exc = cb__map_error_code(resp.ec,
3037
- fmt::format(R"(unable to query (client_context_id="{}"): "{}{}")",
3038
- req.client_context_id,
3039
- req.statement.substr(0, 100),
3040
- req.statement.size() > 100 ? "..." : ""));
3352
+ exc = cb__map_error_code(resp.ctx, "unable to query");
3041
3353
  }
3042
3354
  break;
3043
3355
  }
@@ -3045,43 +3357,46 @@ cb_Backend_document_query(VALUE self, VALUE statement, VALUE options)
3045
3357
  VALUE rows = rb_ary_new_capa(static_cast<long>(resp.payload.rows.size()));
3046
3358
  rb_hash_aset(res, rb_id2sym(rb_intern("rows")), rows);
3047
3359
  for (auto& row : resp.payload.rows) {
3048
- rb_ary_push(rows, rb_str_new(row.data(), static_cast<long>(row.size())));
3360
+ rb_ary_push(rows, rb_external_str_new(row.data(), static_cast<long>(row.size())));
3049
3361
  }
3050
3362
  VALUE meta = rb_hash_new();
3051
3363
  rb_hash_aset(res, rb_id2sym(rb_intern("meta")), meta);
3052
3364
  rb_hash_aset(meta,
3053
3365
  rb_id2sym(rb_intern("status")),
3054
3366
  rb_id2sym(rb_intern2(resp.payload.meta_data.status.data(), static_cast<long>(resp.payload.meta_data.status.size()))));
3055
- rb_hash_aset(meta,
3056
- rb_id2sym(rb_intern("request_id")),
3057
- rb_str_new(resp.payload.meta_data.request_id.data(), static_cast<long>(resp.payload.meta_data.request_id.size())));
3058
3367
  rb_hash_aset(
3059
3368
  meta,
3060
- rb_id2sym(rb_intern("client_context_id")),
3061
- rb_str_new(resp.payload.meta_data.client_context_id.data(), static_cast<long>(resp.payload.meta_data.client_context_id.size())));
3369
+ rb_id2sym(rb_intern("request_id")),
3370
+ rb_external_str_new(resp.payload.meta_data.request_id.data(), static_cast<long>(resp.payload.meta_data.request_id.size())));
3371
+ rb_hash_aset(meta,
3372
+ rb_id2sym(rb_intern("client_context_id")),
3373
+ rb_external_str_new(resp.payload.meta_data.client_context_id.data(),
3374
+ static_cast<long>(resp.payload.meta_data.client_context_id.size())));
3062
3375
  if (resp.payload.meta_data.signature) {
3063
- rb_hash_aset(meta,
3064
- rb_id2sym(rb_intern("signature")),
3065
- rb_str_new(resp.payload.meta_data.signature->data(), static_cast<long>(resp.payload.meta_data.signature->size())));
3376
+ rb_hash_aset(
3377
+ meta,
3378
+ rb_id2sym(rb_intern("signature")),
3379
+ rb_external_str_new(resp.payload.meta_data.signature->data(), static_cast<long>(resp.payload.meta_data.signature->size())));
3066
3380
  }
3067
3381
  if (resp.payload.meta_data.profile) {
3068
- rb_hash_aset(meta,
3069
- rb_id2sym(rb_intern("profile")),
3070
- rb_str_new(resp.payload.meta_data.profile->data(), static_cast<long>(resp.payload.meta_data.profile->size())));
3382
+ rb_hash_aset(
3383
+ meta,
3384
+ rb_id2sym(rb_intern("profile")),
3385
+ rb_external_str_new(resp.payload.meta_data.profile->data(), static_cast<long>(resp.payload.meta_data.profile->size())));
3071
3386
  }
3072
3387
  metrics = rb_hash_new();
3073
3388
  rb_hash_aset(meta, rb_id2sym(rb_intern("metrics")), metrics);
3074
3389
  if (!resp.payload.meta_data.metrics.elapsed_time.empty()) {
3075
3390
  rb_hash_aset(metrics,
3076
3391
  rb_id2sym(rb_intern("elapsed_time")),
3077
- rb_str_new(resp.payload.meta_data.metrics.elapsed_time.data(),
3078
- static_cast<long>(resp.payload.meta_data.metrics.elapsed_time.size())));
3392
+ rb_external_str_new(resp.payload.meta_data.metrics.elapsed_time.data(),
3393
+ static_cast<long>(resp.payload.meta_data.metrics.elapsed_time.size())));
3079
3394
  }
3080
3395
  if (!resp.payload.meta_data.metrics.execution_time.empty()) {
3081
3396
  rb_hash_aset(metrics,
3082
3397
  rb_id2sym(rb_intern("execution_time")),
3083
- rb_str_new(resp.payload.meta_data.metrics.execution_time.data(),
3084
- static_cast<long>(resp.payload.meta_data.metrics.execution_time.size())));
3398
+ rb_external_str_new(resp.payload.meta_data.metrics.execution_time.data(),
3399
+ static_cast<long>(resp.payload.meta_data.metrics.execution_time.size())));
3085
3400
  }
3086
3401
  rb_hash_aset(metrics, rb_id2sym(rb_intern("result_count")), ULL2NUM(resp.payload.meta_data.metrics.result_count));
3087
3402
  rb_hash_aset(metrics, rb_id2sym(rb_intern("result_size")), ULL2NUM(resp.payload.meta_data.metrics.result_size));
@@ -3104,44 +3419,60 @@ cb_Backend_document_query(VALUE self, VALUE statement, VALUE options)
3104
3419
  return Qnil;
3105
3420
  }
3106
3421
 
3107
- static void
3422
+ static VALUE
3108
3423
  cb__generate_bucket_settings(VALUE bucket, couchbase::operations::bucket_settings& entry, bool is_create)
3109
3424
  {
3110
3425
  {
3111
3426
  VALUE bucket_type = rb_hash_aref(bucket, rb_id2sym(rb_intern("bucket_type")));
3112
- Check_Type(bucket_type, T_SYMBOL);
3113
- if (bucket_type == rb_id2sym(rb_intern("couchbase")) || bucket_type == rb_id2sym(rb_intern("membase"))) {
3114
- entry.bucket_type = couchbase::operations::bucket_settings::bucket_type::couchbase;
3115
- } else if (bucket_type == rb_id2sym(rb_intern("memcached"))) {
3116
- entry.bucket_type = couchbase::operations::bucket_settings::bucket_type::memcached;
3117
- } else if (bucket_type == rb_id2sym(rb_intern("ephemeral"))) {
3118
- entry.bucket_type = couchbase::operations::bucket_settings::bucket_type::ephemeral;
3427
+ if (TYPE(bucket_type) == T_SYMBOL) {
3428
+ if (bucket_type == rb_id2sym(rb_intern("couchbase")) || bucket_type == rb_id2sym(rb_intern("membase"))) {
3429
+ entry.bucket_type = couchbase::operations::bucket_settings::bucket_type::couchbase;
3430
+ } else if (bucket_type == rb_id2sym(rb_intern("memcached"))) {
3431
+ entry.bucket_type = couchbase::operations::bucket_settings::bucket_type::memcached;
3432
+ } else if (bucket_type == rb_id2sym(rb_intern("ephemeral"))) {
3433
+ entry.bucket_type = couchbase::operations::bucket_settings::bucket_type::ephemeral;
3434
+ } else {
3435
+ return rb_exc_new_str(rb_eArgError, rb_sprintf("unknown bucket type, given %+" PRIsVALUE, bucket_type));
3436
+ }
3119
3437
  } else {
3120
- rb_raise(rb_eArgError, "unknown bucket type");
3438
+ return rb_exc_new_str(rb_eArgError, rb_sprintf("bucket type must be a Symbol, given %+" PRIsVALUE, bucket_type));
3121
3439
  }
3122
3440
  }
3123
3441
  {
3124
3442
  VALUE name = rb_hash_aref(bucket, rb_id2sym(rb_intern("name")));
3125
- Check_Type(name, T_STRING);
3126
- entry.name.assign(RSTRING_PTR(name), static_cast<size_t>(RSTRING_LEN(name)));
3443
+ if (TYPE(name) == T_STRING) {
3444
+ entry.name.assign(RSTRING_PTR(name), static_cast<size_t>(RSTRING_LEN(name)));
3445
+ } else {
3446
+ return rb_exc_new_str(rb_eArgError, rb_sprintf("bucket name must be a String, given %+" PRIsVALUE, name));
3447
+ }
3127
3448
  }
3128
3449
  {
3129
3450
  VALUE quota = rb_hash_aref(bucket, rb_id2sym(rb_intern("ram_quota_mb")));
3130
- Check_Type(quota, T_FIXNUM);
3131
- entry.ram_quota_mb = FIX2ULONG(quota);
3451
+ if (TYPE(quota) == T_FIXNUM) {
3452
+ entry.ram_quota_mb = FIX2ULONG(quota);
3453
+ } else {
3454
+ return rb_exc_new_str(rb_eArgError, rb_sprintf("bucket RAM quota must be an Integer, given %+" PRIsVALUE, quota));
3455
+ }
3132
3456
  }
3133
3457
  {
3134
3458
  VALUE expiry = rb_hash_aref(bucket, rb_id2sym(rb_intern("max_expiry")));
3135
3459
  if (!NIL_P(expiry)) {
3136
- Check_Type(expiry, T_FIXNUM);
3137
- entry.max_expiry = FIX2UINT(expiry);
3460
+ if (TYPE(expiry) == T_FIXNUM) {
3461
+ entry.max_expiry = FIX2UINT(expiry);
3462
+ } else {
3463
+ return rb_exc_new_str(rb_eArgError, rb_sprintf("bucket max expiry must be an Integer, given %+" PRIsVALUE, expiry));
3464
+ }
3138
3465
  }
3139
3466
  }
3140
3467
  {
3141
3468
  VALUE num_replicas = rb_hash_aref(bucket, rb_id2sym(rb_intern("num_replicas")));
3142
3469
  if (!NIL_P(num_replicas)) {
3143
- Check_Type(num_replicas, T_FIXNUM);
3144
- entry.num_replicas = FIX2UINT(num_replicas);
3470
+ if (TYPE(num_replicas) == T_FIXNUM) {
3471
+ entry.num_replicas = FIX2UINT(num_replicas);
3472
+ } else {
3473
+ return rb_exc_new_str(rb_eArgError,
3474
+ rb_sprintf("bucket number of replicas must be an Integer, given %+" PRIsVALUE, num_replicas));
3475
+ }
3145
3476
  }
3146
3477
  }
3147
3478
  {
@@ -3159,48 +3490,84 @@ cb__generate_bucket_settings(VALUE bucket, couchbase::operations::bucket_setting
3159
3490
  {
3160
3491
  VALUE compression_mode = rb_hash_aref(bucket, rb_id2sym(rb_intern("compression_mode")));
3161
3492
  if (!NIL_P(compression_mode)) {
3162
- Check_Type(compression_mode, T_SYMBOL);
3163
- if (compression_mode == rb_id2sym(rb_intern("active"))) {
3164
- entry.compression_mode = couchbase::operations::bucket_settings::compression_mode::active;
3165
- } else if (compression_mode == rb_id2sym(rb_intern("passive"))) {
3166
- entry.compression_mode = couchbase::operations::bucket_settings::compression_mode::passive;
3167
- } else if (compression_mode == rb_id2sym(rb_intern("off"))) {
3168
- entry.compression_mode = couchbase::operations::bucket_settings::compression_mode::off;
3493
+ if (TYPE(compression_mode) == T_SYMBOL) {
3494
+ if (compression_mode == rb_id2sym(rb_intern("active"))) {
3495
+ entry.compression_mode = couchbase::operations::bucket_settings::compression_mode::active;
3496
+ } else if (compression_mode == rb_id2sym(rb_intern("passive"))) {
3497
+ entry.compression_mode = couchbase::operations::bucket_settings::compression_mode::passive;
3498
+ } else if (compression_mode == rb_id2sym(rb_intern("off"))) {
3499
+ entry.compression_mode = couchbase::operations::bucket_settings::compression_mode::off;
3500
+ } else {
3501
+ return rb_exc_new_str(rb_eArgError, rb_sprintf("unknown compression mode, given %+" PRIsVALUE, compression_mode));
3502
+ }
3169
3503
  } else {
3170
- rb_raise(rb_eArgError, "unknown compression mode");
3504
+ return rb_exc_new_str(rb_eArgError,
3505
+ rb_sprintf("bucket compression mode must be a Symbol, given %+" PRIsVALUE, compression_mode));
3171
3506
  }
3172
3507
  }
3173
3508
  }
3174
3509
  {
3175
3510
  VALUE eviction_policy = rb_hash_aref(bucket, rb_id2sym(rb_intern("eviction_policy")));
3176
3511
  if (!NIL_P(eviction_policy)) {
3177
- Check_Type(eviction_policy, T_SYMBOL);
3178
- if (eviction_policy == rb_id2sym(rb_intern("full"))) {
3179
- entry.eviction_policy = couchbase::operations::bucket_settings::eviction_policy::full;
3180
- } else if (eviction_policy == rb_id2sym(rb_intern("value_only"))) {
3181
- entry.eviction_policy = couchbase::operations::bucket_settings::eviction_policy::value_only;
3182
- } else if (eviction_policy == rb_id2sym(rb_intern("no_eviction"))) {
3183
- entry.eviction_policy = couchbase::operations::bucket_settings::eviction_policy::no_eviction;
3184
- } else if (eviction_policy == rb_id2sym(rb_intern("not_recently_used"))) {
3185
- entry.eviction_policy = couchbase::operations::bucket_settings::eviction_policy::not_recently_used;
3512
+ if (TYPE(eviction_policy) == T_SYMBOL) {
3513
+ if (eviction_policy == rb_id2sym(rb_intern("full"))) {
3514
+ entry.eviction_policy = couchbase::operations::bucket_settings::eviction_policy::full;
3515
+ } else if (eviction_policy == rb_id2sym(rb_intern("value_only"))) {
3516
+ entry.eviction_policy = couchbase::operations::bucket_settings::eviction_policy::value_only;
3517
+ } else if (eviction_policy == rb_id2sym(rb_intern("no_eviction"))) {
3518
+ entry.eviction_policy = couchbase::operations::bucket_settings::eviction_policy::no_eviction;
3519
+ } else if (eviction_policy == rb_id2sym(rb_intern("not_recently_used"))) {
3520
+ entry.eviction_policy = couchbase::operations::bucket_settings::eviction_policy::not_recently_used;
3521
+ } else {
3522
+ return rb_exc_new_str(rb_eArgError, rb_sprintf("unknown eviction policy, given %+" PRIsVALUE, eviction_policy));
3523
+ }
3186
3524
  } else {
3187
- rb_raise(rb_eArgError, "unknown eviction policy");
3525
+ return rb_exc_new_str(rb_eArgError,
3526
+ rb_sprintf("bucket eviction policy must be a Symbol, given %+" PRIsVALUE, eviction_policy));
3527
+ }
3528
+ }
3529
+ }
3530
+ {
3531
+ VALUE minimum_level = rb_hash_aref(bucket, rb_id2sym(rb_intern("minimum_durability_level")));
3532
+ if (!NIL_P(minimum_level)) {
3533
+ if (TYPE(minimum_level) == T_SYMBOL) {
3534
+ if (minimum_level == rb_id2sym(rb_intern("none"))) {
3535
+ entry.minimum_durability_level = couchbase::protocol::durability_level::none;
3536
+ } else if (minimum_level == rb_id2sym(rb_intern("majority"))) {
3537
+ entry.minimum_durability_level = couchbase::protocol::durability_level::majority;
3538
+ } else if (minimum_level == rb_id2sym(rb_intern("majority_and_persist_to_active"))) {
3539
+ entry.minimum_durability_level = couchbase::protocol::durability_level::majority_and_persist_to_active;
3540
+ } else if (minimum_level == rb_id2sym(rb_intern("persist_to_majority"))) {
3541
+ entry.minimum_durability_level = couchbase::protocol::durability_level::persist_to_majority;
3542
+ } else {
3543
+ return rb_exc_new_str(rb_eArgError, rb_sprintf("unknown durability level, given %+" PRIsVALUE, minimum_level));
3544
+ }
3545
+ } else {
3546
+ return rb_exc_new_str(rb_eArgError,
3547
+ rb_sprintf("bucket minimum durability level must be a Symbol, given %+" PRIsVALUE, minimum_level));
3188
3548
  }
3189
3549
  }
3190
3550
  }
3191
3551
  if (is_create) {
3192
3552
  VALUE conflict_resolution_type = rb_hash_aref(bucket, rb_id2sym(rb_intern("conflict_resolution_type")));
3193
3553
  if (!NIL_P(conflict_resolution_type)) {
3194
- Check_Type(conflict_resolution_type, T_SYMBOL);
3195
- if (conflict_resolution_type == rb_id2sym(rb_intern("timestamp"))) {
3196
- entry.conflict_resolution_type = couchbase::operations::bucket_settings::conflict_resolution_type::timestamp;
3197
- } else if (conflict_resolution_type == rb_id2sym(rb_intern("sequence_number"))) {
3198
- entry.conflict_resolution_type = couchbase::operations::bucket_settings::conflict_resolution_type::sequence_number;
3554
+ if (TYPE(conflict_resolution_type) == T_SYMBOL) {
3555
+ if (conflict_resolution_type == rb_id2sym(rb_intern("timestamp"))) {
3556
+ entry.conflict_resolution_type = couchbase::operations::bucket_settings::conflict_resolution_type::timestamp;
3557
+ } else if (conflict_resolution_type == rb_id2sym(rb_intern("sequence_number"))) {
3558
+ entry.conflict_resolution_type = couchbase::operations::bucket_settings::conflict_resolution_type::sequence_number;
3559
+ } else {
3560
+ return rb_exc_new_str(rb_eArgError,
3561
+ rb_sprintf("unknown conflict resolution type, given %+" PRIsVALUE, conflict_resolution_type));
3562
+ }
3199
3563
  } else {
3200
- rb_raise(rb_eArgError, "unknown conflict resolution type");
3564
+ return rb_exc_new_str(
3565
+ rb_eArgError,
3566
+ rb_sprintf("bucket conflict resulution type must be a Symbol, given %+" PRIsVALUE, conflict_resolution_type));
3201
3567
  }
3202
3568
  }
3203
3569
  }
3570
+ return Qnil;
3204
3571
  }
3205
3572
 
3206
3573
  static VALUE
@@ -3223,15 +3590,18 @@ cb_Backend_bucket_create(VALUE self, VALUE bucket_settings, VALUE timeout)
3223
3590
  if (!NIL_P(exc)) {
3224
3591
  break;
3225
3592
  }
3226
- cb__generate_bucket_settings(bucket_settings, req.bucket, true);
3593
+ exc = cb__generate_bucket_settings(bucket_settings, req.bucket, true);
3594
+ if (!NIL_P(exc)) {
3595
+ break;
3596
+ }
3227
3597
  auto barrier = std::make_shared<std::promise<couchbase::operations::bucket_create_response>>();
3228
3598
  auto f = barrier->get_future();
3229
3599
  backend->cluster->execute_http(
3230
3600
  req, [barrier](couchbase::operations::bucket_create_response&& resp) mutable { barrier->set_value(resp); });
3231
3601
  auto resp = f.get();
3232
- if (resp.ec) {
3602
+ if (resp.ctx.ec) {
3233
3603
  exc = cb__map_error_code(
3234
- resp.ec, fmt::format("unable to create bucket \"{}\" on the cluster ({})", req.bucket.name, resp.error_message));
3604
+ resp.ctx, fmt::format("unable to create bucket \"{}\" on the cluster ({})", req.bucket.name, resp.error_message));
3235
3605
  break;
3236
3606
  }
3237
3607
 
@@ -3260,15 +3630,18 @@ cb_Backend_bucket_update(VALUE self, VALUE bucket_settings, VALUE timeout)
3260
3630
  if (!NIL_P(exc)) {
3261
3631
  break;
3262
3632
  }
3263
- cb__generate_bucket_settings(bucket_settings, req.bucket, false);
3633
+ exc = cb__generate_bucket_settings(bucket_settings, req.bucket, false);
3634
+ if (!NIL_P(exc)) {
3635
+ break;
3636
+ }
3264
3637
  auto barrier = std::make_shared<std::promise<couchbase::operations::bucket_update_response>>();
3265
3638
  auto f = barrier->get_future();
3266
3639
  backend->cluster->execute_http(
3267
3640
  req, [barrier](couchbase::operations::bucket_update_response&& resp) mutable { barrier->set_value(resp); });
3268
3641
  auto resp = f.get();
3269
- if (resp.ec) {
3642
+ if (resp.ctx.ec) {
3270
3643
  exc = cb__map_error_code(
3271
- resp.ec, fmt::format("unable to update bucket \"{}\" on the cluster ({})", req.bucket.name, resp.error_message));
3644
+ resp.ctx, fmt::format("unable to update bucket \"{}\" on the cluster ({})", req.bucket.name, resp.error_message));
3272
3645
  break;
3273
3646
  }
3274
3647
  return Qtrue;
@@ -3303,8 +3676,8 @@ cb_Backend_bucket_drop(VALUE self, VALUE bucket_name, VALUE timeout)
3303
3676
  backend->cluster->execute_http(req,
3304
3677
  [barrier](couchbase::operations::bucket_drop_response&& resp) mutable { barrier->set_value(resp); });
3305
3678
  auto resp = f.get();
3306
- if (resp.ec) {
3307
- exc = cb__map_error_code(resp.ec, fmt::format("unable to remove bucket \"{}\" on the cluster", req.name));
3679
+ if (resp.ctx.ec) {
3680
+ exc = cb__map_error_code(resp.ctx, fmt::format("unable to remove bucket \"{}\" on the cluster", req.name));
3308
3681
  break;
3309
3682
  }
3310
3683
  return Qtrue;
@@ -3339,8 +3712,8 @@ cb_Backend_bucket_flush(VALUE self, VALUE bucket_name, VALUE timeout)
3339
3712
  backend->cluster->execute_http(
3340
3713
  req, [barrier](couchbase::operations::bucket_flush_response&& resp) mutable { barrier->set_value(resp); });
3341
3714
  auto resp = f.get();
3342
- if (resp.ec) {
3343
- exc = cb__map_error_code(resp.ec, fmt::format("unable to remove bucket \"{}\" on the cluster", req.name));
3715
+ if (resp.ctx.ec) {
3716
+ exc = cb__map_error_code(resp.ctx, fmt::format("unable to flush bucket \"{}\" on the cluster", req.name));
3344
3717
  break;
3345
3718
  }
3346
3719
 
@@ -3367,8 +3740,8 @@ cb__extract_bucket_settings(const couchbase::operations::bucket_settings& entry,
3367
3740
  rb_hash_aset(bucket, rb_id2sym(rb_intern("bucket_type")), Qnil);
3368
3741
  break;
3369
3742
  }
3370
- rb_hash_aset(bucket, rb_id2sym(rb_intern("name")), rb_str_new(entry.name.data(), static_cast<long>(entry.name.size())));
3371
- rb_hash_aset(bucket, rb_id2sym(rb_intern("uuid")), rb_str_new(entry.uuid.data(), static_cast<long>(entry.uuid.size())));
3743
+ rb_hash_aset(bucket, rb_id2sym(rb_intern("name")), rb_external_str_new(entry.name.data(), static_cast<long>(entry.name.size())));
3744
+ rb_hash_aset(bucket, rb_id2sym(rb_intern("uuid")), rb_external_str_new(entry.uuid.data(), static_cast<long>(entry.uuid.size())));
3372
3745
  rb_hash_aset(bucket, rb_id2sym(rb_intern("ram_quota_mb")), ULL2NUM(entry.ram_quota_mb));
3373
3746
  rb_hash_aset(bucket, rb_id2sym(rb_intern("max_expiry")), ULONG2NUM(entry.max_expiry));
3374
3747
  switch (entry.compression_mode) {
@@ -3416,17 +3789,34 @@ cb__extract_bucket_settings(const couchbase::operations::bucket_settings& entry,
3416
3789
  rb_hash_aset(bucket, rb_id2sym(rb_intern("conflict_resolution_type")), Qnil);
3417
3790
  break;
3418
3791
  }
3792
+ if (entry.minimum_durability_level) {
3793
+ switch (entry.minimum_durability_level.value()) {
3794
+ case couchbase::protocol::durability_level::none:
3795
+ rb_hash_aset(bucket, rb_id2sym(rb_intern("minimum_durability_level")), rb_id2sym(rb_intern("none")));
3796
+ break;
3797
+ case couchbase::protocol::durability_level::majority:
3798
+ rb_hash_aset(bucket, rb_id2sym(rb_intern("minimum_durability_level")), rb_id2sym(rb_intern("majority")));
3799
+ break;
3800
+ case couchbase::protocol::durability_level::majority_and_persist_to_active:
3801
+ rb_hash_aset(
3802
+ bucket, rb_id2sym(rb_intern("minimum_durability_level")), rb_id2sym(rb_intern("majority_and_persist_to_active")));
3803
+ break;
3804
+ case couchbase::protocol::durability_level::persist_to_majority:
3805
+ rb_hash_aset(bucket, rb_id2sym(rb_intern("minimum_durability_level")), rb_id2sym(rb_intern("persist_to_majority")));
3806
+ break;
3807
+ }
3808
+ }
3419
3809
  VALUE capabilities = rb_ary_new_capa(static_cast<long>(entry.capabilities.size()));
3420
3810
  for (const auto& capa : entry.capabilities) {
3421
- rb_ary_push(capabilities, rb_str_new(capa.data(), static_cast<long>(capa.size())));
3811
+ rb_ary_push(capabilities, rb_external_str_new(capa.data(), static_cast<long>(capa.size())));
3422
3812
  }
3423
3813
  rb_hash_aset(bucket, rb_id2sym(rb_intern("capabilities")), capabilities);
3424
3814
  VALUE nodes = rb_ary_new_capa(static_cast<long>(entry.nodes.size()));
3425
3815
  for (const auto& n : entry.nodes) {
3426
3816
  VALUE node = rb_hash_new();
3427
- rb_hash_aset(node, rb_id2sym(rb_intern("status")), rb_str_new(n.status.data(), static_cast<long>(n.status.size())));
3428
- rb_hash_aset(node, rb_id2sym(rb_intern("hostname")), rb_str_new(n.hostname.data(), static_cast<long>(n.hostname.size())));
3429
- rb_hash_aset(node, rb_id2sym(rb_intern("version")), rb_str_new(n.version.data(), static_cast<long>(n.version.size())));
3817
+ rb_hash_aset(node, rb_id2sym(rb_intern("status")), rb_external_str_new(n.status.data(), static_cast<long>(n.status.size())));
3818
+ rb_hash_aset(node, rb_id2sym(rb_intern("hostname")), rb_external_str_new(n.hostname.data(), static_cast<long>(n.hostname.size())));
3819
+ rb_hash_aset(node, rb_id2sym(rb_intern("version")), rb_external_str_new(n.version.data(), static_cast<long>(n.version.size())));
3430
3820
  rb_ary_push(nodes, node);
3431
3821
  }
3432
3822
  rb_hash_aset(bucket, rb_id2sym(rb_intern("nodes")), nodes);
@@ -3455,8 +3845,8 @@ cb_Backend_bucket_get_all(VALUE self, VALUE timeout)
3455
3845
  backend->cluster->execute_http(
3456
3846
  req, [barrier](couchbase::operations::bucket_get_all_response&& resp) mutable { barrier->set_value(resp); });
3457
3847
  auto resp = f.get();
3458
- if (resp.ec) {
3459
- exc = cb__map_error_code(resp.ec, "unable to get list of the buckets of the cluster");
3848
+ if (resp.ctx.ec) {
3849
+ exc = cb__map_error_code(resp.ctx, "unable to get list of the buckets of the cluster");
3460
3850
  break;
3461
3851
  }
3462
3852
 
@@ -3499,8 +3889,8 @@ cb_Backend_bucket_get(VALUE self, VALUE bucket_name, VALUE timeout)
3499
3889
  backend->cluster->execute_http(req,
3500
3890
  [barrier](couchbase::operations::bucket_get_response&& resp) mutable { barrier->set_value(resp); });
3501
3891
  auto resp = f.get();
3502
- if (resp.ec) {
3503
- exc = cb__map_error_code(resp.ec, fmt::format("unable to locate bucket \"{}\" on the cluster", req.name));
3892
+ if (resp.ctx.ec) {
3893
+ exc = cb__map_error_code(resp.ctx, fmt::format("unable to locate bucket \"{}\" on the cluster", req.name));
3504
3894
  break;
3505
3895
  }
3506
3896
 
@@ -3516,20 +3906,24 @@ cb_Backend_bucket_get(VALUE self, VALUE bucket_name, VALUE timeout)
3516
3906
  static void
3517
3907
  cb__extract_role(const couchbase::operations::rbac::role_and_description& entry, VALUE role)
3518
3908
  {
3519
- rb_hash_aset(role, rb_id2sym(rb_intern("name")), rb_str_new(entry.name.data(), static_cast<long>(entry.name.size())));
3520
- rb_hash_aset(
3521
- role, rb_id2sym(rb_intern("display_name")), rb_str_new(entry.display_name.data(), static_cast<long>(entry.display_name.size())));
3522
- rb_hash_aset(
3523
- role, rb_id2sym(rb_intern("description")), rb_str_new(entry.description.data(), static_cast<long>(entry.description.size())));
3909
+ rb_hash_aset(role, rb_id2sym(rb_intern("name")), rb_external_str_new(entry.name.data(), static_cast<long>(entry.name.size())));
3910
+ rb_hash_aset(role,
3911
+ rb_id2sym(rb_intern("display_name")),
3912
+ rb_external_str_new(entry.display_name.data(), static_cast<long>(entry.display_name.size())));
3913
+ rb_hash_aset(role,
3914
+ rb_id2sym(rb_intern("description")),
3915
+ rb_external_str_new(entry.description.data(), static_cast<long>(entry.description.size())));
3524
3916
  if (entry.bucket) {
3525
- rb_hash_aset(role, rb_id2sym(rb_intern("bucket")), rb_str_new(entry.bucket->data(), static_cast<long>(entry.bucket->size())));
3917
+ rb_hash_aset(
3918
+ role, rb_id2sym(rb_intern("bucket")), rb_external_str_new(entry.bucket->data(), static_cast<long>(entry.bucket->size())));
3526
3919
  }
3527
3920
  if (entry.scope) {
3528
- rb_hash_aset(role, rb_id2sym(rb_intern("scope")), rb_str_new(entry.scope->data(), static_cast<long>(entry.scope->size())));
3921
+ rb_hash_aset(role, rb_id2sym(rb_intern("scope")), rb_external_str_new(entry.scope->data(), static_cast<long>(entry.scope->size())));
3529
3922
  }
3530
3923
  if (entry.collection) {
3531
- rb_hash_aset(
3532
- role, rb_id2sym(rb_intern("collection")), rb_str_new(entry.collection->data(), static_cast<long>(entry.collection->size())));
3924
+ rb_hash_aset(role,
3925
+ rb_id2sym(rb_intern("collection")),
3926
+ rb_external_str_new(entry.collection->data(), static_cast<long>(entry.collection->size())));
3533
3927
  }
3534
3928
  }
3535
3929
 
@@ -3556,8 +3950,8 @@ cb_Backend_role_get_all(VALUE self, VALUE timeout)
3556
3950
  backend->cluster->execute_http(
3557
3951
  req, [barrier](couchbase::operations::role_get_all_response&& resp) mutable { barrier->set_value(resp); });
3558
3952
  auto resp = f.get();
3559
- if (resp.ec) {
3560
- exc = cb__map_error_code(resp.ec, "unable to fetch users");
3953
+ if (resp.ctx.ec) {
3954
+ exc = cb__map_error_code(resp.ctx, "unable to fetch roles");
3561
3955
  break;
3562
3956
  }
3563
3957
 
@@ -3576,7 +3970,8 @@ cb_Backend_role_get_all(VALUE self, VALUE timeout)
3576
3970
  static void
3577
3971
  cb__extract_user(const couchbase::operations::rbac::user_and_metadata& entry, VALUE user)
3578
3972
  {
3579
- rb_hash_aset(user, rb_id2sym(rb_intern("username")), rb_str_new(entry.username.data(), static_cast<long>(entry.username.size())));
3973
+ rb_hash_aset(
3974
+ user, rb_id2sym(rb_intern("username")), rb_external_str_new(entry.username.data(), static_cast<long>(entry.username.size())));
3580
3975
  switch (entry.domain) {
3581
3976
  case couchbase::operations::rbac::auth_domain::local:
3582
3977
  rb_hash_aset(user, rb_id2sym(rb_intern("domain")), rb_id2sym(rb_intern("local")));
@@ -3589,44 +3984,47 @@ cb__extract_user(const couchbase::operations::rbac::user_and_metadata& entry, VA
3589
3984
  }
3590
3985
  VALUE external_groups = rb_ary_new_capa(static_cast<long>(entry.external_groups.size()));
3591
3986
  for (const auto& group : entry.external_groups) {
3592
- rb_ary_push(external_groups, rb_str_new(group.data(), static_cast<long>(group.size())));
3987
+ rb_ary_push(external_groups, rb_external_str_new(group.data(), static_cast<long>(group.size())));
3593
3988
  }
3594
3989
  rb_hash_aset(user, rb_id2sym(rb_intern("external_groups")), external_groups);
3595
3990
  VALUE groups = rb_ary_new_capa(static_cast<long>(entry.groups.size()));
3596
3991
  for (const auto& group : entry.groups) {
3597
- rb_ary_push(groups, rb_str_new(group.data(), static_cast<long>(group.size())));
3992
+ rb_ary_push(groups, rb_external_str_new(group.data(), static_cast<long>(group.size())));
3598
3993
  }
3599
3994
  rb_hash_aset(user, rb_id2sym(rb_intern("groups")), groups);
3600
3995
  if (entry.display_name) {
3601
3996
  rb_hash_aset(user,
3602
3997
  rb_id2sym(rb_intern("display_name")),
3603
- rb_str_new(entry.display_name->data(), static_cast<long>(entry.display_name->size())));
3998
+ rb_external_str_new(entry.display_name->data(), static_cast<long>(entry.display_name->size())));
3604
3999
  }
3605
4000
  if (entry.password_changed) {
3606
4001
  rb_hash_aset(user,
3607
4002
  rb_id2sym(rb_intern("password_changed")),
3608
- rb_str_new(entry.password_changed->data(), static_cast<long>(entry.password_changed->size())));
4003
+ rb_external_str_new(entry.password_changed->data(), static_cast<long>(entry.password_changed->size())));
3609
4004
  }
3610
4005
  VALUE effective_roles = rb_ary_new_capa(static_cast<long>(entry.effective_roles.size()));
3611
4006
  for (const auto& er : entry.effective_roles) {
3612
4007
  VALUE role = rb_hash_new();
3613
- rb_hash_aset(role, rb_id2sym(rb_intern("name")), rb_str_new(er.name.data(), static_cast<long>(er.name.size())));
4008
+ rb_hash_aset(role, rb_id2sym(rb_intern("name")), rb_external_str_new(er.name.data(), static_cast<long>(er.name.size())));
3614
4009
  if (er.bucket) {
3615
- rb_hash_aset(role, rb_id2sym(rb_intern("bucket")), rb_str_new(er.bucket->data(), static_cast<long>(er.bucket->size())));
4010
+ rb_hash_aset(
4011
+ role, rb_id2sym(rb_intern("bucket")), rb_external_str_new(er.bucket->data(), static_cast<long>(er.bucket->size())));
3616
4012
  }
3617
4013
  if (er.scope) {
3618
- rb_hash_aset(role, rb_id2sym(rb_intern("scope")), rb_str_new(er.scope->data(), static_cast<long>(er.scope->size())));
4014
+ rb_hash_aset(role, rb_id2sym(rb_intern("scope")), rb_external_str_new(er.scope->data(), static_cast<long>(er.scope->size())));
3619
4015
  }
3620
4016
  if (er.collection) {
3621
- rb_hash_aset(
3622
- role, rb_id2sym(rb_intern("collection")), rb_str_new(er.collection->data(), static_cast<long>(er.collection->size())));
4017
+ rb_hash_aset(role,
4018
+ rb_id2sym(rb_intern("collection")),
4019
+ rb_external_str_new(er.collection->data(), static_cast<long>(er.collection->size())));
3623
4020
  }
3624
4021
  VALUE origins = rb_ary_new_capa(static_cast<long>(er.origins.size()));
3625
4022
  for (const auto& orig : er.origins) {
3626
4023
  VALUE origin = rb_hash_new();
3627
- rb_hash_aset(origin, rb_id2sym(rb_intern("type")), rb_str_new(orig.type.data(), static_cast<long>(orig.type.size())));
4024
+ rb_hash_aset(origin, rb_id2sym(rb_intern("type")), rb_external_str_new(orig.type.data(), static_cast<long>(orig.type.size())));
3628
4025
  if (orig.name) {
3629
- rb_hash_aset(origin, rb_id2sym(rb_intern("name")), rb_str_new(orig.name->data(), static_cast<long>(orig.name->size())));
4026
+ rb_hash_aset(
4027
+ origin, rb_id2sym(rb_intern("name")), rb_external_str_new(orig.name->data(), static_cast<long>(orig.name->size())));
3630
4028
  }
3631
4029
  rb_ary_push(origins, origin);
3632
4030
  }
@@ -3638,16 +4036,18 @@ cb__extract_user(const couchbase::operations::rbac::user_and_metadata& entry, VA
3638
4036
  VALUE roles = rb_ary_new_capa(static_cast<long>(entry.roles.size()));
3639
4037
  for (const auto& er : entry.roles) {
3640
4038
  VALUE role = rb_hash_new();
3641
- rb_hash_aset(role, rb_id2sym(rb_intern("name")), rb_str_new(er.name.data(), static_cast<long>(er.name.size())));
4039
+ rb_hash_aset(role, rb_id2sym(rb_intern("name")), rb_external_str_new(er.name.data(), static_cast<long>(er.name.size())));
3642
4040
  if (er.bucket) {
3643
- rb_hash_aset(role, rb_id2sym(rb_intern("bucket")), rb_str_new(er.bucket->data(), static_cast<long>(er.bucket->size())));
4041
+ rb_hash_aset(
4042
+ role, rb_id2sym(rb_intern("bucket")), rb_external_str_new(er.bucket->data(), static_cast<long>(er.bucket->size())));
3644
4043
  }
3645
4044
  if (er.scope) {
3646
- rb_hash_aset(role, rb_id2sym(rb_intern("scope")), rb_str_new(er.scope->data(), static_cast<long>(er.scope->size())));
4045
+ rb_hash_aset(role, rb_id2sym(rb_intern("scope")), rb_external_str_new(er.scope->data(), static_cast<long>(er.scope->size())));
3647
4046
  }
3648
4047
  if (er.collection) {
3649
- rb_hash_aset(
3650
- role, rb_id2sym(rb_intern("collection")), rb_str_new(er.collection->data(), static_cast<long>(er.collection->size())));
4048
+ rb_hash_aset(role,
4049
+ rb_id2sym(rb_intern("collection")),
4050
+ rb_external_str_new(er.collection->data(), static_cast<long>(er.collection->size())));
3651
4051
  }
3652
4052
  rb_ary_push(roles, role);
3653
4053
  }
@@ -3687,8 +4087,8 @@ cb_Backend_user_get_all(VALUE self, VALUE domain, VALUE timeout)
3687
4087
  backend->cluster->execute_http(
3688
4088
  req, [barrier](couchbase::operations::user_get_all_response&& resp) mutable { barrier->set_value(resp); });
3689
4089
  auto resp = f.get();
3690
- if (resp.ec) {
3691
- exc = cb__map_error_code(resp.ec, "unable to fetch users");
4090
+ if (resp.ctx.ec) {
4091
+ exc = cb__map_error_code(resp.ctx, "unable to fetch users");
3692
4092
  break;
3693
4093
  }
3694
4094
 
@@ -3739,8 +4139,8 @@ cb_Backend_user_get(VALUE self, VALUE domain, VALUE username, VALUE timeout)
3739
4139
  backend->cluster->execute_http(req,
3740
4140
  [barrier](couchbase::operations::user_get_response&& resp) mutable { barrier->set_value(resp); });
3741
4141
  auto resp = f.get();
3742
- if (resp.ec) {
3743
- exc = cb__map_error_code(resp.ec, fmt::format(R"(unable to fetch user "{}")", req.username).c_str());
4142
+ if (resp.ctx.ec) {
4143
+ exc = cb__map_error_code(resp.ctx, fmt::format(R"(unable to fetch user "{}")", req.username));
3744
4144
  break;
3745
4145
  }
3746
4146
 
@@ -3787,8 +4187,8 @@ cb_Backend_user_drop(VALUE self, VALUE domain, VALUE username, VALUE timeout)
3787
4187
  backend->cluster->execute_http(req,
3788
4188
  [barrier](couchbase::operations::user_drop_response&& resp) mutable { barrier->set_value(resp); });
3789
4189
  auto resp = f.get();
3790
- if (resp.ec) {
3791
- exc = cb__map_error_code(resp.ec, fmt::format(R"(unable to fetch user "{}")", req.username).c_str());
4190
+ if (resp.ctx.ec) {
4191
+ exc = cb__map_error_code(resp.ctx, fmt::format(R"(unable to fetch user "{}")", req.username));
3792
4192
  break;
3793
4193
  }
3794
4194
 
@@ -3883,9 +4283,9 @@ cb_Backend_user_upsert(VALUE self, VALUE domain, VALUE user, VALUE timeout)
3883
4283
  backend->cluster->execute_http(req,
3884
4284
  [barrier](couchbase::operations::user_upsert_response&& resp) mutable { barrier->set_value(resp); });
3885
4285
  auto resp = f.get();
3886
- if (resp.ec) {
3887
- exc = cb__map_error_code(
3888
- resp.ec, fmt::format(R"(unable to upsert user "{}" ({}))", req.user.username, fmt::join(resp.errors, ", ")).c_str());
4286
+ if (resp.ctx.ec) {
4287
+ exc = cb__map_error_code(resp.ctx,
4288
+ fmt::format(R"(unable to upsert user "{}" ({}))", req.user.username, fmt::join(resp.errors, ", ")));
3889
4289
  break;
3890
4290
  }
3891
4291
 
@@ -3898,29 +4298,32 @@ cb_Backend_user_upsert(VALUE self, VALUE domain, VALUE user, VALUE timeout)
3898
4298
  static void
3899
4299
  cb__extract_group(const couchbase::operations::rbac::group& entry, VALUE group)
3900
4300
  {
3901
- rb_hash_aset(group, rb_id2sym(rb_intern("name")), rb_str_new(entry.name.data(), static_cast<long>(entry.name.size())));
4301
+ rb_hash_aset(group, rb_id2sym(rb_intern("name")), rb_external_str_new(entry.name.data(), static_cast<long>(entry.name.size())));
3902
4302
  if (entry.description) {
3903
- rb_hash_aset(
3904
- group, rb_id2sym(rb_intern("description")), rb_str_new(entry.description->data(), static_cast<long>(entry.description->size())));
4303
+ rb_hash_aset(group,
4304
+ rb_id2sym(rb_intern("description")),
4305
+ rb_external_str_new(entry.description->data(), static_cast<long>(entry.description->size())));
3905
4306
  }
3906
4307
  if (entry.ldap_group_reference) {
3907
4308
  rb_hash_aset(group,
3908
4309
  rb_id2sym(rb_intern("ldap_group_reference")),
3909
- rb_str_new(entry.ldap_group_reference->data(), static_cast<long>(entry.ldap_group_reference->size())));
4310
+ rb_external_str_new(entry.ldap_group_reference->data(), static_cast<long>(entry.ldap_group_reference->size())));
3910
4311
  }
3911
4312
  VALUE roles = rb_ary_new_capa(static_cast<long>(entry.roles.size()));
3912
4313
  for (const auto& er : entry.roles) {
3913
4314
  VALUE role = rb_hash_new();
3914
- rb_hash_aset(role, rb_id2sym(rb_intern("name")), rb_str_new(er.name.data(), static_cast<long>(er.name.size())));
4315
+ rb_hash_aset(role, rb_id2sym(rb_intern("name")), rb_external_str_new(er.name.data(), static_cast<long>(er.name.size())));
3915
4316
  if (er.bucket) {
3916
- rb_hash_aset(role, rb_id2sym(rb_intern("bucket")), rb_str_new(er.bucket->data(), static_cast<long>(er.bucket->size())));
4317
+ rb_hash_aset(
4318
+ role, rb_id2sym(rb_intern("bucket")), rb_external_str_new(er.bucket->data(), static_cast<long>(er.bucket->size())));
3917
4319
  }
3918
4320
  if (er.scope) {
3919
- rb_hash_aset(role, rb_id2sym(rb_intern("scope")), rb_str_new(er.scope->data(), static_cast<long>(er.scope->size())));
4321
+ rb_hash_aset(role, rb_id2sym(rb_intern("scope")), rb_external_str_new(er.scope->data(), static_cast<long>(er.scope->size())));
3920
4322
  }
3921
4323
  if (er.collection) {
3922
- rb_hash_aset(
3923
- role, rb_id2sym(rb_intern("collection")), rb_str_new(er.collection->data(), static_cast<long>(er.collection->size())));
4324
+ rb_hash_aset(role,
4325
+ rb_id2sym(rb_intern("collection")),
4326
+ rb_external_str_new(er.collection->data(), static_cast<long>(er.collection->size())));
3924
4327
  }
3925
4328
  rb_ary_push(roles, role);
3926
4329
  }
@@ -3950,8 +4353,8 @@ cb_Backend_group_get_all(VALUE self, VALUE timeout)
3950
4353
  backend->cluster->execute_http(
3951
4354
  req, [barrier](couchbase::operations::group_get_all_response&& resp) mutable { barrier->set_value(resp); });
3952
4355
  auto resp = f.get();
3953
- if (resp.ec) {
3954
- exc = cb__map_error_code(resp.ec, "unable to fetch groups");
4356
+ if (resp.ctx.ec) {
4357
+ exc = cb__map_error_code(resp.ctx, "unable to fetch groups");
3955
4358
  break;
3956
4359
  }
3957
4360
 
@@ -3993,8 +4396,8 @@ cb_Backend_group_get(VALUE self, VALUE name, VALUE timeout)
3993
4396
  backend->cluster->execute_http(req,
3994
4397
  [barrier](couchbase::operations::group_get_response&& resp) mutable { barrier->set_value(resp); });
3995
4398
  auto resp = f.get();
3996
- if (resp.ec) {
3997
- exc = cb__map_error_code(resp.ec, fmt::format(R"(unable to fetch group "{}")", req.name));
4399
+ if (resp.ctx.ec) {
4400
+ exc = cb__map_error_code(resp.ctx, fmt::format(R"(unable to fetch group "{}")", req.name));
3998
4401
  break;
3999
4402
  }
4000
4403
 
@@ -4032,8 +4435,8 @@ cb_Backend_group_drop(VALUE self, VALUE name, VALUE timeout)
4032
4435
  backend->cluster->execute_http(req,
4033
4436
  [barrier](couchbase::operations::group_drop_response&& resp) mutable { barrier->set_value(resp); });
4034
4437
  auto resp = f.get();
4035
- if (resp.ec) {
4036
- exc = cb__map_error_code(resp.ec, fmt::format(R"(unable to drop group "{}")", req.name));
4438
+ if (resp.ctx.ec) {
4439
+ exc = cb__map_error_code(resp.ctx, fmt::format(R"(unable to drop group "{}")", req.name));
4037
4440
  break;
4038
4441
  }
4039
4442
 
@@ -4108,9 +4511,9 @@ cb_Backend_group_upsert(VALUE self, VALUE group, VALUE timeout)
4108
4511
  backend->cluster->execute_http(
4109
4512
  req, [barrier](couchbase::operations::group_upsert_response&& resp) mutable { barrier->set_value(resp); });
4110
4513
  auto resp = f.get();
4111
- if (resp.ec) {
4112
- exc = cb__map_error_code(
4113
- resp.ec, fmt::format(R"(unable to upsert group "{}" ({}))", req.group.name, fmt::join(resp.errors, ", ")).c_str());
4514
+ if (resp.ctx.ec) {
4515
+ exc = cb__map_error_code(resp.ctx,
4516
+ fmt::format(R"(unable to upsert group "{}" ({}))", req.group.name, fmt::join(resp.errors, ", ")));
4114
4517
  break;
4115
4518
  }
4116
4519
 
@@ -4139,8 +4542,8 @@ cb_Backend_cluster_enable_developer_preview(VALUE self)
4139
4542
  backend->cluster->execute_http(
4140
4543
  req, [barrier](couchbase::operations::cluster_developer_preview_enable_response&& resp) mutable { barrier->set_value(resp); });
4141
4544
  auto resp = f.get();
4142
- if (resp.ec) {
4143
- exc = cb__map_error_code(resp.ec, fmt::format("unable to enable developer preview for this cluster"));
4545
+ if (resp.ctx.ec) {
4546
+ exc = cb__map_error_code(resp.ctx, "unable to enable developer preview for this cluster");
4144
4547
  break;
4145
4548
  }
4146
4549
  spdlog::critical(
@@ -4178,8 +4581,8 @@ cb_Backend_scope_get_all(VALUE self, VALUE bucket_name, VALUE timeout)
4178
4581
  backend->cluster->execute_http(
4179
4582
  req, [barrier](couchbase::operations::scope_get_all_response&& resp) mutable { barrier->set_value(resp); });
4180
4583
  auto resp = f.get();
4181
- if (resp.ec) {
4182
- exc = cb__map_error_code(resp.ec, fmt::format("unable to get list of the scopes of the bucket \"{}\"", req.bucket_name));
4584
+ if (resp.ctx.ec) {
4585
+ exc = cb__map_error_code(resp.ctx, fmt::format("unable to get list of the scopes of the bucket \"{}\"", req.bucket_name));
4183
4586
  break;
4184
4587
  }
4185
4588
 
@@ -4189,12 +4592,13 @@ cb_Backend_scope_get_all(VALUE self, VALUE bucket_name, VALUE timeout)
4189
4592
  for (const auto& s : resp.manifest.scopes) {
4190
4593
  VALUE scope = rb_hash_new();
4191
4594
  rb_hash_aset(scope, rb_id2sym(rb_intern("uid")), ULL2NUM(s.uid));
4192
- rb_hash_aset(scope, rb_id2sym(rb_intern("name")), rb_str_new(s.name.data(), static_cast<long>(s.name.size())));
4595
+ rb_hash_aset(scope, rb_id2sym(rb_intern("name")), rb_external_str_new(s.name.data(), static_cast<long>(s.name.size())));
4193
4596
  VALUE collections = rb_ary_new_capa(static_cast<long>(s.collections.size()));
4194
4597
  for (const auto& c : s.collections) {
4195
4598
  VALUE collection = rb_hash_new();
4196
4599
  rb_hash_aset(collection, rb_id2sym(rb_intern("uid")), ULL2NUM(c.uid));
4197
- rb_hash_aset(collection, rb_id2sym(rb_intern("name")), rb_str_new(c.name.data(), static_cast<long>(c.name.size())));
4600
+ rb_hash_aset(
4601
+ collection, rb_id2sym(rb_intern("name")), rb_external_str_new(c.name.data(), static_cast<long>(c.name.size())));
4198
4602
  rb_ary_push(collections, collection);
4199
4603
  }
4200
4604
  rb_hash_aset(scope, rb_id2sym(rb_intern("collections")), collections);
@@ -4234,8 +4638,8 @@ cb_Backend_collections_manifest_get(VALUE self, VALUE bucket_name, VALUE timeout
4234
4638
  backend->cluster->execute(
4235
4639
  req, [barrier](couchbase::operations::collections_manifest_get_response&& resp) mutable { barrier->set_value(resp); });
4236
4640
  auto resp = f.get();
4237
- if (resp.ec) {
4238
- exc = cb__map_error_code(resp.ec, fmt::format("unable to get collections manifest of the bucket \"{}\"", req.id.bucket));
4641
+ if (resp.ctx.ec) {
4642
+ exc = cb__map_error_code(resp.ctx, fmt::format("unable to get collections manifest of the bucket \"{}\"", req.id.bucket));
4239
4643
  break;
4240
4644
  }
4241
4645
 
@@ -4245,12 +4649,13 @@ cb_Backend_collections_manifest_get(VALUE self, VALUE bucket_name, VALUE timeout
4245
4649
  for (const auto& s : resp.manifest.scopes) {
4246
4650
  VALUE scope = rb_hash_new();
4247
4651
  rb_hash_aset(scope, rb_id2sym(rb_intern("uid")), ULL2NUM(s.uid));
4248
- rb_hash_aset(scope, rb_id2sym(rb_intern("name")), rb_str_new(s.name.data(), static_cast<long>(s.name.size())));
4652
+ rb_hash_aset(scope, rb_id2sym(rb_intern("name")), rb_external_str_new(s.name.data(), static_cast<long>(s.name.size())));
4249
4653
  VALUE collections = rb_ary_new_capa(static_cast<long>(s.collections.size()));
4250
4654
  for (const auto& c : s.collections) {
4251
4655
  VALUE collection = rb_hash_new();
4252
4656
  rb_hash_aset(collection, rb_id2sym(rb_intern("uid")), ULL2NUM(c.uid));
4253
- rb_hash_aset(collection, rb_id2sym(rb_intern("name")), rb_str_new(c.name.data(), static_cast<long>(c.name.size())));
4657
+ rb_hash_aset(
4658
+ collection, rb_id2sym(rb_intern("name")), rb_external_str_new(c.name.data(), static_cast<long>(c.name.size())));
4254
4659
  rb_ary_push(collections, collection);
4255
4660
  }
4256
4661
  rb_hash_aset(scope, rb_id2sym(rb_intern("collections")), collections);
@@ -4292,8 +4697,8 @@ cb_Backend_scope_create(VALUE self, VALUE bucket_name, VALUE scope_name, VALUE t
4292
4697
  backend->cluster->execute_http(
4293
4698
  req, [barrier](couchbase::operations::scope_create_response&& resp) mutable { barrier->set_value(resp); });
4294
4699
  auto resp = f.get();
4295
- if (resp.ec) {
4296
- exc = cb__map_error_code(resp.ec,
4700
+ if (resp.ctx.ec) {
4701
+ exc = cb__map_error_code(resp.ctx,
4297
4702
  fmt::format(R"(unable to create the scope "{}" on the bucket "{}")", req.scope_name, req.bucket_name));
4298
4703
  break;
4299
4704
  }
@@ -4331,9 +4736,9 @@ cb_Backend_scope_drop(VALUE self, VALUE bucket_name, VALUE scope_name, VALUE tim
4331
4736
  backend->cluster->execute_http(req,
4332
4737
  [barrier](couchbase::operations::scope_drop_response&& resp) mutable { barrier->set_value(resp); });
4333
4738
  auto resp = f.get();
4334
- if (resp.ec) {
4335
- exc = cb__map_error_code(resp.ec,
4336
- fmt::format("unable to drop the scope \"{}\" on the bucket \"{}\"", req.scope_name, req.bucket_name));
4739
+ if (resp.ctx.ec) {
4740
+ exc = cb__map_error_code(resp.ctx,
4741
+ fmt::format(R"(unable to drop the scope "{}" on the bucket "{}")", req.scope_name, req.bucket_name));
4337
4742
  break;
4338
4743
  }
4339
4744
  return ULL2NUM(resp.uid);
@@ -4377,9 +4782,9 @@ cb_Backend_collection_create(VALUE self, VALUE bucket_name, VALUE scope_name, VA
4377
4782
  backend->cluster->execute_http(
4378
4783
  req, [barrier](couchbase::operations::collection_create_response&& resp) mutable { barrier->set_value(resp); });
4379
4784
  auto resp = f.get();
4380
- if (resp.ec) {
4785
+ if (resp.ctx.ec) {
4381
4786
  exc = cb__map_error_code(
4382
- resp.ec,
4787
+ resp.ctx,
4383
4788
  fmt::format(
4384
4789
  R"(unable create the collection "{}.{}" on the bucket "{}")", req.scope_name, req.collection_name, req.bucket_name));
4385
4790
  break;
@@ -4421,9 +4826,9 @@ cb_Backend_collection_drop(VALUE self, VALUE bucket_name, VALUE scope_name, VALU
4421
4826
  backend->cluster->execute_http(
4422
4827
  req, [barrier](couchbase::operations::collection_drop_response&& resp) mutable { barrier->set_value(resp); });
4423
4828
  auto resp = f.get();
4424
- if (resp.ec) {
4829
+ if (resp.ctx.ec) {
4425
4830
  exc = cb__map_error_code(
4426
- resp.ec,
4831
+ resp.ctx,
4427
4832
  fmt::format(
4428
4833
  R"(unable to drop the collection "{}.{}" on the bucket "{}")", req.scope_name, req.collection_name, req.bucket_name));
4429
4834
  break;
@@ -4460,43 +4865,49 @@ cb_Backend_query_index_get_all(VALUE self, VALUE bucket_name, VALUE timeout)
4460
4865
  backend->cluster->execute_http(
4461
4866
  req, [barrier](couchbase::operations::query_index_get_all_response&& resp) mutable { barrier->set_value(resp); });
4462
4867
  auto resp = f.get();
4463
- if (resp.ec) {
4464
- exc = cb__map_error_code(resp.ec, fmt::format("unable to get list of the indexes of the bucket \"{}\"", req.bucket_name));
4868
+ if (resp.ctx.ec) {
4869
+ exc = cb__map_error_code(resp.ctx, fmt::format("unable to get list of the indexes of the bucket \"{}\"", req.bucket_name));
4465
4870
  break;
4466
4871
  }
4467
4872
 
4468
4873
  VALUE res = rb_hash_new();
4469
- rb_hash_aset(res, rb_id2sym(rb_intern("status")), rb_str_new(resp.status.data(), static_cast<long>(resp.status.size())));
4874
+ rb_hash_aset(res, rb_id2sym(rb_intern("status")), rb_external_str_new(resp.status.data(), static_cast<long>(resp.status.size())));
4470
4875
  VALUE indexes = rb_ary_new_capa(static_cast<long>(resp.indexes.size()));
4471
4876
  for (const auto& idx : resp.indexes) {
4472
4877
  VALUE index = rb_hash_new();
4473
- rb_hash_aset(index, rb_id2sym(rb_intern("id")), rb_str_new(idx.id.data(), static_cast<long>(idx.id.size())));
4474
- rb_hash_aset(index, rb_id2sym(rb_intern("state")), rb_str_new(idx.state.data(), static_cast<long>(idx.state.size())));
4475
- rb_hash_aset(index, rb_id2sym(rb_intern("name")), rb_str_new(idx.name.data(), static_cast<long>(idx.name.size())));
4476
- rb_hash_aset(
4477
- index, rb_id2sym(rb_intern("datastore_id")), rb_str_new(idx.datastore_id.data(), static_cast<long>(idx.datastore_id.size())));
4478
- rb_hash_aset(
4479
- index, rb_id2sym(rb_intern("keyspace_id")), rb_str_new(idx.keyspace_id.data(), static_cast<long>(idx.keyspace_id.size())));
4480
- rb_hash_aset(
4481
- index, rb_id2sym(rb_intern("namespace_id")), rb_str_new(idx.namespace_id.data(), static_cast<long>(idx.namespace_id.size())));
4482
- rb_hash_aset(index, rb_id2sym(rb_intern("type")), rb_str_new(idx.type.data(), static_cast<long>(idx.type.size())));
4878
+ rb_hash_aset(index, rb_id2sym(rb_intern("id")), rb_external_str_new(idx.id.data(), static_cast<long>(idx.id.size())));
4879
+ rb_hash_aset(index, rb_id2sym(rb_intern("state")), rb_external_str_new(idx.state.data(), static_cast<long>(idx.state.size())));
4880
+ rb_hash_aset(index, rb_id2sym(rb_intern("name")), rb_external_str_new(idx.name.data(), static_cast<long>(idx.name.size())));
4881
+ rb_hash_aset(index,
4882
+ rb_id2sym(rb_intern("datastore_id")),
4883
+ rb_external_str_new(idx.datastore_id.data(), static_cast<long>(idx.datastore_id.size())));
4884
+ rb_hash_aset(index,
4885
+ rb_id2sym(rb_intern("keyspace_id")),
4886
+ rb_external_str_new(idx.keyspace_id.data(), static_cast<long>(idx.keyspace_id.size())));
4887
+ rb_hash_aset(index,
4888
+ rb_id2sym(rb_intern("namespace_id")),
4889
+ rb_external_str_new(idx.namespace_id.data(), static_cast<long>(idx.namespace_id.size())));
4890
+ rb_hash_aset(index, rb_id2sym(rb_intern("type")), rb_external_str_new(idx.type.data(), static_cast<long>(idx.type.size())));
4483
4891
  rb_hash_aset(index, rb_id2sym(rb_intern("is_primary")), idx.is_primary ? Qtrue : Qfalse);
4484
4892
  VALUE index_key = rb_ary_new_capa(static_cast<long>(idx.index_key.size()));
4485
4893
  for (const auto& key : idx.index_key) {
4486
- rb_ary_push(index_key, rb_str_new(key.data(), static_cast<long>(key.size())));
4894
+ rb_ary_push(index_key, rb_external_str_new(key.data(), static_cast<long>(key.size())));
4487
4895
  }
4488
4896
  rb_hash_aset(index, rb_id2sym(rb_intern("index_key")), index_key);
4489
4897
  if (idx.scope_id) {
4490
- rb_hash_aset(
4491
- index, rb_id2sym(rb_intern("scope_id")), rb_str_new(idx.scope_id->data(), static_cast<long>(idx.scope_id->size())));
4898
+ rb_hash_aset(index,
4899
+ rb_id2sym(rb_intern("scope_id")),
4900
+ rb_external_str_new(idx.scope_id->data(), static_cast<long>(idx.scope_id->size())));
4492
4901
  }
4493
4902
  if (idx.bucket_id) {
4494
- rb_hash_aset(
4495
- index, rb_id2sym(rb_intern("bucket_id")), rb_str_new(idx.bucket_id->data(), static_cast<long>(idx.bucket_id->size())));
4903
+ rb_hash_aset(index,
4904
+ rb_id2sym(rb_intern("bucket_id")),
4905
+ rb_external_str_new(idx.bucket_id->data(), static_cast<long>(idx.bucket_id->size())));
4496
4906
  }
4497
4907
  if (idx.condition) {
4498
- rb_hash_aset(
4499
- index, rb_id2sym(rb_intern("condition")), rb_str_new(idx.condition->data(), static_cast<long>(idx.condition->size())));
4908
+ rb_hash_aset(index,
4909
+ rb_id2sym(rb_intern("condition")),
4910
+ rb_external_str_new(idx.condition->data(), static_cast<long>(idx.condition->size())));
4500
4911
  }
4501
4912
  rb_ary_push(indexes, index);
4502
4913
  }
@@ -4577,29 +4988,30 @@ cb_Backend_query_index_create(VALUE self, VALUE bucket_name, VALUE index_name, V
4577
4988
  backend->cluster->execute_http(
4578
4989
  req, [barrier](couchbase::operations::query_index_create_response&& resp) mutable { barrier->set_value(resp); });
4579
4990
  auto resp = f.get();
4580
- if (resp.ec) {
4991
+ if (resp.ctx.ec) {
4581
4992
  if (!resp.errors.empty()) {
4582
4993
  const auto& first_error = resp.errors.front();
4583
- exc = cb__map_error_code(resp.ec,
4994
+ exc = cb__map_error_code(resp.ctx,
4584
4995
  fmt::format(R"(unable to create index "{}" on the bucket "{}" ({}: {}))",
4585
4996
  req.index_name,
4586
4997
  req.bucket_name,
4587
4998
  first_error.code,
4588
4999
  first_error.message));
4589
5000
  } else {
4590
- exc = cb__map_error_code(resp.ec,
5001
+ exc = cb__map_error_code(resp.ctx,
4591
5002
  fmt::format(R"(unable to create index "{}" on the bucket "{}")", req.index_name, req.bucket_name));
4592
5003
  }
4593
5004
  break;
4594
5005
  }
4595
5006
  VALUE res = rb_hash_new();
4596
- rb_hash_aset(res, rb_id2sym(rb_intern("status")), rb_str_new(resp.status.data(), static_cast<long>(resp.status.size())));
5007
+ rb_hash_aset(res, rb_id2sym(rb_intern("status")), rb_external_str_new(resp.status.data(), static_cast<long>(resp.status.size())));
4597
5008
  if (!resp.errors.empty()) {
4598
5009
  VALUE errors = rb_ary_new_capa(static_cast<long>(resp.errors.size()));
4599
5010
  for (const auto& err : resp.errors) {
4600
5011
  VALUE error = rb_hash_new();
4601
5012
  rb_hash_aset(error, rb_id2sym(rb_intern("code")), ULL2NUM(err.code));
4602
- rb_hash_aset(error, rb_id2sym(rb_intern("message")), rb_str_new(err.message.data(), static_cast<long>(err.message.size())));
5013
+ rb_hash_aset(
5014
+ error, rb_id2sym(rb_intern("message")), rb_external_str_new(err.message.data(), static_cast<long>(err.message.size())));
4603
5015
  rb_ary_push(errors, error);
4604
5016
  }
4605
5017
  rb_hash_aset(res, rb_id2sym(rb_intern("errors")), errors);
@@ -4656,29 +5068,30 @@ cb_Backend_query_index_drop(VALUE self, VALUE bucket_name, VALUE index_name, VAL
4656
5068
  backend->cluster->execute_http(
4657
5069
  req, [barrier](couchbase::operations::query_index_drop_response&& resp) mutable { barrier->set_value(resp); });
4658
5070
  auto resp = f.get();
4659
- if (resp.ec) {
5071
+ if (resp.ctx.ec) {
4660
5072
  if (!resp.errors.empty()) {
4661
5073
  const auto& first_error = resp.errors.front();
4662
- exc = cb__map_error_code(resp.ec,
5074
+ exc = cb__map_error_code(resp.ctx,
4663
5075
  fmt::format(R"(unable to drop index "{}" on the bucket "{}" ({}: {}))",
4664
5076
  req.index_name,
4665
5077
  req.bucket_name,
4666
5078
  first_error.code,
4667
5079
  first_error.message));
4668
5080
  } else {
4669
- exc = cb__map_error_code(resp.ec,
5081
+ exc = cb__map_error_code(resp.ctx,
4670
5082
  fmt::format(R"(unable to drop index "{}" on the bucket "{}")", req.index_name, req.bucket_name));
4671
5083
  }
4672
5084
  break;
4673
5085
  }
4674
5086
  VALUE res = rb_hash_new();
4675
- rb_hash_aset(res, rb_id2sym(rb_intern("status")), rb_str_new(resp.status.data(), static_cast<long>(resp.status.size())));
5087
+ rb_hash_aset(res, rb_id2sym(rb_intern("status")), rb_external_str_new(resp.status.data(), static_cast<long>(resp.status.size())));
4676
5088
  if (!resp.errors.empty()) {
4677
5089
  VALUE errors = rb_ary_new_capa(static_cast<long>(resp.errors.size()));
4678
5090
  for (const auto& err : resp.errors) {
4679
5091
  VALUE error = rb_hash_new();
4680
5092
  rb_hash_aset(error, rb_id2sym(rb_intern("code")), ULL2NUM(err.code));
4681
- rb_hash_aset(error, rb_id2sym(rb_intern("message")), rb_str_new(err.message.data(), static_cast<long>(err.message.size())));
5093
+ rb_hash_aset(
5094
+ error, rb_id2sym(rb_intern("message")), rb_external_str_new(err.message.data(), static_cast<long>(err.message.size())));
4682
5095
  rb_ary_push(errors, error);
4683
5096
  }
4684
5097
  rb_hash_aset(res, rb_id2sym(rb_intern("errors")), errors);
@@ -4751,28 +5164,29 @@ cb_Backend_query_index_create_primary(VALUE self, VALUE bucket_name, VALUE optio
4751
5164
  backend->cluster->execute_http(
4752
5165
  req, [barrier](couchbase::operations::query_index_create_response&& resp) mutable { barrier->set_value(resp); });
4753
5166
  auto resp = f.get();
4754
- if (resp.ec) {
5167
+ if (resp.ctx.ec) {
4755
5168
  if (!resp.errors.empty()) {
4756
5169
  const auto& first_error = resp.errors.front();
4757
- exc = cb__map_error_code(resp.ec,
5170
+ exc = cb__map_error_code(resp.ctx,
4758
5171
  fmt::format(R"(unable to create primary index on the bucket "{}" ({}: {}))",
4759
5172
  req.bucket_name,
4760
5173
  first_error.code,
4761
5174
  first_error.message));
4762
5175
  } else {
4763
5176
  exc = cb__map_error_code(
4764
- resp.ec, fmt::format(R"(unable to create primary index on the bucket "{}")", req.index_name, req.bucket_name));
5177
+ resp.ctx, fmt::format(R"(unable to create primary index on the bucket "{}")", req.index_name, req.bucket_name));
4765
5178
  }
4766
5179
  break;
4767
5180
  }
4768
5181
  VALUE res = rb_hash_new();
4769
- rb_hash_aset(res, rb_id2sym(rb_intern("status")), rb_str_new(resp.status.data(), static_cast<long>(resp.status.size())));
5182
+ rb_hash_aset(res, rb_id2sym(rb_intern("status")), rb_external_str_new(resp.status.data(), static_cast<long>(resp.status.size())));
4770
5183
  if (!resp.errors.empty()) {
4771
5184
  VALUE errors = rb_ary_new_capa(static_cast<long>(resp.errors.size()));
4772
5185
  for (const auto& err : resp.errors) {
4773
5186
  VALUE error = rb_hash_new();
4774
5187
  rb_hash_aset(error, rb_id2sym(rb_intern("code")), ULL2NUM(err.code));
4775
- rb_hash_aset(error, rb_id2sym(rb_intern("message")), rb_str_new(err.message.data(), static_cast<long>(err.message.size())));
5188
+ rb_hash_aset(
5189
+ error, rb_id2sym(rb_intern("message")), rb_external_str_new(err.message.data(), static_cast<long>(err.message.size())));
4776
5190
  rb_ary_push(errors, error);
4777
5191
  }
4778
5192
  rb_hash_aset(res, rb_id2sym(rb_intern("errors")), errors);
@@ -4834,26 +5248,27 @@ cb_Backend_query_index_drop_primary(VALUE self, VALUE bucket_name, VALUE options
4834
5248
  backend->cluster->execute_http(
4835
5249
  req, [barrier](couchbase::operations::query_index_drop_response&& resp) mutable { barrier->set_value(resp); });
4836
5250
  auto resp = f.get();
4837
- if (resp.ec) {
5251
+ if (resp.ctx.ec) {
4838
5252
  if (!resp.errors.empty()) {
4839
5253
  const auto& first_error = resp.errors.front();
4840
5254
  exc = cb__map_error_code(
4841
- resp.ec,
5255
+ resp.ctx,
4842
5256
  fmt::format(
4843
5257
  R"(unable to drop primary index on the bucket "{}" ({}: {}))", req.bucket_name, first_error.code, first_error.message));
4844
5258
  } else {
4845
- exc = cb__map_error_code(resp.ec, fmt::format(R"(unable to drop primary index on the bucket "{}")", req.bucket_name));
5259
+ exc = cb__map_error_code(resp.ctx, fmt::format(R"(unable to drop primary index on the bucket "{}")", req.bucket_name));
4846
5260
  }
4847
5261
  break;
4848
5262
  }
4849
5263
  VALUE res = rb_hash_new();
4850
- rb_hash_aset(res, rb_id2sym(rb_intern("status")), rb_str_new(resp.status.data(), static_cast<long>(resp.status.size())));
5264
+ rb_hash_aset(res, rb_id2sym(rb_intern("status")), rb_external_str_new(resp.status.data(), static_cast<long>(resp.status.size())));
4851
5265
  if (!resp.errors.empty()) {
4852
5266
  VALUE errors = rb_ary_new_capa(static_cast<long>(resp.errors.size()));
4853
5267
  for (const auto& err : resp.errors) {
4854
5268
  VALUE error = rb_hash_new();
4855
5269
  rb_hash_aset(error, rb_id2sym(rb_intern("code")), ULL2NUM(err.code));
4856
- rb_hash_aset(error, rb_id2sym(rb_intern("message")), rb_str_new(err.message.data(), static_cast<long>(err.message.size())));
5270
+ rb_hash_aset(
5271
+ error, rb_id2sym(rb_intern("message")), rb_external_str_new(err.message.data(), static_cast<long>(err.message.size())));
4857
5272
  rb_ary_push(errors, error);
4858
5273
  }
4859
5274
  rb_hash_aset(res, rb_id2sym(rb_intern("errors")), errors);
@@ -4890,17 +5305,17 @@ cb_Backend_query_index_build_deferred(VALUE self, VALUE bucket_name, VALUE timeo
4890
5305
  backend->cluster->execute_http(
4891
5306
  req, [barrier](couchbase::operations::query_index_build_deferred_response&& resp) mutable { barrier->set_value(resp); });
4892
5307
  auto resp = f.get();
4893
- if (resp.ec) {
5308
+ if (resp.ctx.ec) {
4894
5309
  if (!resp.errors.empty()) {
4895
5310
  const auto& first_error = resp.errors.front();
4896
5311
  exc = cb__map_error_code(
4897
- resp.ec,
5312
+ resp.ctx,
4898
5313
  fmt::format(
4899
5314
  R"(unable to drop primary index on the bucket "{}" ({}: {}))", req.bucket_name, first_error.code, first_error.message));
4900
5315
 
4901
5316
  } else {
4902
5317
  exc = cb__map_error_code(
4903
- resp.ec, fmt::format("unable to trigger build for deferred indexes for the bucket \"{}\"", req.bucket_name));
5318
+ resp.ctx, fmt::format("unable to trigger build for deferred indexes for the bucket \"{}\"", req.bucket_name));
4904
5319
  }
4905
5320
  break;
4906
5321
  }
@@ -4934,31 +5349,35 @@ cb_Backend_query_index_watch(VALUE self, VALUE bucket_name, VALUE index_names, V
4934
5349
  static void
4935
5350
  cb__extract_search_index(VALUE index, const couchbase::operations::search_index& idx)
4936
5351
  {
4937
- rb_hash_aset(index, rb_id2sym(rb_intern("uuid")), rb_str_new(idx.uuid.data(), static_cast<long>(idx.uuid.size())));
4938
- rb_hash_aset(index, rb_id2sym(rb_intern("name")), rb_str_new(idx.name.data(), static_cast<long>(idx.name.size())));
4939
- rb_hash_aset(index, rb_id2sym(rb_intern("type")), rb_str_new(idx.type.data(), static_cast<long>(idx.type.size())));
5352
+ rb_hash_aset(index, rb_id2sym(rb_intern("uuid")), rb_external_str_new(idx.uuid.data(), static_cast<long>(idx.uuid.size())));
5353
+ rb_hash_aset(index, rb_id2sym(rb_intern("name")), rb_external_str_new(idx.name.data(), static_cast<long>(idx.name.size())));
5354
+ rb_hash_aset(index, rb_id2sym(rb_intern("type")), rb_external_str_new(idx.type.data(), static_cast<long>(idx.type.size())));
4940
5355
  if (!idx.params_json.empty()) {
4941
- rb_hash_aset(index, rb_id2sym(rb_intern("params")), rb_str_new(idx.params_json.data(), static_cast<long>(idx.params_json.size())));
5356
+ rb_hash_aset(
5357
+ index, rb_id2sym(rb_intern("params")), rb_external_str_new(idx.params_json.data(), static_cast<long>(idx.params_json.size())));
4942
5358
  }
4943
5359
 
4944
5360
  if (!idx.source_uuid.empty()) {
4945
- rb_hash_aset(
4946
- index, rb_id2sym(rb_intern("source_uuid")), rb_str_new(idx.source_uuid.data(), static_cast<long>(idx.source_uuid.size())));
5361
+ rb_hash_aset(index,
5362
+ rb_id2sym(rb_intern("source_uuid")),
5363
+ rb_external_str_new(idx.source_uuid.data(), static_cast<long>(idx.source_uuid.size())));
4947
5364
  }
4948
5365
  if (!idx.source_name.empty()) {
4949
- rb_hash_aset(
4950
- index, rb_id2sym(rb_intern("source_name")), rb_str_new(idx.source_name.data(), static_cast<long>(idx.source_name.size())));
5366
+ rb_hash_aset(index,
5367
+ rb_id2sym(rb_intern("source_name")),
5368
+ rb_external_str_new(idx.source_name.data(), static_cast<long>(idx.source_name.size())));
4951
5369
  }
4952
- rb_hash_aset(index, rb_id2sym(rb_intern("source_type")), rb_str_new(idx.source_type.data(), static_cast<long>(idx.source_type.size())));
5370
+ rb_hash_aset(
5371
+ index, rb_id2sym(rb_intern("source_type")), rb_external_str_new(idx.source_type.data(), static_cast<long>(idx.source_type.size())));
4953
5372
  if (!idx.source_params_json.empty()) {
4954
5373
  rb_hash_aset(index,
4955
5374
  rb_id2sym(rb_intern("source_params")),
4956
- rb_str_new(idx.source_params_json.data(), static_cast<long>(idx.source_params_json.size())));
5375
+ rb_external_str_new(idx.source_params_json.data(), static_cast<long>(idx.source_params_json.size())));
4957
5376
  }
4958
5377
  if (!idx.plan_params_json.empty()) {
4959
5378
  rb_hash_aset(index,
4960
5379
  rb_id2sym(rb_intern("plan_params")),
4961
- rb_str_new(idx.plan_params_json.data(), static_cast<long>(idx.plan_params_json.size())));
5380
+ rb_external_str_new(idx.plan_params_json.data(), static_cast<long>(idx.plan_params_json.size())));
4962
5381
  }
4963
5382
  }
4964
5383
 
@@ -4985,14 +5404,15 @@ cb_Backend_search_index_get_all(VALUE self, VALUE timeout)
4985
5404
  backend->cluster->execute_http(
4986
5405
  req, [barrier](couchbase::operations::search_index_get_all_response&& resp) mutable { barrier->set_value(resp); });
4987
5406
  auto resp = f.get();
4988
- if (resp.ec) {
4989
- exc = cb__map_error_code(resp.ec, "unable to get list of the search indexes");
5407
+ if (resp.ctx.ec) {
5408
+ exc = cb__map_error_code(resp.ctx, "unable to get list of the search indexes");
4990
5409
  break;
4991
5410
  }
4992
5411
  VALUE res = rb_hash_new();
4993
- rb_hash_aset(res, rb_id2sym(rb_intern("status")), rb_str_new(resp.status.data(), static_cast<long>(resp.status.size())));
4994
- rb_hash_aset(
4995
- res, rb_id2sym(rb_intern("impl_version")), rb_str_new(resp.impl_version.data(), static_cast<long>(resp.impl_version.size())));
5412
+ rb_hash_aset(res, rb_id2sym(rb_intern("status")), rb_external_str_new(resp.status.data(), static_cast<long>(resp.status.size())));
5413
+ rb_hash_aset(res,
5414
+ rb_id2sym(rb_intern("impl_version")),
5415
+ rb_external_str_new(resp.impl_version.data(), static_cast<long>(resp.impl_version.size())));
4996
5416
  VALUE indexes = rb_ary_new_capa(static_cast<long>(resp.indexes.size()));
4997
5417
  for (const auto& idx : resp.indexes) {
4998
5418
  VALUE index = rb_hash_new();
@@ -5031,11 +5451,11 @@ cb_Backend_search_index_get(VALUE self, VALUE index_name, VALUE timeout)
5031
5451
  backend->cluster->execute_http(
5032
5452
  req, [barrier](couchbase::operations::search_index_get_response&& resp) mutable { barrier->set_value(resp); });
5033
5453
  auto resp = f.get();
5034
- if (resp.ec) {
5454
+ if (resp.ctx.ec) {
5035
5455
  if (resp.error.empty()) {
5036
- exc = cb__map_error_code(resp.ec, fmt::format("unable to get search index \"{}\"", req.index_name));
5456
+ exc = cb__map_error_code(resp.ctx, fmt::format("unable to get search index \"{}\"", req.index_name));
5037
5457
  } else {
5038
- exc = cb__map_error_code(resp.ec, fmt::format("unable to get search index \"{}\": {}", req.index_name, resp.error));
5458
+ exc = cb__map_error_code(resp.ctx, fmt::format("unable to get search index \"{}\": {}", req.index_name, resp.error));
5039
5459
  }
5040
5460
  break;
5041
5461
  }
@@ -5120,16 +5540,16 @@ cb_Backend_search_index_upsert(VALUE self, VALUE index_definition, VALUE timeout
5120
5540
  backend->cluster->execute_http(
5121
5541
  req, [barrier](couchbase::operations::search_index_upsert_response&& resp) mutable { barrier->set_value(resp); });
5122
5542
  auto resp = f.get();
5123
- if (resp.ec) {
5543
+ if (resp.ctx.ec) {
5124
5544
  if (resp.error.empty()) {
5125
- exc = cb__map_error_code(resp.ec, fmt::format("unable to upsert the search index \"{}\"", req.index.name));
5545
+ exc = cb__map_error_code(resp.ctx, fmt::format("unable to upsert the search index \"{}\"", req.index.name));
5126
5546
  } else {
5127
- exc = cb__map_error_code(resp.ec, fmt::format("unable to upsert the search index \"{}\": {}", req.index.name, resp.error));
5547
+ exc = cb__map_error_code(resp.ctx, fmt::format("unable to upsert the search index \"{}\": {}", req.index.name, resp.error));
5128
5548
  }
5129
5549
  break;
5130
5550
  }
5131
5551
  VALUE res = rb_hash_new();
5132
- rb_hash_aset(res, rb_id2sym(rb_intern("status")), rb_str_new(resp.status.data(), static_cast<long>(resp.status.size())));
5552
+ rb_hash_aset(res, rb_id2sym(rb_intern("status")), rb_external_str_new(resp.status.data(), static_cast<long>(resp.status.size())));
5133
5553
  return res;
5134
5554
  } while (false);
5135
5555
  rb_exc_raise(exc);
@@ -5161,16 +5581,16 @@ cb_Backend_search_index_drop(VALUE self, VALUE index_name, VALUE timeout)
5161
5581
  backend->cluster->execute_http(
5162
5582
  req, [barrier](couchbase::operations::search_index_drop_response&& resp) mutable { barrier->set_value(resp); });
5163
5583
  auto resp = f.get();
5164
- if (resp.ec) {
5584
+ if (resp.ctx.ec) {
5165
5585
  if (resp.error.empty()) {
5166
- exc = cb__map_error_code(resp.ec, fmt::format("unable to drop the search index \"{}\"", req.index_name));
5586
+ exc = cb__map_error_code(resp.ctx, fmt::format("unable to drop the search index \"{}\"", req.index_name));
5167
5587
  } else {
5168
- exc = cb__map_error_code(resp.ec, fmt::format("unable to drop the search index \"{}\": {}", req.index_name, resp.error));
5588
+ exc = cb__map_error_code(resp.ctx, fmt::format("unable to drop the search index \"{}\": {}", req.index_name, resp.error));
5169
5589
  }
5170
5590
  break;
5171
5591
  }
5172
5592
  VALUE res = rb_hash_new();
5173
- rb_hash_aset(res, rb_id2sym(rb_intern("status")), rb_str_new(resp.status.data(), static_cast<long>(resp.status.size())));
5593
+ rb_hash_aset(res, rb_id2sym(rb_intern("status")), rb_external_str_new(resp.status.data(), static_cast<long>(resp.status.size())));
5174
5594
  return res;
5175
5595
  } while (false);
5176
5596
  rb_exc_raise(exc);
@@ -5202,19 +5622,19 @@ cb_Backend_search_index_get_documents_count(VALUE self, VALUE index_name, VALUE
5202
5622
  backend->cluster->execute_http(
5203
5623
  req, [barrier](couchbase::operations::search_index_get_documents_count_response&& resp) mutable { barrier->set_value(resp); });
5204
5624
  auto resp = f.get();
5205
- if (resp.ec) {
5625
+ if (resp.ctx.ec) {
5206
5626
  if (resp.error.empty()) {
5207
5627
  exc = cb__map_error_code(
5208
- resp.ec, fmt::format("unable to get number of the indexed documents for the search index \"{}\"", req.index_name));
5628
+ resp.ctx, fmt::format("unable to get number of the indexed documents for the search index \"{}\"", req.index_name));
5209
5629
  } else {
5210
5630
  exc = cb__map_error_code(
5211
- resp.ec,
5631
+ resp.ctx,
5212
5632
  fmt::format("unable to get number of the indexed documents for the search index \"{}\": {}", req.index_name, resp.error));
5213
5633
  }
5214
5634
  break;
5215
5635
  }
5216
5636
  VALUE res = rb_hash_new();
5217
- rb_hash_aset(res, rb_id2sym(rb_intern("status")), rb_str_new(resp.status.data(), static_cast<long>(resp.status.size())));
5637
+ rb_hash_aset(res, rb_id2sym(rb_intern("status")), rb_external_str_new(resp.status.data(), static_cast<long>(resp.status.size())));
5218
5638
  rb_hash_aset(res, rb_id2sym(rb_intern("count")), ULL2NUM(resp.count));
5219
5639
  return res;
5220
5640
  } while (false);
@@ -5247,16 +5667,16 @@ cb_Backend_search_index_get_stats(VALUE self, VALUE index_name, VALUE timeout)
5247
5667
  backend->cluster->execute_http(
5248
5668
  req, [barrier](couchbase::operations::search_index_get_stats_response&& resp) mutable { barrier->set_value(resp); });
5249
5669
  auto resp = f.get();
5250
- if (resp.ec) {
5670
+ if (resp.ctx.ec) {
5251
5671
  if (resp.error.empty()) {
5252
- exc = cb__map_error_code(resp.ec, fmt::format("unable to get stats for the search index \"{}\"", req.index_name));
5672
+ exc = cb__map_error_code(resp.ctx, fmt::format("unable to get stats for the search index \"{}\"", req.index_name));
5253
5673
  } else {
5254
- exc = cb__map_error_code(resp.ec,
5674
+ exc = cb__map_error_code(resp.ctx,
5255
5675
  fmt::format("unable to get stats for the search index \"{}\": {}", req.index_name, resp.error));
5256
5676
  }
5257
5677
  break;
5258
5678
  }
5259
- return rb_str_new(resp.stats.data(), static_cast<long>(resp.stats.size()));
5679
+ return rb_external_str_new(resp.stats.data(), static_cast<long>(resp.stats.size()));
5260
5680
  } while (false);
5261
5681
  rb_exc_raise(exc);
5262
5682
  return Qnil;
@@ -5285,11 +5705,11 @@ cb_Backend_search_get_stats(VALUE self, VALUE timeout)
5285
5705
  backend->cluster->execute_http(
5286
5706
  req, [barrier](couchbase::operations::search_index_stats_response&& resp) mutable { barrier->set_value(resp); });
5287
5707
  auto resp = f.get();
5288
- if (resp.ec) {
5289
- exc = cb__map_error_code(resp.ec, "unable to get stats for the search service");
5708
+ if (resp.ctx.ec) {
5709
+ exc = cb__map_error_code(resp.ctx, "unable to get stats for the search service");
5290
5710
  break;
5291
5711
  }
5292
- return rb_str_new(resp.stats.data(), static_cast<long>(resp.stats.size()));
5712
+ return rb_external_str_new(resp.stats.data(), static_cast<long>(resp.stats.size()));
5293
5713
  } while (false);
5294
5714
  rb_exc_raise(exc);
5295
5715
  return Qnil;
@@ -5321,17 +5741,17 @@ cb_Backend_search_index_pause_ingest(VALUE self, VALUE index_name, VALUE timeout
5321
5741
  backend->cluster->execute_http(
5322
5742
  req, [barrier](couchbase::operations::search_index_control_ingest_response&& resp) mutable { barrier->set_value(resp); });
5323
5743
  auto resp = f.get();
5324
- if (resp.ec) {
5744
+ if (resp.ctx.ec) {
5325
5745
  if (resp.error.empty()) {
5326
- exc = cb__map_error_code(resp.ec, fmt::format("unable to pause ingest for the search index \"{}\"", req.index_name));
5746
+ exc = cb__map_error_code(resp.ctx, fmt::format("unable to pause ingest for the search index \"{}\"", req.index_name));
5327
5747
  } else {
5328
- exc = cb__map_error_code(resp.ec,
5748
+ exc = cb__map_error_code(resp.ctx,
5329
5749
  fmt::format("unable to pause ingest for the search index \"{}\": {}", req.index_name, resp.error));
5330
5750
  }
5331
5751
  break;
5332
5752
  }
5333
5753
  VALUE res = rb_hash_new();
5334
- rb_hash_aset(res, rb_id2sym(rb_intern("status")), rb_str_new(resp.status.data(), static_cast<long>(resp.status.size())));
5754
+ rb_hash_aset(res, rb_id2sym(rb_intern("status")), rb_external_str_new(resp.status.data(), static_cast<long>(resp.status.size())));
5335
5755
  return res;
5336
5756
  } while (false);
5337
5757
  rb_exc_raise(exc);
@@ -5364,17 +5784,17 @@ cb_Backend_search_index_resume_ingest(VALUE self, VALUE index_name, VALUE timeou
5364
5784
  backend->cluster->execute_http(
5365
5785
  req, [barrier](couchbase::operations::search_index_control_ingest_response&& resp) mutable { barrier->set_value(resp); });
5366
5786
  auto resp = f.get();
5367
- if (resp.ec) {
5787
+ if (resp.ctx.ec) {
5368
5788
  if (resp.error.empty()) {
5369
- exc = cb__map_error_code(resp.ec, fmt::format("unable to resume ingest for the search index \"{}\"", req.index_name));
5789
+ exc = cb__map_error_code(resp.ctx, fmt::format("unable to resume ingest for the search index \"{}\"", req.index_name));
5370
5790
  } else {
5371
5791
  exc = cb__map_error_code(
5372
- resp.ec, fmt::format("unable to resume ingest for the search index \"{}\": {}", req.index_name, resp.error));
5792
+ resp.ctx, fmt::format("unable to resume ingest for the search index \"{}\": {}", req.index_name, resp.error));
5373
5793
  }
5374
5794
  break;
5375
5795
  }
5376
5796
  VALUE res = rb_hash_new();
5377
- rb_hash_aset(res, rb_id2sym(rb_intern("status")), rb_str_new(resp.status.data(), static_cast<long>(resp.status.size())));
5797
+ rb_hash_aset(res, rb_id2sym(rb_intern("status")), rb_external_str_new(resp.status.data(), static_cast<long>(resp.status.size())));
5378
5798
  return res;
5379
5799
  } while (false);
5380
5800
  rb_exc_raise(exc);
@@ -5407,17 +5827,17 @@ cb_Backend_search_index_allow_querying(VALUE self, VALUE index_name, VALUE timeo
5407
5827
  backend->cluster->execute_http(
5408
5828
  req, [barrier](couchbase::operations::search_index_control_query_response&& resp) mutable { barrier->set_value(resp); });
5409
5829
  auto resp = f.get();
5410
- if (resp.ec) {
5830
+ if (resp.ctx.ec) {
5411
5831
  if (resp.error.empty()) {
5412
- exc = cb__map_error_code(resp.ec, fmt::format("unable to allow querying for the search index \"{}\"", req.index_name));
5832
+ exc = cb__map_error_code(resp.ctx, fmt::format("unable to allow querying for the search index \"{}\"", req.index_name));
5413
5833
  } else {
5414
5834
  exc = cb__map_error_code(
5415
- resp.ec, fmt::format("unable to allow querying for the search index \"{}\": {}", req.index_name, resp.error));
5835
+ resp.ctx, fmt::format("unable to allow querying for the search index \"{}\": {}", req.index_name, resp.error));
5416
5836
  }
5417
5837
  break;
5418
5838
  }
5419
5839
  VALUE res = rb_hash_new();
5420
- rb_hash_aset(res, rb_id2sym(rb_intern("status")), rb_str_new(resp.status.data(), static_cast<long>(resp.status.size())));
5840
+ rb_hash_aset(res, rb_id2sym(rb_intern("status")), rb_external_str_new(resp.status.data(), static_cast<long>(resp.status.size())));
5421
5841
  return res;
5422
5842
  } while (false);
5423
5843
  rb_exc_raise(exc);
@@ -5450,17 +5870,17 @@ cb_Backend_search_index_disallow_querying(VALUE self, VALUE index_name, VALUE ti
5450
5870
  backend->cluster->execute_http(
5451
5871
  req, [barrier](couchbase::operations::search_index_control_query_response&& resp) mutable { barrier->set_value(resp); });
5452
5872
  auto resp = f.get();
5453
- if (resp.ec) {
5873
+ if (resp.ctx.ec) {
5454
5874
  if (resp.error.empty()) {
5455
- exc = cb__map_error_code(resp.ec, fmt::format("unable to disallow querying for the search index \"{}\"", req.index_name));
5875
+ exc = cb__map_error_code(resp.ctx, fmt::format("unable to disallow querying for the search index \"{}\"", req.index_name));
5456
5876
  } else {
5457
5877
  exc = cb__map_error_code(
5458
- resp.ec, fmt::format("unable to disallow querying for the search index \"{}\": {}", req.index_name, resp.error));
5878
+ resp.ctx, fmt::format("unable to disallow querying for the search index \"{}\": {}", req.index_name, resp.error));
5459
5879
  }
5460
5880
  break;
5461
5881
  }
5462
5882
  VALUE res = rb_hash_new();
5463
- rb_hash_aset(res, rb_id2sym(rb_intern("status")), rb_str_new(resp.status.data(), static_cast<long>(resp.status.size())));
5883
+ rb_hash_aset(res, rb_id2sym(rb_intern("status")), rb_external_str_new(resp.status.data(), static_cast<long>(resp.status.size())));
5464
5884
  return res;
5465
5885
  } while (false);
5466
5886
  rb_exc_raise(exc);
@@ -5493,17 +5913,17 @@ cb_Backend_search_index_freeze_plan(VALUE self, VALUE index_name, VALUE timeout)
5493
5913
  backend->cluster->execute_http(
5494
5914
  req, [barrier](couchbase::operations::search_index_control_plan_freeze_response&& resp) mutable { barrier->set_value(resp); });
5495
5915
  auto resp = f.get();
5496
- if (resp.ec) {
5916
+ if (resp.ctx.ec) {
5497
5917
  if (resp.error.empty()) {
5498
- exc = cb__map_error_code(resp.ec, fmt::format("unable to freeze for the search index \"{}\"", req.index_name));
5918
+ exc = cb__map_error_code(resp.ctx, fmt::format("unable to freeze for the search index \"{}\"", req.index_name));
5499
5919
  } else {
5500
5920
  exc =
5501
- cb__map_error_code(resp.ec, fmt::format("unable to freeze for the search index \"{}\": {}", req.index_name, resp.error));
5921
+ cb__map_error_code(resp.ctx, fmt::format("unable to freeze for the search index \"{}\": {}", req.index_name, resp.error));
5502
5922
  }
5503
5923
  break;
5504
5924
  }
5505
5925
  VALUE res = rb_hash_new();
5506
- rb_hash_aset(res, rb_id2sym(rb_intern("status")), rb_str_new(resp.status.data(), static_cast<long>(resp.status.size())));
5926
+ rb_hash_aset(res, rb_id2sym(rb_intern("status")), rb_external_str_new(resp.status.data(), static_cast<long>(resp.status.size())));
5507
5927
  return res;
5508
5928
  } while (false);
5509
5929
  rb_exc_raise(exc);
@@ -5536,17 +5956,17 @@ cb_Backend_search_index_unfreeze_plan(VALUE self, VALUE index_name, VALUE timeou
5536
5956
  backend->cluster->execute_http(
5537
5957
  req, [barrier](couchbase::operations::search_index_control_plan_freeze_response&& resp) mutable { barrier->set_value(resp); });
5538
5958
  auto resp = f.get();
5539
- if (resp.ec) {
5959
+ if (resp.ctx.ec) {
5540
5960
  if (resp.error.empty()) {
5541
- exc = cb__map_error_code(resp.ec, fmt::format("unable to unfreeze plan for the search index \"{}\"", req.index_name));
5961
+ exc = cb__map_error_code(resp.ctx, fmt::format("unable to unfreeze plan for the search index \"{}\"", req.index_name));
5542
5962
  } else {
5543
- exc = cb__map_error_code(resp.ec,
5963
+ exc = cb__map_error_code(resp.ctx,
5544
5964
  fmt::format("unable to unfreeze for the search index \"{}\": {}", req.index_name, resp.error));
5545
5965
  }
5546
5966
  break;
5547
5967
  }
5548
5968
  VALUE res = rb_hash_new();
5549
- rb_hash_aset(res, rb_id2sym(rb_intern("status")), rb_str_new(resp.status.data(), static_cast<long>(resp.status.size())));
5969
+ rb_hash_aset(res, rb_id2sym(rb_intern("status")), rb_external_str_new(resp.status.data(), static_cast<long>(resp.status.size())));
5550
5970
  return res;
5551
5971
  } while (false);
5552
5972
  rb_exc_raise(exc);
@@ -5582,18 +6002,19 @@ cb_Backend_search_index_analyze_document(VALUE self, VALUE index_name, VALUE enc
5582
6002
  backend->cluster->execute_http(
5583
6003
  req, [barrier](couchbase::operations::search_index_analyze_document_response&& resp) mutable { barrier->set_value(resp); });
5584
6004
  auto resp = f.get();
5585
- if (resp.ec) {
6005
+ if (resp.ctx.ec) {
5586
6006
  if (resp.error.empty()) {
5587
- exc = cb__map_error_code(resp.ec, fmt::format("unable to analyze document using the search index \"{}\"", req.index_name));
6007
+ exc = cb__map_error_code(resp.ctx, fmt::format("unable to analyze document using the search index \"{}\"", req.index_name));
5588
6008
  } else {
5589
6009
  exc = cb__map_error_code(
5590
- resp.ec, fmt::format("unable to analyze document using the search index \"{}\": {}", req.index_name, resp.error));
6010
+ resp.ctx, fmt::format("unable to analyze document using the search index \"{}\": {}", req.index_name, resp.error));
5591
6011
  }
5592
6012
  break;
5593
6013
  }
5594
6014
  VALUE res = rb_hash_new();
5595
- rb_hash_aset(res, rb_id2sym(rb_intern("status")), rb_str_new(resp.status.data(), static_cast<long>(resp.status.size())));
5596
- rb_hash_aset(res, rb_id2sym(rb_intern("analysis")), rb_str_new(resp.analysis.data(), static_cast<long>(resp.analysis.size())));
6015
+ rb_hash_aset(res, rb_id2sym(rb_intern("status")), rb_external_str_new(resp.status.data(), static_cast<long>(resp.status.size())));
6016
+ rb_hash_aset(
6017
+ res, rb_id2sym(rb_intern("analysis")), rb_external_str_new(resp.analysis.data(), static_cast<long>(resp.analysis.size())));
5597
6018
  return res;
5598
6019
  } while (false);
5599
6020
  rb_exc_raise(exc);
@@ -5768,22 +6189,23 @@ cb_Backend_document_search(VALUE self, VALUE index_name, VALUE query, VALUE opti
5768
6189
  auto f = barrier->get_future();
5769
6190
  backend->cluster->execute_http(req, [barrier](couchbase::operations::search_response&& resp) mutable { barrier->set_value(resp); });
5770
6191
  auto resp = f.get();
5771
- if (resp.ec) {
6192
+ if (resp.ctx.ec) {
5772
6193
  exc =
5773
- cb__map_error_code(resp.ec, fmt::format("unable to perform search query for index \"{}\": {}", req.index_name, resp.error));
6194
+ cb__map_error_code(resp.ctx, fmt::format("unable to perform search query for index \"{}\": {}", req.index_name, resp.error));
5774
6195
  break;
5775
6196
  }
5776
6197
  VALUE res = rb_hash_new();
5777
6198
 
5778
6199
  VALUE meta_data = rb_hash_new();
5779
- rb_hash_aset(meta_data,
5780
- rb_id2sym(rb_intern("client_context_id")),
5781
- rb_str_new(resp.meta_data.client_context_id.data(), static_cast<long>(resp.meta_data.client_context_id.size())));
6200
+ rb_hash_aset(
6201
+ meta_data,
6202
+ rb_id2sym(rb_intern("client_context_id")),
6203
+ rb_external_str_new(resp.meta_data.client_context_id.data(), static_cast<long>(resp.meta_data.client_context_id.size())));
5782
6204
 
5783
6205
  VALUE metrics = rb_hash_new();
5784
6206
  rb_hash_aset(metrics,
5785
6207
  rb_id2sym(rb_intern("took")),
5786
- LONG2NUM(std::chrono::duration_cast<std::chrono::milliseconds>(resp.meta_data.metrics.took).count()));
6208
+ LL2NUM(std::chrono::duration_cast<std::chrono::milliseconds>(resp.meta_data.metrics.took).count()));
5787
6209
  rb_hash_aset(metrics, rb_id2sym(rb_intern("total_rows")), ULL2NUM(resp.meta_data.metrics.total_rows));
5788
6210
  rb_hash_aset(metrics, rb_id2sym(rb_intern("max_score")), DBL2NUM(resp.meta_data.metrics.max_score));
5789
6211
  rb_hash_aset(metrics, rb_id2sym(rb_intern("success_partition_count")), ULL2NUM(resp.meta_data.metrics.success_partition_count));
@@ -5794,8 +6216,8 @@ cb_Backend_document_search(VALUE self, VALUE index_name, VALUE query, VALUE opti
5794
6216
  VALUE errors = rb_hash_new();
5795
6217
  for (auto err : resp.meta_data.errors) {
5796
6218
  rb_hash_aset(errors,
5797
- rb_str_new(err.first.data(), static_cast<long>(err.first.size())),
5798
- rb_str_new(err.second.data(), static_cast<long>(err.second.size())));
6219
+ rb_external_str_new(err.first.data(), static_cast<long>(err.first.size())),
6220
+ rb_external_str_new(err.second.data(), static_cast<long>(err.second.size())));
5799
6221
  }
5800
6222
  rb_hash_aset(meta_data, rb_id2sym(rb_intern("errors")), errors);
5801
6223
  }
@@ -5805,14 +6227,16 @@ cb_Backend_document_search(VALUE self, VALUE index_name, VALUE query, VALUE opti
5805
6227
  VALUE rows = rb_ary_new_capa(static_cast<long>(resp.rows.size()));
5806
6228
  for (const auto& entry : resp.rows) {
5807
6229
  VALUE row = rb_hash_new();
5808
- rb_hash_aset(row, rb_id2sym(rb_intern("index")), rb_str_new(entry.index.data(), static_cast<long>(entry.index.size())));
5809
- rb_hash_aset(row, rb_id2sym(rb_intern("id")), rb_str_new(entry.id.data(), static_cast<long>(entry.id.size())));
6230
+ rb_hash_aset(
6231
+ row, rb_id2sym(rb_intern("index")), rb_external_str_new(entry.index.data(), static_cast<long>(entry.index.size())));
6232
+ rb_hash_aset(row, rb_id2sym(rb_intern("id")), rb_external_str_new(entry.id.data(), static_cast<long>(entry.id.size())));
5810
6233
  rb_hash_aset(row, rb_id2sym(rb_intern("score")), DBL2NUM(entry.score));
5811
6234
  VALUE locations = rb_ary_new_capa(static_cast<long>(entry.locations.size()));
5812
6235
  for (const auto& loc : entry.locations) {
5813
6236
  VALUE location = rb_hash_new();
5814
- rb_hash_aset(row, rb_id2sym(rb_intern("field")), rb_str_new(loc.field.data(), static_cast<long>(loc.field.size())));
5815
- rb_hash_aset(row, rb_id2sym(rb_intern("term")), rb_str_new(loc.term.data(), static_cast<long>(loc.term.size())));
6237
+ rb_hash_aset(
6238
+ row, rb_id2sym(rb_intern("field")), rb_external_str_new(loc.field.data(), static_cast<long>(loc.field.size())));
6239
+ rb_hash_aset(row, rb_id2sym(rb_intern("term")), rb_external_str_new(loc.term.data(), static_cast<long>(loc.term.size())));
5816
6240
  rb_hash_aset(row, rb_id2sym(rb_intern("pos")), ULL2NUM(loc.position));
5817
6241
  rb_hash_aset(row, rb_id2sym(rb_intern("start_offset")), ULL2NUM(loc.start_offset));
5818
6242
  rb_hash_aset(row, rb_id2sym(rb_intern("end_offset")), ULL2NUM(loc.end_offset));
@@ -5831,20 +6255,22 @@ cb_Backend_document_search(VALUE self, VALUE index_name, VALUE query, VALUE opti
5831
6255
  for (const auto& field_fragments : entry.fragments) {
5832
6256
  VALUE fragments_list = rb_ary_new_capa(static_cast<long>(field_fragments.second.size()));
5833
6257
  for (const auto& fragment : field_fragments.second) {
5834
- rb_ary_push(fragments_list, rb_str_new(fragment.data(), static_cast<long>(fragment.size())));
6258
+ rb_ary_push(fragments_list, rb_external_str_new(fragment.data(), static_cast<long>(fragment.size())));
5835
6259
  }
5836
- rb_hash_aset(
5837
- fragments, rb_str_new(field_fragments.first.data(), static_cast<long>(field_fragments.first.size())), fragments_list);
6260
+ rb_hash_aset(fragments,
6261
+ rb_external_str_new(field_fragments.first.data(), static_cast<long>(field_fragments.first.size())),
6262
+ fragments_list);
5838
6263
  }
5839
6264
  rb_hash_aset(row, rb_id2sym(rb_intern("fragments")), fragments);
5840
6265
  }
5841
6266
  if (!entry.fields.empty()) {
5842
- rb_hash_aset(row, rb_id2sym(rb_intern("fields")), rb_str_new(entry.fields.data(), static_cast<long>(entry.fields.size())));
6267
+ rb_hash_aset(
6268
+ row, rb_id2sym(rb_intern("fields")), rb_external_str_new(entry.fields.data(), static_cast<long>(entry.fields.size())));
5843
6269
  }
5844
6270
  if (!entry.explanation.empty()) {
5845
6271
  rb_hash_aset(row,
5846
6272
  rb_id2sym(rb_intern("explanation")),
5847
- rb_str_new(entry.explanation.data(), static_cast<long>(entry.explanation.size())));
6273
+ rb_external_str_new(entry.explanation.data(), static_cast<long>(entry.explanation.size())));
5848
6274
  }
5849
6275
  rb_ary_push(rows, row);
5850
6276
  }
@@ -5854,9 +6280,10 @@ cb_Backend_document_search(VALUE self, VALUE index_name, VALUE query, VALUE opti
5854
6280
  VALUE result_facets = rb_hash_new();
5855
6281
  for (const auto& entry : resp.facets) {
5856
6282
  VALUE facet = rb_hash_new();
5857
- VALUE facet_name = rb_str_new(entry.name.data(), static_cast<long>(entry.name.size()));
6283
+ VALUE facet_name = rb_external_str_new(entry.name.data(), static_cast<long>(entry.name.size()));
5858
6284
  rb_hash_aset(facet, rb_id2sym(rb_intern("name")), facet_name);
5859
- rb_hash_aset(facet, rb_id2sym(rb_intern("field")), rb_str_new(entry.field.data(), static_cast<long>(entry.field.size())));
6285
+ rb_hash_aset(
6286
+ facet, rb_id2sym(rb_intern("field")), rb_external_str_new(entry.field.data(), static_cast<long>(entry.field.size())));
5860
6287
  rb_hash_aset(facet, rb_id2sym(rb_intern("total")), ULL2NUM(entry.total));
5861
6288
  rb_hash_aset(facet, rb_id2sym(rb_intern("missing")), ULL2NUM(entry.missing));
5862
6289
  rb_hash_aset(facet, rb_id2sym(rb_intern("other")), ULL2NUM(entry.other));
@@ -5864,7 +6291,8 @@ cb_Backend_document_search(VALUE self, VALUE index_name, VALUE query, VALUE opti
5864
6291
  VALUE terms = rb_ary_new_capa(static_cast<long>(entry.terms.size()));
5865
6292
  for (const auto& item : entry.terms) {
5866
6293
  VALUE term = rb_hash_new();
5867
- rb_hash_aset(term, rb_id2sym(rb_intern("term")), rb_str_new(item.term.data(), static_cast<long>(item.term.size())));
6294
+ rb_hash_aset(
6295
+ term, rb_id2sym(rb_intern("term")), rb_external_str_new(item.term.data(), static_cast<long>(item.term.size())));
5868
6296
  rb_hash_aset(term, rb_id2sym(rb_intern("count")), ULL2NUM(item.count));
5869
6297
  rb_ary_push(terms, term);
5870
6298
  }
@@ -5873,18 +6301,19 @@ cb_Backend_document_search(VALUE self, VALUE index_name, VALUE query, VALUE opti
5873
6301
  VALUE date_ranges = rb_ary_new_capa(static_cast<long>(entry.date_ranges.size()));
5874
6302
  for (const auto& item : entry.date_ranges) {
5875
6303
  VALUE date_range = rb_hash_new();
5876
- rb_hash_aset(
5877
- date_range, rb_id2sym(rb_intern("name")), rb_str_new(item.name.data(), static_cast<long>(item.name.size())));
6304
+ rb_hash_aset(date_range,
6305
+ rb_id2sym(rb_intern("name")),
6306
+ rb_external_str_new(item.name.data(), static_cast<long>(item.name.size())));
5878
6307
  rb_hash_aset(date_range, rb_id2sym(rb_intern("count")), ULL2NUM(item.count));
5879
6308
  if (item.start) {
5880
6309
  rb_hash_aset(date_range,
5881
6310
  rb_id2sym(rb_intern("start_time")),
5882
- rb_str_new(item.start->data(), static_cast<long>(item.start->size())));
6311
+ rb_external_str_new(item.start->data(), static_cast<long>(item.start->size())));
5883
6312
  }
5884
6313
  if (item.end) {
5885
6314
  rb_hash_aset(date_range,
5886
6315
  rb_id2sym(rb_intern("end_time")),
5887
- rb_str_new(item.end->data(), static_cast<long>(item.end->size())));
6316
+ rb_external_str_new(item.end->data(), static_cast<long>(item.end->size())));
5888
6317
  }
5889
6318
  rb_ary_push(date_ranges, date_range);
5890
6319
  }
@@ -5893,8 +6322,9 @@ cb_Backend_document_search(VALUE self, VALUE index_name, VALUE query, VALUE opti
5893
6322
  VALUE numeric_ranges = rb_ary_new_capa(static_cast<long>(entry.numeric_ranges.size()));
5894
6323
  for (const auto& item : entry.numeric_ranges) {
5895
6324
  VALUE numeric_range = rb_hash_new();
5896
- rb_hash_aset(
5897
- numeric_range, rb_id2sym(rb_intern("name")), rb_str_new(item.name.data(), static_cast<long>(item.name.size())));
6325
+ rb_hash_aset(numeric_range,
6326
+ rb_id2sym(rb_intern("name")),
6327
+ rb_external_str_new(item.name.data(), static_cast<long>(item.name.size())));
5898
6328
  rb_hash_aset(numeric_range, rb_id2sym(rb_intern("count")), ULL2NUM(item.count));
5899
6329
  if (std::holds_alternative<double>(item.min)) {
5900
6330
  rb_hash_aset(numeric_range, rb_id2sym(rb_intern("min")), DBL2NUM(std::get<double>(item.min)));
@@ -5964,8 +6394,9 @@ cb_Backend_dns_srv(VALUE self, VALUE hostname, VALUE service)
5964
6394
  VALUE res = rb_ary_new();
5965
6395
  for (const auto& target : resp.targets) {
5966
6396
  VALUE addr = rb_hash_new();
5967
- rb_hash_aset(
5968
- addr, rb_id2sym(rb_intern("hostname")), rb_str_new(target.hostname.data(), static_cast<long>(target.hostname.size())));
6397
+ rb_hash_aset(addr,
6398
+ rb_id2sym(rb_intern("hostname")),
6399
+ rb_external_str_new(target.hostname.data(), static_cast<long>(target.hostname.size())));
5969
6400
  rb_hash_aset(addr, rb_id2sym(rb_intern("port")), UINT2NUM(target.port));
5970
6401
  rb_ary_push(res, addr);
5971
6402
  }
@@ -5998,20 +6429,20 @@ cb_Backend_analytics_get_pending_mutations(VALUE self, VALUE timeout)
5998
6429
  backend->cluster->execute_http(
5999
6430
  req, [barrier](couchbase::operations::analytics_get_pending_mutations_response&& resp) mutable { barrier->set_value(resp); });
6000
6431
  auto resp = f.get();
6001
- if (resp.ec) {
6432
+ if (resp.ctx.ec) {
6002
6433
  if (resp.errors.empty()) {
6003
- exc = cb__map_error_code(resp.ec, "unable to get pending mutations for the analytics service");
6434
+ exc = cb__map_error_code(resp.ctx, "unable to get pending mutations for the analytics service");
6004
6435
  } else {
6005
6436
  const auto& first_error = resp.errors.front();
6006
6437
  exc = cb__map_error_code(
6007
- resp.ec,
6438
+ resp.ctx,
6008
6439
  fmt::format("unable to get pending mutations for the analytics service ({}: {})", first_error.code, first_error.message));
6009
6440
  }
6010
6441
  break;
6011
6442
  }
6012
6443
  VALUE res = rb_hash_new();
6013
6444
  for (const auto& entry : resp.stats) {
6014
- rb_hash_aset(res, rb_str_new(entry.first.data(), static_cast<long>(entry.first.size())), ULL2NUM(entry.second));
6445
+ rb_hash_aset(res, rb_external_str_new(entry.first.data(), static_cast<long>(entry.first.size())), ULL2NUM(entry.second));
6015
6446
  }
6016
6447
  return res;
6017
6448
  } while (false);
@@ -6042,27 +6473,28 @@ cb_Backend_analytics_dataset_get_all(VALUE self, VALUE timeout)
6042
6473
  backend->cluster->execute_http(
6043
6474
  req, [barrier](couchbase::operations::analytics_dataset_get_all_response&& resp) mutable { barrier->set_value(resp); });
6044
6475
  auto resp = f.get();
6045
- if (resp.ec) {
6476
+ if (resp.ctx.ec) {
6046
6477
  if (resp.errors.empty()) {
6047
- exc = cb__map_error_code(resp.ec, "unable to fetch all datasets");
6478
+ exc = cb__map_error_code(resp.ctx, "unable to fetch all datasets");
6048
6479
  } else {
6049
6480
  const auto& first_error = resp.errors.front();
6050
6481
  exc =
6051
- cb__map_error_code(resp.ec, fmt::format("unable to fetch all datasets ({}: {})", first_error.code, first_error.message));
6482
+ cb__map_error_code(resp.ctx, fmt::format("unable to fetch all datasets ({}: {})", first_error.code, first_error.message));
6052
6483
  }
6053
6484
  break;
6054
6485
  }
6055
6486
  VALUE res = rb_ary_new_capa(static_cast<long>(resp.datasets.size()));
6056
6487
  for (const auto& ds : resp.datasets) {
6057
6488
  VALUE dataset = rb_hash_new();
6058
- rb_hash_aset(dataset, rb_id2sym(rb_intern("name")), rb_str_new(ds.name.data(), static_cast<long>(ds.name.size())));
6489
+ rb_hash_aset(dataset, rb_id2sym(rb_intern("name")), rb_external_str_new(ds.name.data(), static_cast<long>(ds.name.size())));
6059
6490
  rb_hash_aset(dataset,
6060
6491
  rb_id2sym(rb_intern("dataverse_name")),
6061
- rb_str_new(ds.dataverse_name.data(), static_cast<long>(ds.dataverse_name.size())));
6062
- rb_hash_aset(
6063
- dataset, rb_id2sym(rb_intern("link_name")), rb_str_new(ds.link_name.data(), static_cast<long>(ds.link_name.size())));
6492
+ rb_external_str_new(ds.dataverse_name.data(), static_cast<long>(ds.dataverse_name.size())));
6064
6493
  rb_hash_aset(
6065
- dataset, rb_id2sym(rb_intern("bucket_name")), rb_str_new(ds.bucket_name.data(), static_cast<long>(ds.bucket_name.size())));
6494
+ dataset, rb_id2sym(rb_intern("link_name")), rb_external_str_new(ds.link_name.data(), static_cast<long>(ds.link_name.size())));
6495
+ rb_hash_aset(dataset,
6496
+ rb_id2sym(rb_intern("bucket_name")),
6497
+ rb_external_str_new(ds.bucket_name.data(), static_cast<long>(ds.bucket_name.size())));
6066
6498
  rb_ary_push(res, dataset);
6067
6499
  }
6068
6500
  return res;
@@ -6106,12 +6538,12 @@ cb_Backend_analytics_dataset_drop(VALUE self, VALUE dataset_name, VALUE datavers
6106
6538
  backend->cluster->execute_http(
6107
6539
  req, [barrier](couchbase::operations::analytics_dataset_drop_response&& resp) mutable { barrier->set_value(resp); });
6108
6540
  auto resp = f.get();
6109
- if (resp.ec) {
6541
+ if (resp.ctx.ec) {
6110
6542
  if (resp.errors.empty()) {
6111
- exc = cb__map_error_code(resp.ec, fmt::format("unable to drop dataset `{}`.`{}`", req.dataverse_name, req.dataset_name));
6543
+ exc = cb__map_error_code(resp.ctx, fmt::format("unable to drop dataset `{}`.`{}`", req.dataverse_name, req.dataset_name));
6112
6544
  } else {
6113
6545
  const auto& first_error = resp.errors.front();
6114
- exc = cb__map_error_code(resp.ec,
6546
+ exc = cb__map_error_code(resp.ctx,
6115
6547
  fmt::format("unable to drop dataset `{}`.`{}` ({}: {})",
6116
6548
  req.dataverse_name,
6117
6549
  req.dataset_name,
@@ -6175,12 +6607,12 @@ cb_Backend_analytics_dataset_create(VALUE self,
6175
6607
  backend->cluster->execute_http(
6176
6608
  req, [barrier](couchbase::operations::analytics_dataset_create_response&& resp) mutable { barrier->set_value(resp); });
6177
6609
  auto resp = f.get();
6178
- if (resp.ec) {
6610
+ if (resp.ctx.ec) {
6179
6611
  if (resp.errors.empty()) {
6180
- exc = cb__map_error_code(resp.ec, fmt::format("unable to create dataset `{}`.`{}`", req.dataverse_name, req.dataset_name));
6612
+ exc = cb__map_error_code(resp.ctx, fmt::format("unable to create dataset `{}`.`{}`", req.dataverse_name, req.dataset_name));
6181
6613
  } else {
6182
6614
  const auto& first_error = resp.errors.front();
6183
- exc = cb__map_error_code(resp.ec,
6615
+ exc = cb__map_error_code(resp.ctx,
6184
6616
  fmt::format("unable to create dataset `{}`.`{}` ({}: {})",
6185
6617
  req.dataverse_name,
6186
6618
  req.dataset_name,
@@ -6224,13 +6656,13 @@ cb_Backend_analytics_dataverse_drop(VALUE self, VALUE dataverse_name, VALUE igno
6224
6656
  backend->cluster->execute_http(
6225
6657
  req, [barrier](couchbase::operations::analytics_dataverse_drop_response&& resp) mutable { barrier->set_value(resp); });
6226
6658
  auto resp = f.get();
6227
- if (resp.ec) {
6659
+ if (resp.ctx.ec) {
6228
6660
  if (resp.errors.empty()) {
6229
- exc = cb__map_error_code(resp.ec, fmt::format("unable to drop dataverse `{}`", req.dataverse_name));
6661
+ exc = cb__map_error_code(resp.ctx, fmt::format("unable to drop dataverse `{}`", req.dataverse_name));
6230
6662
  } else {
6231
6663
  const auto& first_error = resp.errors.front();
6232
6664
  exc = cb__map_error_code(
6233
- resp.ec,
6665
+ resp.ctx,
6234
6666
  fmt::format("unable to drop dataverse `{}` ({}: {})", req.dataverse_name, first_error.code, first_error.message));
6235
6667
  }
6236
6668
  break;
@@ -6273,13 +6705,13 @@ cb_Backend_analytics_dataverse_create(VALUE self, VALUE dataverse_name, VALUE ig
6273
6705
  backend->cluster->execute_http(
6274
6706
  req, [barrier](couchbase::operations::analytics_dataverse_create_response&& resp) mutable { barrier->set_value(resp); });
6275
6707
  auto resp = f.get();
6276
- if (resp.ec) {
6708
+ if (resp.ctx.ec) {
6277
6709
  if (resp.errors.empty()) {
6278
- exc = cb__map_error_code(resp.ec, fmt::format("unable to create dataverse `{}`", req.dataverse_name));
6710
+ exc = cb__map_error_code(resp.ctx, fmt::format("unable to create dataverse `{}`", req.dataverse_name));
6279
6711
  } else {
6280
6712
  const auto& first_error = resp.errors.front();
6281
6713
  exc = cb__map_error_code(
6282
- resp.ec,
6714
+ resp.ctx,
6283
6715
  fmt::format("unable to create dataverse `{}` ({}: {})", req.dataverse_name, first_error.code, first_error.message));
6284
6716
  }
6285
6717
  break;
@@ -6313,25 +6745,26 @@ cb_Backend_analytics_index_get_all(VALUE self, VALUE timeout)
6313
6745
  backend->cluster->execute_http(
6314
6746
  req, [barrier](couchbase::operations::analytics_index_get_all_response&& resp) mutable { barrier->set_value(resp); });
6315
6747
  auto resp = f.get();
6316
- if (resp.ec) {
6748
+ if (resp.ctx.ec) {
6317
6749
  if (resp.errors.empty()) {
6318
- exc = cb__map_error_code(resp.ec, "unable to fetch all indexes");
6750
+ exc = cb__map_error_code(resp.ctx, "unable to fetch all indexes");
6319
6751
  } else {
6320
6752
  const auto& first_error = resp.errors.front();
6321
6753
  exc =
6322
- cb__map_error_code(resp.ec, fmt::format("unable to fetch all indexes ({}: {})", first_error.code, first_error.message));
6754
+ cb__map_error_code(resp.ctx, fmt::format("unable to fetch all indexes ({}: {})", first_error.code, first_error.message));
6323
6755
  }
6324
6756
  break;
6325
6757
  }
6326
6758
  VALUE res = rb_ary_new_capa(static_cast<long>(resp.indexes.size()));
6327
6759
  for (const auto& idx : resp.indexes) {
6328
6760
  VALUE index = rb_hash_new();
6329
- rb_hash_aset(index, rb_id2sym(rb_intern("name")), rb_str_new(idx.name.data(), static_cast<long>(idx.name.size())));
6330
- rb_hash_aset(
6331
- index, rb_id2sym(rb_intern("dataset_name")), rb_str_new(idx.dataset_name.data(), static_cast<long>(idx.dataset_name.size())));
6761
+ rb_hash_aset(index, rb_id2sym(rb_intern("name")), rb_external_str_new(idx.name.data(), static_cast<long>(idx.name.size())));
6762
+ rb_hash_aset(index,
6763
+ rb_id2sym(rb_intern("dataset_name")),
6764
+ rb_external_str_new(idx.dataset_name.data(), static_cast<long>(idx.dataset_name.size())));
6332
6765
  rb_hash_aset(index,
6333
6766
  rb_id2sym(rb_intern("dataverse_name")),
6334
- rb_str_new(idx.dataverse_name.data(), static_cast<long>(idx.dataverse_name.size())));
6767
+ rb_external_str_new(idx.dataverse_name.data(), static_cast<long>(idx.dataverse_name.size())));
6335
6768
  rb_hash_aset(index, rb_id2sym(rb_intern("is_primary")), idx.is_primary ? Qtrue : Qfalse);
6336
6769
  rb_ary_push(res, index);
6337
6770
  }
@@ -6396,13 +6829,13 @@ cb_Backend_analytics_index_create(VALUE self,
6396
6829
  backend->cluster->execute_http(
6397
6830
  req, [barrier](couchbase::operations::analytics_index_create_response&& resp) mutable { barrier->set_value(resp); });
6398
6831
  auto resp = f.get();
6399
- if (resp.ec) {
6832
+ if (resp.ctx.ec) {
6400
6833
  if (resp.errors.empty()) {
6401
6834
  exc = cb__map_error_code(
6402
- resp.ec, fmt::format("unable to create index `{}` on `{}`.`{}`", req.index_name, req.dataverse_name, req.dataset_name));
6835
+ resp.ctx, fmt::format("unable to create index `{}` on `{}`.`{}`", req.index_name, req.dataverse_name, req.dataset_name));
6403
6836
  } else {
6404
6837
  const auto& first_error = resp.errors.front();
6405
- exc = cb__map_error_code(resp.ec,
6838
+ exc = cb__map_error_code(resp.ctx,
6406
6839
  fmt::format("unable to create index `{}` on `{}`.`{}` ({}: {})",
6407
6840
  req.index_name,
6408
6841
  req.dataverse_name,
@@ -6460,13 +6893,13 @@ cb_Backend_analytics_index_drop(VALUE self,
6460
6893
  backend->cluster->execute_http(
6461
6894
  req, [barrier](couchbase::operations::analytics_index_drop_response&& resp) mutable { barrier->set_value(resp); });
6462
6895
  auto resp = f.get();
6463
- if (resp.ec) {
6896
+ if (resp.ctx.ec) {
6464
6897
  if (resp.errors.empty()) {
6465
6898
  exc = cb__map_error_code(
6466
- resp.ec, fmt::format("unable to drop index `{}`.`{}`.`{}`", req.dataverse_name, req.dataset_name, req.index_name));
6899
+ resp.ctx, fmt::format("unable to drop index `{}`.`{}`.`{}`", req.dataverse_name, req.dataset_name, req.index_name));
6467
6900
  } else {
6468
6901
  const auto& first_error = resp.errors.front();
6469
- exc = cb__map_error_code(resp.ec,
6902
+ exc = cb__map_error_code(resp.ctx,
6470
6903
  fmt::format("unable to drop index `{}`.`{}`.`{}` ({}: {})",
6471
6904
  req.dataverse_name,
6472
6905
  req.dataset_name,
@@ -6517,12 +6950,12 @@ cb_Backend_analytics_link_connect(VALUE self, VALUE link_name, VALUE force, VALU
6517
6950
  backend->cluster->execute_http(
6518
6951
  req, [barrier](couchbase::operations::analytics_link_connect_response&& resp) mutable { barrier->set_value(resp); });
6519
6952
  auto resp = f.get();
6520
- if (resp.ec) {
6953
+ if (resp.ctx.ec) {
6521
6954
  if (resp.errors.empty()) {
6522
- exc = cb__map_error_code(resp.ec, fmt::format("unable to connect link `{}` on `{}`", req.link_name, req.dataverse_name));
6955
+ exc = cb__map_error_code(resp.ctx, fmt::format("unable to connect link `{}` on `{}`", req.link_name, req.dataverse_name));
6523
6956
  } else {
6524
6957
  const auto& first_error = resp.errors.front();
6525
- exc = cb__map_error_code(resp.ec,
6958
+ exc = cb__map_error_code(resp.ctx,
6526
6959
  fmt::format("unable to connect link `{}` on `{}` ({}: {})",
6527
6960
  req.link_name,
6528
6961
  req.dataverse_name,
@@ -6569,12 +7002,13 @@ cb_Backend_analytics_link_disconnect(VALUE self, VALUE link_name, VALUE datavers
6569
7002
  backend->cluster->execute_http(
6570
7003
  req, [barrier](couchbase::operations::analytics_link_disconnect_response&& resp) mutable { barrier->set_value(resp); });
6571
7004
  auto resp = f.get();
6572
- if (resp.ec) {
7005
+ if (resp.ctx.ec) {
6573
7006
  if (resp.errors.empty()) {
6574
- exc = cb__map_error_code(resp.ec, fmt::format("unable to disconnect link `{}` on `{}`", req.link_name, req.dataverse_name));
7007
+ exc =
7008
+ cb__map_error_code(resp.ctx, fmt::format("unable to disconnect link `{}` on `{}`", req.link_name, req.dataverse_name));
6575
7009
  } else {
6576
7010
  const auto& first_error = resp.errors.front();
6577
- exc = cb__map_error_code(resp.ec,
7011
+ exc = cb__map_error_code(resp.ctx,
6578
7012
  fmt::format("unable to disconnect link `{}` on `{}` ({}: {})",
6579
7013
  req.link_name,
6580
7014
  req.dataverse_name,
@@ -6663,6 +7097,23 @@ cb_Backend_document_analytics(VALUE self, VALUE statement, VALUE options)
6663
7097
  req.scan_consistency = couchbase::operations::analytics_request::scan_consistency_type::request_plus;
6664
7098
  }
6665
7099
  }
7100
+ VALUE scope_qualifier = rb_hash_aref(options, rb_id2sym(rb_intern("scope_qualifier")));
7101
+ if (!NIL_P(scope_qualifier) && TYPE(scope_qualifier) == T_STRING) {
7102
+ req.scope_qualifier.emplace(std::string(RSTRING_PTR(scope_qualifier), static_cast<std::size_t>(RSTRING_LEN(scope_qualifier))));
7103
+ } else {
7104
+ VALUE scope_name = rb_hash_aref(options, rb_id2sym(rb_intern("scope_name")));
7105
+ if (!NIL_P(scope_name) && TYPE(scope_name) == T_STRING) {
7106
+ req.scope_name.emplace(std::string(RSTRING_PTR(scope_name), static_cast<std::size_t>(RSTRING_LEN(scope_name))));
7107
+ VALUE bucket_name = rb_hash_aref(options, rb_id2sym(rb_intern("bucket_name")));
7108
+ if (NIL_P(bucket_name)) {
7109
+ exc = rb_exc_new_cstr(
7110
+ eInvalidArgument,
7111
+ fmt::format("bucket must be specified for analytics query in scope \"{}\"", req.scope_name.value()).c_str());
7112
+ break;
7113
+ }
7114
+ req.bucket_name.emplace(std::string(RSTRING_PTR(bucket_name), static_cast<std::size_t>(RSTRING_LEN(bucket_name))));
7115
+ }
7116
+ }
6666
7117
 
6667
7118
  VALUE raw_params = rb_hash_aref(options, rb_id2sym(rb_intern("raw_parameters")));
6668
7119
  if (!NIL_P(raw_params)) {
@@ -6675,20 +7126,13 @@ cb_Backend_document_analytics(VALUE self, VALUE statement, VALUE options)
6675
7126
  backend->cluster->execute_http(req,
6676
7127
  [barrier](couchbase::operations::analytics_response&& resp) mutable { barrier->set_value(resp); });
6677
7128
  auto resp = f.get();
6678
- if (resp.ec) {
7129
+ if (resp.ctx.ec) {
6679
7130
  if (resp.payload.meta_data.errors && !resp.payload.meta_data.errors->empty()) {
6680
7131
  const auto& first_error = resp.payload.meta_data.errors->front();
6681
- exc = cb__map_error_code(resp.ec,
6682
- fmt::format("unable to execute analytics query: \"{}{}\" ({}: {})",
6683
- req.statement.substr(0, 50),
6684
- req.statement.size() > 50 ? "..." : "",
6685
- first_error.code,
6686
- first_error.message));
7132
+ exc = cb__map_error_code(resp.ctx,
7133
+ fmt::format("unable to execute analytics query ({}: {})", first_error.code, first_error.message));
6687
7134
  } else {
6688
- exc = cb__map_error_code(resp.ec,
6689
- fmt::format("unable to execute analytics query: \"{}{}\"",
6690
- req.statement.substr(0, 50),
6691
- req.statement.size() > 50 ? "..." : ""));
7135
+ exc = cb__map_error_code(resp.ctx, "unable to execute analytics query");
6692
7136
  }
6693
7137
  break;
6694
7138
  }
@@ -6696,40 +7140,43 @@ cb_Backend_document_analytics(VALUE self, VALUE statement, VALUE options)
6696
7140
  VALUE rows = rb_ary_new_capa(static_cast<long>(resp.payload.rows.size()));
6697
7141
  rb_hash_aset(res, rb_id2sym(rb_intern("rows")), rows);
6698
7142
  for (auto& row : resp.payload.rows) {
6699
- rb_ary_push(rows, rb_str_new(row.data(), static_cast<long>(row.size())));
7143
+ rb_ary_push(rows, rb_external_str_new(row.data(), static_cast<long>(row.size())));
6700
7144
  }
6701
7145
  VALUE meta = rb_hash_new();
6702
7146
  rb_hash_aset(res, rb_id2sym(rb_intern("meta")), meta);
6703
7147
  rb_hash_aset(meta,
6704
7148
  rb_id2sym(rb_intern("status")),
6705
7149
  rb_id2sym(rb_intern2(resp.payload.meta_data.status.data(), static_cast<long>(resp.payload.meta_data.status.size()))));
6706
- rb_hash_aset(meta,
6707
- rb_id2sym(rb_intern("request_id")),
6708
- rb_str_new(resp.payload.meta_data.request_id.data(), static_cast<long>(resp.payload.meta_data.request_id.size())));
6709
7150
  rb_hash_aset(
6710
7151
  meta,
6711
- rb_id2sym(rb_intern("client_context_id")),
6712
- rb_str_new(resp.payload.meta_data.client_context_id.data(), static_cast<long>(resp.payload.meta_data.client_context_id.size())));
7152
+ rb_id2sym(rb_intern("request_id")),
7153
+ rb_external_str_new(resp.payload.meta_data.request_id.data(), static_cast<long>(resp.payload.meta_data.request_id.size())));
7154
+ rb_hash_aset(meta,
7155
+ rb_id2sym(rb_intern("client_context_id")),
7156
+ rb_external_str_new(resp.payload.meta_data.client_context_id.data(),
7157
+ static_cast<long>(resp.payload.meta_data.client_context_id.size())));
6713
7158
  if (resp.payload.meta_data.signature) {
6714
- rb_hash_aset(meta,
6715
- rb_id2sym(rb_intern("signature")),
6716
- rb_str_new(resp.payload.meta_data.signature->data(), static_cast<long>(resp.payload.meta_data.signature->size())));
7159
+ rb_hash_aset(
7160
+ meta,
7161
+ rb_id2sym(rb_intern("signature")),
7162
+ rb_external_str_new(resp.payload.meta_data.signature->data(), static_cast<long>(resp.payload.meta_data.signature->size())));
6717
7163
  }
6718
7164
  if (resp.payload.meta_data.profile) {
6719
- rb_hash_aset(meta,
6720
- rb_id2sym(rb_intern("profile")),
6721
- rb_str_new(resp.payload.meta_data.profile->data(), static_cast<long>(resp.payload.meta_data.profile->size())));
7165
+ rb_hash_aset(
7166
+ meta,
7167
+ rb_id2sym(rb_intern("profile")),
7168
+ rb_external_str_new(resp.payload.meta_data.profile->data(), static_cast<long>(resp.payload.meta_data.profile->size())));
6722
7169
  }
6723
7170
  VALUE metrics = rb_hash_new();
6724
7171
  rb_hash_aset(meta, rb_id2sym(rb_intern("metrics")), metrics);
6725
7172
  rb_hash_aset(metrics,
6726
7173
  rb_id2sym(rb_intern("elapsed_time")),
6727
- rb_str_new(resp.payload.meta_data.metrics.elapsed_time.data(),
6728
- static_cast<long>(resp.payload.meta_data.metrics.elapsed_time.size())));
7174
+ rb_external_str_new(resp.payload.meta_data.metrics.elapsed_time.data(),
7175
+ static_cast<long>(resp.payload.meta_data.metrics.elapsed_time.size())));
6729
7176
  rb_hash_aset(metrics,
6730
7177
  rb_id2sym(rb_intern("execution_time")),
6731
- rb_str_new(resp.payload.meta_data.metrics.execution_time.data(),
6732
- static_cast<long>(resp.payload.meta_data.metrics.execution_time.size())));
7178
+ rb_external_str_new(resp.payload.meta_data.metrics.execution_time.data(),
7179
+ static_cast<long>(resp.payload.meta_data.metrics.execution_time.size())));
6733
7180
  rb_hash_aset(metrics, rb_id2sym(rb_intern("result_count")), ULL2NUM(resp.payload.meta_data.metrics.result_count));
6734
7181
  rb_hash_aset(metrics, rb_id2sym(rb_intern("result_size")), ULL2NUM(resp.payload.meta_data.metrics.result_count));
6735
7182
  if (resp.payload.meta_data.metrics.sort_count) {
@@ -6762,14 +7209,16 @@ cb_Backend_parse_connection_string(VALUE self, VALUE connection_string)
6762
7209
 
6763
7210
  VALUE res = rb_hash_new();
6764
7211
  if (!connstr.scheme.empty()) {
6765
- rb_hash_aset(res, rb_id2sym(rb_intern("scheme")), rb_str_new(connstr.scheme.data(), static_cast<long>(connstr.scheme.size())));
7212
+ rb_hash_aset(
7213
+ res, rb_id2sym(rb_intern("scheme")), rb_external_str_new(connstr.scheme.data(), static_cast<long>(connstr.scheme.size())));
6766
7214
  rb_hash_aset(res, rb_id2sym(rb_intern("tls")), connstr.tls ? Qtrue : Qfalse);
6767
7215
  }
6768
7216
 
6769
7217
  VALUE nodes = rb_ary_new_capa(static_cast<long>(connstr.bootstrap_nodes.size()));
6770
7218
  for (const auto& entry : connstr.bootstrap_nodes) {
6771
7219
  VALUE node = rb_hash_new();
6772
- rb_hash_aset(node, rb_id2sym(rb_intern("address")), rb_str_new(entry.address.data(), static_cast<long>(entry.address.size())));
7220
+ rb_hash_aset(
7221
+ node, rb_id2sym(rb_intern("address")), rb_external_str_new(entry.address.data(), static_cast<long>(entry.address.size())));
6773
7222
  if (entry.port > 0) {
6774
7223
  rb_hash_aset(node, rb_id2sym(rb_intern("port")), UINT2NUM(entry.port));
6775
7224
  }
@@ -6801,15 +7250,15 @@ cb_Backend_parse_connection_string(VALUE self, VALUE connection_string)
6801
7250
  VALUE params = rb_hash_new();
6802
7251
  for (const auto& param : connstr.params) {
6803
7252
  rb_hash_aset(params,
6804
- rb_str_new(param.first.data(), static_cast<long>(param.first.size())),
6805
- rb_str_new(param.second.data(), static_cast<long>(param.second.size())));
7253
+ rb_external_str_new(param.first.data(), static_cast<long>(param.first.size())),
7254
+ rb_external_str_new(param.second.data(), static_cast<long>(param.second.size())));
6806
7255
  }
6807
7256
  rb_hash_aset(res, rb_id2sym(rb_intern("params")), params);
6808
7257
 
6809
7258
  if (connstr.default_bucket_name) {
6810
7259
  rb_hash_aset(res,
6811
7260
  rb_id2sym(rb_intern("default_bucket_name")),
6812
- rb_str_new(connstr.default_bucket_name->data(), static_cast<long>(connstr.default_bucket_name->size())));
7261
+ rb_external_str_new(connstr.default_bucket_name->data(), static_cast<long>(connstr.default_bucket_name->size())));
6813
7262
  }
6814
7263
  if (connstr.default_port > 0) {
6815
7264
  rb_hash_aset(res, rb_id2sym(rb_intern("default_port")), UINT2NUM(connstr.default_port));
@@ -6825,7 +7274,8 @@ cb_Backend_parse_connection_string(VALUE self, VALUE connection_string)
6825
7274
  break;
6826
7275
  }
6827
7276
  if (connstr.error) {
6828
- rb_hash_aset(res, rb_id2sym(rb_intern("error")), rb_str_new(connstr.error->data(), static_cast<long>(connstr.error->size())));
7277
+ rb_hash_aset(
7278
+ res, rb_id2sym(rb_intern("error")), rb_external_str_new(connstr.error->data(), static_cast<long>(connstr.error->size())));
6829
7279
  }
6830
7280
  return res;
6831
7281
  }
@@ -6869,15 +7319,15 @@ cb_Backend_view_index_get_all(VALUE self, VALUE bucket_name, VALUE name_space, V
6869
7319
  backend->cluster->execute_http(
6870
7320
  req, [barrier](couchbase::operations::view_index_get_all_response&& resp) mutable { barrier->set_value(resp); });
6871
7321
  auto resp = f.get();
6872
- if (resp.ec) {
6873
- exc = cb__map_error_code(resp.ec, "unable to get list of the design documents");
7322
+ if (resp.ctx.ec) {
7323
+ exc = cb__map_error_code(resp.ctx, "unable to get list of the design documents");
6874
7324
  break;
6875
7325
  }
6876
7326
  VALUE res = rb_ary_new_capa(static_cast<long>(resp.design_documents.size()));
6877
7327
  for (const auto& entry : resp.design_documents) {
6878
7328
  VALUE dd = rb_hash_new();
6879
- rb_hash_aset(dd, rb_id2sym(rb_intern("name")), rb_str_new(entry.name.data(), static_cast<long>(entry.name.size())));
6880
- rb_hash_aset(dd, rb_id2sym(rb_intern("rev")), rb_str_new(entry.rev.data(), static_cast<long>(entry.rev.size())));
7329
+ rb_hash_aset(dd, rb_id2sym(rb_intern("name")), rb_external_str_new(entry.name.data(), static_cast<long>(entry.name.size())));
7330
+ rb_hash_aset(dd, rb_id2sym(rb_intern("rev")), rb_external_str_new(entry.rev.data(), static_cast<long>(entry.rev.size())));
6881
7331
  switch (entry.ns) {
6882
7332
  case couchbase::operations::design_document::name_space::development:
6883
7333
  rb_hash_aset(dd, rb_id2sym(rb_intern("namespace")), rb_id2sym(rb_intern("development")));
@@ -6888,18 +7338,19 @@ cb_Backend_view_index_get_all(VALUE self, VALUE bucket_name, VALUE name_space, V
6888
7338
  }
6889
7339
  VALUE views = rb_hash_new();
6890
7340
  for (const auto& view_entry : entry.views) {
6891
- VALUE view_name = rb_str_new(view_entry.first.data(), static_cast<long>(view_entry.first.size()));
7341
+ VALUE view_name = rb_external_str_new(view_entry.first.data(), static_cast<long>(view_entry.first.size()));
6892
7342
  VALUE view = rb_hash_new();
6893
7343
  rb_hash_aset(view, rb_id2sym(rb_intern("name")), view_name);
6894
7344
  if (view_entry.second.map) {
6895
7345
  rb_hash_aset(view,
6896
7346
  rb_id2sym(rb_intern("map")),
6897
- rb_str_new(view_entry.second.map->data(), static_cast<long>(view_entry.second.map->size())));
7347
+ rb_external_str_new(view_entry.second.map->data(), static_cast<long>(view_entry.second.map->size())));
6898
7348
  }
6899
7349
  if (view_entry.second.reduce) {
6900
- rb_hash_aset(view,
6901
- rb_id2sym(rb_intern("reduce")),
6902
- rb_str_new(view_entry.second.reduce->data(), static_cast<long>(view_entry.second.reduce->size())));
7350
+ rb_hash_aset(
7351
+ view,
7352
+ rb_id2sym(rb_intern("reduce")),
7353
+ rb_external_str_new(view_entry.second.reduce->data(), static_cast<long>(view_entry.second.reduce->size())));
6903
7354
  }
6904
7355
  rb_hash_aset(views, view_name, view);
6905
7356
  }
@@ -6953,16 +7404,17 @@ cb_Backend_view_index_get(VALUE self, VALUE bucket_name, VALUE document_name, VA
6953
7404
  backend->cluster->execute_http(
6954
7405
  req, [barrier](couchbase::operations::view_index_get_response&& resp) mutable { barrier->set_value(resp); });
6955
7406
  auto resp = f.get();
6956
- if (resp.ec) {
7407
+ if (resp.ctx.ec) {
6957
7408
  exc = cb__map_error_code(
6958
- resp.ec,
7409
+ resp.ctx,
6959
7410
  fmt::format(R"(unable to get design document "{}" ({}) on bucket "{}")", req.document_name, req.name_space, req.bucket_name));
6960
7411
  break;
6961
7412
  }
6962
7413
  VALUE res = rb_hash_new();
6963
7414
  rb_hash_aset(
6964
- res, rb_id2sym(rb_intern("name")), rb_str_new(resp.document.name.data(), static_cast<long>(resp.document.name.size())));
6965
- rb_hash_aset(res, rb_id2sym(rb_intern("rev")), rb_str_new(resp.document.rev.data(), static_cast<long>(resp.document.rev.size())));
7415
+ res, rb_id2sym(rb_intern("name")), rb_external_str_new(resp.document.name.data(), static_cast<long>(resp.document.name.size())));
7416
+ rb_hash_aset(
7417
+ res, rb_id2sym(rb_intern("rev")), rb_external_str_new(resp.document.rev.data(), static_cast<long>(resp.document.rev.size())));
6966
7418
  switch (resp.document.ns) {
6967
7419
  case couchbase::operations::design_document::name_space::development:
6968
7420
  rb_hash_aset(res, rb_id2sym(rb_intern("namespace")), rb_id2sym(rb_intern("development")));
@@ -6973,18 +7425,18 @@ cb_Backend_view_index_get(VALUE self, VALUE bucket_name, VALUE document_name, VA
6973
7425
  }
6974
7426
  VALUE views = rb_hash_new();
6975
7427
  for (const auto& view_entry : resp.document.views) {
6976
- VALUE view_name = rb_str_new(view_entry.first.data(), static_cast<long>(view_entry.first.size()));
7428
+ VALUE view_name = rb_external_str_new(view_entry.first.data(), static_cast<long>(view_entry.first.size()));
6977
7429
  VALUE view = rb_hash_new();
6978
7430
  rb_hash_aset(view, rb_id2sym(rb_intern("name")), view_name);
6979
7431
  if (view_entry.second.map) {
6980
7432
  rb_hash_aset(view,
6981
7433
  rb_id2sym(rb_intern("map")),
6982
- rb_str_new(view_entry.second.map->data(), static_cast<long>(view_entry.second.map->size())));
7434
+ rb_external_str_new(view_entry.second.map->data(), static_cast<long>(view_entry.second.map->size())));
6983
7435
  }
6984
7436
  if (view_entry.second.reduce) {
6985
7437
  rb_hash_aset(view,
6986
7438
  rb_id2sym(rb_intern("reduce")),
6987
- rb_str_new(view_entry.second.reduce->data(), static_cast<long>(view_entry.second.reduce->size())));
7439
+ rb_external_str_new(view_entry.second.reduce->data(), static_cast<long>(view_entry.second.reduce->size())));
6988
7440
  }
6989
7441
  rb_hash_aset(views, view_name, view);
6990
7442
  }
@@ -7036,9 +7488,9 @@ cb_Backend_view_index_drop(VALUE self, VALUE bucket_name, VALUE document_name, V
7036
7488
  backend->cluster->execute_http(
7037
7489
  req, [barrier](couchbase::operations::view_index_drop_response&& resp) mutable { barrier->set_value(resp); });
7038
7490
  auto resp = f.get();
7039
- if (resp.ec) {
7491
+ if (resp.ctx.ec) {
7040
7492
  exc = cb__map_error_code(
7041
- resp.ec,
7493
+ resp.ctx,
7042
7494
  fmt::format(
7043
7495
  R"(unable to drop design document "{}" ({}) on bucket "{}")", req.document_name, req.name_space, req.bucket_name));
7044
7496
  break;
@@ -7117,9 +7569,9 @@ cb_Backend_view_index_upsert(VALUE self, VALUE bucket_name, VALUE document, VALU
7117
7569
  backend->cluster->execute_http(
7118
7570
  req, [barrier](couchbase::operations::view_index_upsert_response&& resp) mutable { barrier->set_value(resp); });
7119
7571
  auto resp = f.get();
7120
- if (resp.ec) {
7572
+ if (resp.ctx.ec) {
7121
7573
  exc = cb__map_error_code(
7122
- resp.ec,
7574
+ resp.ctx,
7123
7575
  fmt::format(
7124
7576
  R"(unable to store design document "{}" ({}) on bucket "{}")", req.document.name, req.document.ns, req.bucket_name));
7125
7577
  break;
@@ -7267,24 +7719,12 @@ cb_Backend_document_view(VALUE self, VALUE bucket_name, VALUE design_document_na
7267
7719
  backend->cluster->execute_http(
7268
7720
  req, [barrier](couchbase::operations::document_view_response&& resp) mutable { barrier->set_value(resp); });
7269
7721
  auto resp = f.get();
7270
- if (resp.ec) {
7722
+ if (resp.ctx.ec) {
7271
7723
  if (resp.error) {
7272
- exc = cb__map_error_code(
7273
- resp.ec,
7274
- fmt::format(R"(unable to execute query for view "{}" of design document "{}" ({}) on bucket "{}": {} ({}))",
7275
- req.view_name,
7276
- req.document_name,
7277
- req.name_space,
7278
- req.bucket_name,
7279
- resp.error->code,
7280
- resp.error->message));
7724
+ exc = cb__map_error_code(resp.ctx,
7725
+ fmt::format(R"(unable to execute view query {} ({}))", resp.error->code, resp.error->message));
7281
7726
  } else {
7282
- exc = cb__map_error_code(resp.ec,
7283
- fmt::format(R"(unable to execute query for view "{}" of design document "{}" ({}) on bucket "{}")",
7284
- req.view_name,
7285
- req.document_name,
7286
- req.name_space,
7287
- req.bucket_name));
7727
+ exc = cb__map_error_code(resp.ctx, "unable to execute view query");
7288
7728
  }
7289
7729
  break;
7290
7730
  }
@@ -7297,7 +7737,7 @@ cb_Backend_document_view(VALUE self, VALUE bucket_name, VALUE design_document_na
7297
7737
  if (resp.meta_data.debug_info) {
7298
7738
  rb_hash_aset(meta,
7299
7739
  rb_id2sym(rb_intern("debug_info")),
7300
- rb_str_new(resp.meta_data.debug_info->data(), static_cast<long>(resp.meta_data.debug_info->size())));
7740
+ rb_external_str_new(resp.meta_data.debug_info->data(), static_cast<long>(resp.meta_data.debug_info->size())));
7301
7741
  }
7302
7742
  rb_hash_aset(res, rb_id2sym(rb_intern("meta")), meta);
7303
7743
 
@@ -7305,10 +7745,11 @@ cb_Backend_document_view(VALUE self, VALUE bucket_name, VALUE design_document_na
7305
7745
  for (const auto& entry : resp.rows) {
7306
7746
  VALUE row = rb_hash_new();
7307
7747
  if (entry.id) {
7308
- rb_hash_aset(row, rb_id2sym(rb_intern("id")), rb_str_new(entry.id->data(), static_cast<long>(entry.id->size())));
7748
+ rb_hash_aset(row, rb_id2sym(rb_intern("id")), rb_external_str_new(entry.id->data(), static_cast<long>(entry.id->size())));
7309
7749
  }
7310
- rb_hash_aset(row, rb_id2sym(rb_intern("key")), rb_str_new(entry.key.data(), static_cast<long>(entry.key.size())));
7311
- rb_hash_aset(row, rb_id2sym(rb_intern("value")), rb_str_new(entry.value.data(), static_cast<long>(entry.value.size())));
7750
+ rb_hash_aset(row, rb_id2sym(rb_intern("key")), rb_external_str_new(entry.key.data(), static_cast<long>(entry.key.size())));
7751
+ rb_hash_aset(
7752
+ row, rb_id2sym(rb_intern("value")), rb_external_str_new(entry.value.data(), static_cast<long>(entry.value.size())));
7312
7753
  rb_ary_push(rows, row);
7313
7754
  }
7314
7755
  rb_hash_aset(res, rb_id2sym(rb_intern("rows")), rows);
@@ -7379,7 +7820,7 @@ cb_Backend_snappy_compress(VALUE self, VALUE data)
7379
7820
 
7380
7821
  std::string compressed{};
7381
7822
  std::size_t compressed_size = snappy::Compress(RSTRING_PTR(data), static_cast<std::size_t>(RSTRING_LEN(data)), &compressed);
7382
- return rb_str_new(compressed.data(), static_cast<long>(compressed_size));
7823
+ return rb_external_str_new(compressed.data(), static_cast<long>(compressed_size));
7383
7824
  }
7384
7825
 
7385
7826
  static VALUE
@@ -7391,7 +7832,7 @@ cb_Backend_snappy_uncompress(VALUE self, VALUE data)
7391
7832
  std::string uncompressed{};
7392
7833
  bool success = snappy::Uncompress(RSTRING_PTR(data), static_cast<std::size_t>(RSTRING_LEN(data)), &uncompressed);
7393
7834
  if (success) {
7394
- return rb_str_new(uncompressed.data(), static_cast<long>(uncompressed.size()));
7835
+ return rb_external_str_new(uncompressed.data(), static_cast<long>(uncompressed.size()));
7395
7836
  }
7396
7837
  rb_raise(rb_eArgError, "Unable to decompress buffer");
7397
7838
  return Qnil;
@@ -7410,7 +7851,7 @@ cb_Backend_leb128_encode(VALUE self, VALUE number)
7410
7851
  }
7411
7852
  couchbase::protocol::unsigned_leb128<std::uint64_t> encoded(NUM2ULL(number));
7412
7853
  std::string buf = encoded.get();
7413
- return rb_str_new(buf.data(), static_cast<long>(buf.size()));
7854
+ return rb_external_str_new(buf.data(), static_cast<long>(buf.size()));
7414
7855
  }
7415
7856
 
7416
7857
  static VALUE
@@ -7421,7 +7862,7 @@ cb_Backend_leb128_decode(VALUE self, VALUE data)
7421
7862
  std::string buf(RSTRING_PTR(data), static_cast<std::size_t>(RSTRING_LEN(data)));
7422
7863
  if (!buf.empty()) {
7423
7864
  auto rv = couchbase::protocol::decode_unsigned_leb128<std::uint64_t>(buf, couchbase::protocol::Leb128NoThrow());
7424
- if (rv.second.data()) {
7865
+ if (rv.second.data() != nullptr) {
7425
7866
  return ULL2NUM(rv.first);
7426
7867
  }
7427
7868
  }
@@ -7554,7 +7995,10 @@ init_logger()
7554
7995
  spdlog::cfg::helpers::load_levels(env_val);
7555
7996
  }
7556
7997
 
7557
- couchbase::platform::install_backtrace_terminate_handler();
7998
+ env_val = spdlog::details::os::getenv("COUCHBASE_BACKEND_DONT_INSTALL_TERMINATE_HANDLER");
7999
+ if (env_val.empty()) {
8000
+ couchbase::platform::install_backtrace_terminate_handler();
8001
+ }
7558
8002
  }
7559
8003
 
7560
8004
  extern "C" {