couchbase 3.9.0 → 3.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0a72603dc40eb6d8ba7d1636cf67372ef65fc11f59e0617934514e96117bd5fb
4
- data.tar.gz: 2adf92e075788643ed2943884221066a023c6a2e5ac7cad8636d72f3562e7bb4
3
+ metadata.gz: 2c9165b07ea3bb12062cc5e778c2ac9642f30b39ef9ac83227d7f056be5dedae
4
+ data.tar.gz: 2092c8f82df2b1a225585baeb53506f914c2fa8225e41b3eed1640ab21bd1eba
5
5
  SHA512:
6
- metadata.gz: 37fbf00228a35e36bbb7e1bddb780cb634bb563159165305f7c9a1980b0dbd01777c7d2e6478fa59a3a8e13a5dd4e7d2db49b0e9ecedd05b48cad6d571cc125b
7
- data.tar.gz: 206550bc22e145d9fa43dc239ed83ddf08b0ad82247aac0c5c17aecf071d73a1e77034dcf322a84ab419a45121ef890d97c64365b7e550b1c5ed58c914b8dd29
6
+ metadata.gz: 44cec54d8295fb96753fdb035edc77be74925cf2fc028b2fa647ba26cdb8ea018b5f48f07b1fac129853f41b7050f6680ae612690363e7c3e2ee82376a0c1d41
7
+ data.tar.gz: bb3802becc6da9d4aca3b085cc8f9b4ff88415d0d2d155ac62980cef6d051bcb86d2e93d3cc192ec399b5780583260d309a2c8cc07a97cf15d8e9669b50ff289
data/README.md CHANGED
@@ -23,7 +23,7 @@ The library has been tested with MRI 3.2, 3.3, 3.4 and 4.0. Supported platforms
23
23
  Add this line to your application's Gemfile:
24
24
 
25
25
  ```ruby
26
- gem "couchbase", "3.9.0"
26
+ gem "couchbase", "3.9.1"
27
27
  ```
28
28
 
29
29
  And then execute:
@@ -3,7 +3,7 @@ cmake_flags << "-DCPM_USE_NAMED_CACHE_DIRECTORIES=ON"
3
3
  cmake_flags << "-DCPM_USE_LOCAL_PACKAGES=OFF"
4
4
  cmake_flags << "-DCPM_SOURCE_CACHE=#{__dir__}"
5
5
  cmake_flags << "-DCOUCHBASE_CXX_CLIENT_EMBED_MOZILLA_CA_BUNDLE_ROOT=#{__dir__}"
6
- cmake_flags << "-DEXT_GIT_REVISION=efbce2324574ed7bfaa7c9db131b82154dbdd178"
7
- cmake_flags << "-DCOUCHBASE_CXX_CLIENT_GIT_REVISION=380784c1f5a69aecc464911b2d29a68c7150a0ba"
8
- cmake_flags << "-DCOUCHBASE_CXX_CLIENT_GIT_DESCRIBE=1.5.0-0-g380784c1"
9
- cmake_flags << "-DCOUCHBASE_CXX_CLIENT_BUILD_TIMESTAMP=2026-10-20T15:47:48"
6
+ cmake_flags << "-DEXT_GIT_REVISION=18481d03bfc5d030af5235fc7daf35b9d58ba38c"
7
+ cmake_flags << "-DCOUCHBASE_CXX_CLIENT_GIT_REVISION=33c90f28cede04652cfb7edae748b84fe82c39a1"
8
+ cmake_flags << "-DCOUCHBASE_CXX_CLIENT_GIT_DESCRIBE=1.5.1-0-g33c90f28"
9
+ cmake_flags << "-DCOUCHBASE_CXX_CLIENT_BUILD_TIMESTAMP=2026-10-23T22:11:52"
@@ -16,7 +16,7 @@ endif()
16
16
 
17
17
  project(
18
18
  couchbase_cxx_client
19
- VERSION "1.5.0"
19
+ VERSION "1.5.1"
20
20
  LANGUAGES CXX C)
