couchbase 3.0.2 → 3.0.3

Sign up to get free protection for your applications and to get access to all the features.
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" {