21
21
  message(
22
22
  STATUS
@@ -562,8 +562,12 @@ if(COUCHBASE_CXX_CLIENT_BUILD_SHARED OR BUILD_SHARED_LIBS)
562
562
  add_library(couchbase_cxx_client SHARED ${couchbase_cxx_client_FILES})
563
563
  add_library(couchbase_cxx_client::couchbase_cxx_client ALIAS couchbase_cxx_client)
564
564
 
565
- set_target_properties(couchbase_cxx_client PROPERTIES VERSION ${couchbase_cxx_client_VERSION_MAJOR}
566
- SOVERSION ${couchbase_cxx_client_VERSION})
565
+ # The soname carries MAJOR.MINOR. A patch release keeps the ABI, so a binary linked against one
566
+ # MAJOR.MINOR release loads every later patch of it; a minor release may change the ABI and the soname.
567
+ set_target_properties(
568
+ couchbase_cxx_client
569
+ PROPERTIES VERSION ${couchbase_cxx_client_VERSION}
570
+ SOVERSION ${couchbase_cxx_client_VERSION_MAJOR}.${couchbase_cxx_client_VERSION_MINOR})
567
571
  list(APPEND couchbase_cxx_client_LIBRARIES couchbase_cxx_client)
568
572
  if(NOT WIN32)
569
573
  set(couchbase_cxx_client_DEFAULT_LIBRARY couchbase_cxx_client::couchbase_cxx_client)
@@ -238,15 +238,29 @@ set(CA_BUNDLE_CPP_FILE "${CMAKE_CURRENT_BINARY_DIR}/generated/mozilla_ca_bundle.
238
238
  # seems to be cross-platform and fast.
239
239
  string(
240
240
  REGEX MATCHALL
241
- "[^=#]+=+\n-----BEGIN CERTIFICATE-----[^-]+-----END CERTIFICATE-----"
241
+ "[^\n]+\n=+\n(#[^\n]*\n)*-----BEGIN CERTIFICATE-----[^-]+-----END CERTIFICATE-----"
242
242
  CERTIFICATES
243
243
  "${CA_BUNDLE_CONTENT}")
244
244
  list(LENGTH CERTIFICATES NUMBER_OF_CERTIFICATES)
245
+ if(COUCHBASE_CXX_CLIENT_EMBED_MOZILLA_CA_BUNDLE)
246
+ # A bundle layout that the certificate expressions do not recognise fails configure. Otherwise the
247
+ # library builds with fewer default roots than the bundle carries, or none.
248
+ string(REGEX MATCHALL "-----BEGIN CERTIFICATE-----" PEM_BLOCKS "${CA_BUNDLE_CONTENT}")
249
+ list(LENGTH PEM_BLOCKS NUMBER_OF_PEM_BLOCKS)
250
+ if(NUMBER_OF_CERTIFICATES EQUAL 0 OR NOT NUMBER_OF_CERTIFICATES EQUAL NUMBER_OF_PEM_BLOCKS)
251
+ message(
252
+ FATAL_ERROR
253
+ "Extracted ${NUMBER_OF_CERTIFICATES} of ${NUMBER_OF_PEM_BLOCKS} certificates from "
254
+ "${COUCHBASE_CXX_CLIENT_EMBED_MOZILLA_CA_BUNDLE_ROOT}/mozilla-ca-bundle.crt")
255
+ endif()
256
+ endif()
245
257
  file(
246
258
  WRITE ${CA_BUNDLE_CPP_FILE}
247
259
  "
248
260
  #include \"core/mozilla_ca_bundle.hxx\"
249
261
 
262
+ #include <couchbase/build_config.hxx>
263
+
250
264
  #include <gsl/span>
251
265
 
252
266
  #include <array>
@@ -256,23 +270,77 @@ namespace couchbase::core::default_ca
256
270
  {
257
271
  constexpr inline std::array<certificate, ${NUMBER_OF_CERTIFICATES}> certificates{
258
272
  ")
273
+ set(CERTIFICATE_BODIES "")
259
274
  foreach(CERTIFICATE ${CERTIFICATES})
260
275
  string(
261
276
  REGEX MATCH
262
- "[ \t\r\n]*([^=\n]+)[ \t\r\n]*=+\n(-----BEGIN CERTIFICATE-----[^-]+-----END CERTIFICATE-----)"
277
+ "^([^\n]+)\n=+\n(#[^\n]*\n)*(-----BEGIN CERTIFICATE-----[^-]+-----END CERTIFICATE-----)$"
263
278
  PARTS
264
- ${CERTIFICATE})
279
+ "${CERTIFICATE}")
280
+ if(NOT PARTS)
281
+ message(FATAL_ERROR "Unable to split CA bundle entry into name and certificate:\n${CERTIFICATE}")
282
+ endif()
283
+ set(CERTIFICATE_NAME "${CMAKE_MATCH_1}")
284
+ set(CERTIFICATE_BODY "${CMAKE_MATCH_3}")
285
+ if(NOT CERTIFICATE_BODY MATCHES "^-----BEGIN CERTIFICATE-----\n([A-Za-z0-9+/=]+\n)+-----END CERTIFICATE-----$")
286
+ message(FATAL_ERROR "CA bundle entry \"${CERTIFICATE_NAME}\" is not a PEM certificate:\n${CERTIFICATE_BODY}")
287
+ endif()
288
+ # The name is emitted as an R"(...)" literal, which ends at the first )" it contains. The body
289
+ # cannot contain one: the PEM check above admits no ')'.
290
+ string(FIND "${CERTIFICATE_NAME}" ")\"" CLOSING_DELIMITER)
291
+ if(NOT CLOSING_DELIMITER EQUAL -1)
292
+ message(FATAL_ERROR "CA bundle entry name cannot be embedded as a raw string: ${CERTIFICATE_NAME}")
293
+ endif()
294
+ list(APPEND CERTIFICATE_BODIES "${CERTIFICATE_BODY}")
265
295
  file(APPEND ${CA_BUNDLE_CPP_FILE}
266
- " certificate{ R\"(${CMAKE_MATCH_1})\",
267
- R\"(${CMAKE_MATCH_2})\", },
296
+ " certificate{ R\"(${CERTIFICATE_NAME})\",
297
+ R\"(${CERTIFICATE_BODY})\", },
268
298
 
269
299
  ")
270
300
  endforeach()
301
+ set(UNIQUE_CERTIFICATE_BODIES ${CERTIFICATE_BODIES})
302
+ list(REMOVE_DUPLICATES UNIQUE_CERTIFICATE_BODIES)
303
+ list(LENGTH UNIQUE_CERTIFICATE_BODIES NUMBER_OF_UNIQUE_CERTIFICATES)
304
+ if(NOT NUMBER_OF_UNIQUE_CERTIFICATES EQUAL NUMBER_OF_CERTIFICATES)
305
+ message(FATAL_ERROR "CA bundle carries ${NUMBER_OF_CERTIFICATES} certificates, but only "
306
+ "${NUMBER_OF_UNIQUE_CERTIFICATES} are distinct")
307
+ endif()
271
308
 
272
309
  file(
273
310
  APPEND ${CA_BUNDLE_CPP_FILE}
274
311
  "};
275
312
 
313
+ namespace
314
+ {
315
+ constexpr auto
316
+ is_pem_certificate(std::string_view body) -> bool
317
+ {
318
+ constexpr std::string_view header{ \"-----BEGIN CERTIFICATE-----\\n\" };
319
+ constexpr std::string_view footer{ \"\\n-----END CERTIFICATE-----\" };
320
+ return body.size() > header.size() + footer.size() && body.substr(0, header.size()) == header &&
321
+ body.substr(body.size() - footer.size()) == footer;
322
+ }
323
+
324
+ constexpr auto
325
+ every_entry_is_named_certificate() -> bool
326
+ {
327
+ for (const auto& entry : certificates) {
328
+ if (entry.authority.empty() || !is_pem_certificate(entry.body)) {
329
+ return false;
330
+ }
331
+ }
332
+ return true;
333
+ }
334
+ } // namespace
335
+
336
+ // An array sized larger than its initialiser list value-initialises the remaining entries.
337
+ static_assert(every_entry_is_named_certificate(),
338
+ \"every embedded CA bundle entry carries a name and a PEM certificate\");
339
+ #if defined(COUCHBASE_CXX_CLIENT_EMBED_MOZILLA_CA_BUNDLE)
340
+ static_assert(!certificates.empty(),
341
+ \"COUCHBASE_CXX_CLIENT_EMBED_MOZILLA_CA_BUNDLE is enabled, but no certificates were embedded\");
342
+ #endif
343
+
276
344
  auto
277
345
  mozilla_ca_certs() -> gsl::span<const certificate>
278
346
  {
@@ -2651,22 +2651,21 @@ cluster::query_stream(operations::query_request request,
2651
2651
  std::chrono::steady_clock::now() +
2652
2652
  request.timeout.value_or(impl_->default_timeout_for(service_type::query));
2653
2653
  impl_->defer_until_open(
2654
- [&] {
2655
- return
2656
- [self = *this, deadline, request = std::move(request), handler = std::move(handler)](
2657
- std::error_code ec) mutable {
2658
- if (ec) {
2659
- error_context::query ctx{};
2660
- ctx.ec = ec;
2661
- ctx.statement = request.statement;
2662
- ctx.client_context_id = request.client_context_id.has_value()
2663
- ? *request.client_context_id
2664
- : uuid::to_string(uuid::random());
2665
- return handler({}, std::move(ctx));
2666
- }
2667
- request.timeout = remaining_until(deadline);
2668
- self.query_stream(std::move(request), std::move(handler));
2669
- };
2654
+ [&, self = *this] {
2655
+ return [self, deadline, request = std::move(request), handler = std::move(handler)](
2656
+ std::error_code ec) mutable {
2657
+ if (ec) {
2658
+ error_context::query ctx{};
2659
+ ctx.ec = ec;
2660
+ ctx.statement = request.statement;
2661
+ ctx.client_context_id = request.client_context_id.has_value()
2662
+ ? *request.client_context_id
2663
+ : uuid::to_string(uuid::random());
2664
+ return handler({}, std::move(ctx));
2665
+ }
2666
+ request.timeout = remaining_until(deadline);
2667
+ self.query_stream(std::move(request), std::move(handler));
2668
+ };
2670
2669
  },
2671
2670
  deadline)) {
2672
2671
  return;
@@ -2718,22 +2717,21 @@ cluster::analytics_query_stream(
2718
2717
  std::chrono::steady_clock::now() +
2719
2718
  request.timeout.value_or(impl_->default_timeout_for(service_type::analytics));
2720
2719
  impl_->defer_until_open(
2721
- [&] {
2722
- return
2723
- [self = *this, deadline, request = std::move(request), handler = std::move(handler)](
2724
- std::error_code ec) mutable {
2725
- if (ec) {
2726
- error_context::analytics ctx{};
2727
- ctx.ec = ec;
2728
- ctx.statement = request.statement;
2729
- ctx.client_context_id = request.client_context_id.has_value()
2730
- ? *request.client_context_id
2731
- : uuid::to_string(uuid::random());
2732
- return handler({}, std::move(ctx));
2733
- }
2734
- request.timeout = remaining_until(deadline);
2735
- self.analytics_query_stream(std::move(request), std::move(handler));
2736
- };
2720
+ [&, self = *this] {
2721
+ return [self, deadline, request = std::move(request), handler = std::move(handler)](
2722
+ std::error_code ec) mutable {
2723
+ if (ec) {
2724
+ error_context::analytics ctx{};
2725
+ ctx.ec = ec;
2726
+ ctx.statement = request.statement;
2727
+ ctx.client_context_id = request.client_context_id.has_value()
2728
+ ? *request.client_context_id
2729
+ : uuid::to_string(uuid::random());
2730
+ return handler({}, std::move(ctx));
2731
+ }
2732
+ request.timeout = remaining_until(deadline);
2733
+ self.analytics_query_stream(std::move(request), std::move(handler));
2734
+ };
2737
2735
  },
2738
2736
  deadline)) {
2739
2737
  return;
@@ -109,7 +109,7 @@ extract_eventing_error_code(const tao::json::value& response, std::uint32_t stat
109
109
  name->get_string(),
110
110
  description,
111
111
  };
112
- if (problem.name == "ERR_APP_NOT_FOUND_TS") {
112
+ if (problem.name == "ERR_APP_NOT_FOUND_TS" || problem.name == "ERR_APP_NOT_FOUND") {
113
113
  return { errc::management::eventing_function_not_found, problem };
114
114
  }
115
115
  if (problem.name == "ERR_APP_NOT_DEPLOYED") {
@@ -443,16 +443,18 @@ encode_payload_length(std::size_t length) -> std::vector<std::byte>
443
443
  }
444
444
  // 7 + 64
445
445
  constexpr std::uint8_t field_7_bit = 127 | flag_mask;
446
+ // std::size_t is 32 bits on 32-bit targets, where shifting it by 32 or more is undefined.
447
+ const std::uint64_t wide_length = length;
446
448
  return {
447
449
  std::byte{ field_7_bit },
448
- static_cast<std::byte>((length >> 56) & 0xff),
449
- static_cast<std::byte>((length >> 48) & 0xff),
450
- static_cast<std::byte>((length >> 40) & 0xff),
451
- static_cast<std::byte>((length >> 32) & 0xff),
452
- static_cast<std::byte>((length >> 24) & 0xff),
453
- static_cast<std::byte>((length >> 16) & 0xff),
454
- static_cast<std::byte>((length >> 8) & 0xff),
455
- static_cast<std::byte>(length & 0xff),
450
+ static_cast<std::byte>((wide_length >> 56) & 0xff),
451
+ static_cast<std::byte>((wide_length >> 48) & 0xff),
452
+ static_cast<std::byte>((wide_length >> 40) & 0xff),
453
+ static_cast<std::byte>((wide_length >> 32) & 0xff),
454
+ static_cast<std::byte>((wide_length >> 24) & 0xff),
455
+ static_cast<std::byte>((wide_length >> 16) & 0xff),
456
+ static_cast<std::byte>((wide_length >> 8) & 0xff),
457
+ static_cast<std::byte>(wide_length & 0xff),
456
458
  };
457
459
  }
458
460
 
@@ -888,7 +888,7 @@ enum class management {
888
888
  bucket_not_flushable = 607,
889
889
 
890
890
  /// Occurs if the function is not found
891
- /// name is "ERR_APP_NOT_FOUND_TS"
891
+ /// name is "ERR_APP_NOT_FOUND_TS" or "ERR_APP_NOT_FOUND"
892
892
  eventing_function_not_found = 608,
893
893
 
894
894
  /// Occurs if the function is not deployed, but the action expects it to
@@ -21,5 +21,5 @@ module Couchbase
21
21
  # $ ruby -rcouchbase -e 'pp Couchbase::VERSION'
22
22
  # {:sdk=>"3.4.0", :ruby_abi=>"3.1.0", :revision=>"416fe68e6029ec8a4c40611cf6e6b30d3b90d20f"}
23
23
  VERSION = {} unless defined?(VERSION) # rubocop:disable Style/MutableConstant
24
- VERSION.update(:sdk => "3.9.0")
24
+ VERSION.update(:sdk => "3.9.1")
25
25
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: couchbase
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.9.0
4
+ version: 3.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sergey Avseyev
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-10-21 00:00:00.000000000 Z
11
+ date: 2026-10-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -3729,9 +3729,9 @@ metadata:
3729
3729
  homepage_uri: https://docs.couchbase.com/ruby-sdk/current/hello-world/start-using-sdk.html
3730
3730
  bug_tracker_uri: https://jira.issues.couchbase.com/browse/RCBC
3731
3731
  mailing_list_uri: https://www.couchbase.com/forums/c/ruby-sdk
3732
- source_code_uri: https://github.com/couchbase/couchbase-ruby-client/tree/3.9.0
3733
- changelog_uri: https://github.com/couchbase/couchbase-ruby-client/releases/tag/3.9.0
3734
- documentation_uri: https://docs.couchbase.com/sdk-api/couchbase-ruby-client-3.9.0/index.html
3732
+ source_code_uri: https://github.com/couchbase/couchbase-ruby-client/tree/3.9.1
3733
+ changelog_uri: https://github.com/couchbase/couchbase-ruby-client/releases/tag/3.9.1
3734
+ documentation_uri: https://docs.couchbase.com/sdk-api/couchbase-ruby-client-3.9.1/index.html
3735
3735
  github_repo: https://github.com/couchbase/couchbase-ruby-client
3736
3736
  rubygems_mfa_required: 'true'
3737
3737
  post_install_message: