couchbase 3.0.0.alpha.5-universal-darwin-19 → 3.0.0.beta.1-universal-darwin-19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +12 -3
  3. data/README.md +4 -2
  4. data/Rakefile +1 -1
  5. data/couchbase.gemspec +17 -12
  6. data/ext/.idea/misc.xml +12 -0
  7. data/ext/CMakeLists.txt +10 -1
  8. data/ext/build_config.hxx.in +20 -0
  9. data/ext/build_version.hxx.in +1 -1
  10. data/ext/couchbase/bucket.hxx +90 -24
  11. data/ext/couchbase/cluster.hxx +125 -84
  12. data/ext/couchbase/cluster_options.hxx +53 -0
  13. data/ext/couchbase/configuration.hxx +220 -2
  14. data/ext/couchbase/couchbase.cxx +134 -127
  15. data/ext/couchbase/io/dns_client.hxx +3 -1
  16. data/ext/couchbase/io/http_command.hxx +91 -0
  17. data/ext/couchbase/io/http_session.hxx +58 -19
  18. data/ext/couchbase/io/http_session_manager.hxx +26 -31
  19. data/ext/couchbase/io/mcbp_command.hxx +180 -0
  20. data/ext/couchbase/io/mcbp_message.hxx +5 -0
  21. data/ext/couchbase/io/mcbp_session.hxx +213 -98
  22. data/ext/couchbase/io/streams.hxx +165 -0
  23. data/ext/couchbase/operations.hxx +1 -1
  24. data/ext/couchbase/operations/analytics_dataset_create.hxx +1 -1
  25. data/ext/couchbase/operations/bucket_create.hxx +4 -2
  26. data/ext/couchbase/operations/bucket_drop.hxx +4 -2
  27. data/ext/couchbase/operations/bucket_flush.hxx +4 -2
  28. data/ext/couchbase/operations/bucket_get.hxx +4 -2
  29. data/ext/couchbase/operations/bucket_get_all.hxx +4 -2
  30. data/ext/couchbase/operations/bucket_update.hxx +4 -2
  31. data/ext/couchbase/operations/cluster_developer_preview_enable.hxx +4 -2
  32. data/ext/couchbase/operations/collection_create.hxx +4 -2
  33. data/ext/couchbase/operations/collection_drop.hxx +4 -2
  34. data/ext/couchbase/operations/document_analytics.hxx +0 -4
  35. data/ext/couchbase/operations/document_decrement.hxx +6 -3
  36. data/ext/couchbase/operations/document_get.hxx +3 -0
  37. data/ext/couchbase/operations/document_get_and_lock.hxx +3 -0
  38. data/ext/couchbase/operations/document_get_and_touch.hxx +5 -2
  39. data/ext/couchbase/operations/document_get_projected.hxx +12 -9
  40. data/ext/couchbase/operations/document_increment.hxx +6 -3
  41. data/ext/couchbase/operations/document_insert.hxx +5 -2
  42. data/ext/couchbase/operations/document_lookup_in.hxx +3 -0
  43. data/ext/couchbase/operations/document_mutate_in.hxx +6 -3
  44. data/ext/couchbase/operations/document_remove.hxx +3 -0
  45. data/ext/couchbase/operations/document_replace.hxx +5 -2
  46. data/ext/couchbase/operations/document_search.hxx +6 -7
  47. data/ext/couchbase/operations/document_touch.hxx +5 -2
  48. data/ext/couchbase/operations/document_unlock.hxx +3 -0
  49. data/ext/couchbase/operations/document_upsert.hxx +5 -2
  50. data/ext/couchbase/operations/query_index_build_deferred.hxx +3 -3
  51. data/ext/couchbase/operations/query_index_create.hxx +3 -3
  52. data/ext/couchbase/operations/query_index_drop.hxx +3 -3
  53. data/ext/couchbase/operations/query_index_get_all.hxx +3 -3
  54. data/ext/couchbase/operations/scope_create.hxx +4 -2
  55. data/ext/couchbase/operations/scope_drop.hxx +4 -2
  56. data/ext/couchbase/operations/scope_get_all.hxx +4 -2
  57. data/ext/couchbase/operations/search_index_analyze_document.hxx +2 -2
  58. data/ext/couchbase/operations/search_index_control_ingest.hxx +2 -2
  59. data/ext/couchbase/operations/search_index_control_plan_freeze.hxx +2 -2
  60. data/ext/couchbase/operations/search_index_control_query.hxx +2 -2
  61. data/ext/couchbase/operations/search_index_drop.hxx +2 -2
  62. data/ext/couchbase/operations/search_index_get.hxx +2 -2
  63. data/ext/couchbase/operations/search_index_get_all.hxx +2 -2
  64. data/ext/couchbase/operations/search_index_get_documents_count.hxx +2 -2
  65. data/ext/couchbase/operations/search_index_upsert.hxx +2 -2
  66. data/ext/couchbase/origin.hxx +148 -0
  67. data/ext/couchbase/protocol/cmd_cluster_map_change_notification.hxx +1 -6
  68. data/ext/couchbase/protocol/cmd_decrement.hxx +5 -5
  69. data/ext/couchbase/protocol/cmd_get_and_touch.hxx +5 -5
  70. data/ext/couchbase/protocol/cmd_get_cluster_config.hxx +1 -6
  71. data/ext/couchbase/protocol/cmd_increment.hxx +5 -5
  72. data/ext/couchbase/protocol/cmd_info.hxx +0 -11
  73. data/ext/couchbase/protocol/cmd_insert.hxx +5 -5
  74. data/ext/couchbase/protocol/cmd_mutate_in.hxx +6 -6
  75. data/ext/couchbase/protocol/cmd_replace.hxx +5 -5
  76. data/ext/couchbase/protocol/cmd_touch.hxx +1 -1
  77. data/ext/couchbase/protocol/cmd_upsert.hxx +5 -5
  78. data/ext/couchbase/timeout_defaults.hxx +7 -0
  79. data/ext/couchbase/utils/connection_string.hxx +139 -0
  80. data/ext/extconf.rb +44 -11
  81. data/ext/test/main.cxx +93 -15
  82. data/ext/third_party/http_parser/Makefile +160 -0
  83. data/ext/third_party/json/Makefile +77 -0
  84. data/lib/couchbase/analytics_options.rb +18 -4
  85. data/lib/couchbase/binary_collection.rb +2 -2
  86. data/lib/couchbase/binary_collection_options.rb +2 -2
  87. data/lib/couchbase/bucket.rb +4 -4
  88. data/lib/couchbase/cluster.rb +60 -46
  89. data/lib/couchbase/collection.rb +13 -13
  90. data/lib/couchbase/collection_options.rb +15 -9
  91. data/{bin/console → lib/couchbase/datastructures.rb} +4 -7
  92. data/lib/couchbase/datastructures/couchbase_list.rb +171 -0
  93. data/lib/couchbase/datastructures/couchbase_map.rb +205 -0
  94. data/lib/couchbase/datastructures/couchbase_queue.rb +145 -0
  95. data/lib/couchbase/datastructures/couchbase_set.rb +138 -0
  96. data/lib/couchbase/errors.rb +66 -63
  97. data/lib/couchbase/libcouchbase.bundle +0 -0
  98. data/lib/couchbase/management/user_manager.rb +1 -1
  99. data/lib/couchbase/mutation_state.rb +1 -0
  100. data/lib/couchbase/query_options.rb +25 -2
  101. data/lib/couchbase/scope.rb +0 -7
  102. data/lib/couchbase/search_options.rb +7 -0
  103. data/lib/couchbase/version.rb +1 -1
  104. data/lib/couchbase/view_options.rb +4 -3
  105. metadata +20 -82
  106. data/.github/workflows/tests-6.0.3.yml +0 -52
  107. data/.github/workflows/tests-dev-preview.yml +0 -55
  108. data/.github/workflows/tests.yml +0 -50
  109. data/.gitignore +0 -20
  110. data/.gitmodules +0 -21
  111. data/.idea/.gitignore +0 -5
  112. data/.idea/dictionaries/gem_terms.xml +0 -18
  113. data/.idea/inspectionProfiles/Project_Default.xml +0 -8
  114. data/.idea/vcs.xml +0 -13
  115. data/bin/check-cluster +0 -31
  116. data/bin/fetch-stats +0 -19
  117. data/bin/init-cluster +0 -82
  118. data/bin/jenkins/build-extension +0 -35
  119. data/bin/jenkins/install-dependencies +0 -47
  120. data/bin/jenkins/test-with-cbdyncluster +0 -58
  121. data/bin/setup +0 -24
  122. data/ext/couchbase/configuration_monitor.hxx +0 -93
  123. data/ext/couchbase/operations/command.hxx +0 -163
  124. data/rbi/couchbase.rbi +0 -79
@@ -0,0 +1,53 @@
1
+ /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Copyright 2020 Couchbase, Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ #pragma once
19
+
20
+ #include <timeout_defaults.hxx>
21
+
22
+ namespace couchbase
23
+ {
24
+ struct cluster_options {
25
+ std::chrono::milliseconds bootstrap_timeout = timeout_defaults::bootstrap_timeout;
26
+ std::chrono::milliseconds connect_timeout = timeout_defaults::connect_timeout;
27
+ std::chrono::milliseconds key_value_timeout = timeout_defaults::key_value_timeout;
28
+ std::chrono::milliseconds key_value_durable_timeout = timeout_defaults::key_value_durable_timeout;
29
+ std::chrono::milliseconds view_timeout = timeout_defaults::view_timeout;
30
+ std::chrono::milliseconds query_timeout = timeout_defaults::query_timeout;
31
+ std::chrono::milliseconds analytics_timeout = timeout_defaults::analytics_timeout;
32
+ std::chrono::milliseconds search_timeout = timeout_defaults::search_timeout;
33
+ std::chrono::milliseconds management_timeout = timeout_defaults::management_timeout;
34
+ std::chrono::milliseconds dns_srv_timeout = timeout_defaults::dns_srv_timeout;
35
+
36
+ bool enable_tls{ false };
37
+ std::string trust_certificate{};
38
+ bool enable_mutation_tokens{ true };
39
+ bool enable_tcp_keep_alive{ true };
40
+ bool force_ipv4{ false };
41
+ bool enable_dns_srv{ true };
42
+ std::string network{ "auto" };
43
+
44
+ std::chrono::milliseconds tcp_keep_alive_interval = timeout_defaults::tcp_keep_alive_interval;
45
+ std::chrono::milliseconds config_poll_interval = timeout_defaults::config_poll_interval;
46
+ std::chrono::milliseconds config_poll_floor = timeout_defaults::config_poll_floor;
47
+ std::chrono::milliseconds config_idle_redial_timeout = timeout_defaults::config_idle_redial_timeout;
48
+
49
+ size_t max_http_connections{ 0 };
50
+ std::chrono::milliseconds idle_http_connection_timeout = timeout_defaults::idle_http_connection_timeout;
51
+ };
52
+
53
+ } // namespace couchbase
@@ -24,6 +24,8 @@
24
24
  #include <utils/crc32.hxx>
25
25
  #include <platform/uuid.h>
26
26
 
27
+ #include <service_type.hxx>
28
+
27
29
  namespace couchbase
28
30
  {
29
31
  struct configuration {
@@ -35,14 +37,149 @@ struct configuration {
35
37
  std::optional<std::uint16_t> views;
36
38
  std::optional<std::uint16_t> query;
37
39
  };
40
+ struct alternate_address {
41
+ std::string name;
42
+ std::string hostname;
43
+ port_map services_plain{};
44
+ port_map services_tls{};
45
+ };
38
46
  struct node {
39
47
  bool this_node{ false };
40
48
  size_t index;
41
49
  std::string hostname;
42
50
  port_map services_plain;
43
51
  port_map services_tls;
52
+ std::map<std::string, alternate_address> alt{};
53
+
54
+ [[nodiscard]] std::uint16_t port_or(service_type type, bool is_tls, std::uint16_t default_value) const
55
+ {
56
+ if (is_tls) {
57
+ switch (type) {
58
+ case service_type::query:
59
+ return services_tls.query.value_or(default_value);
60
+
61
+ case service_type::analytics:
62
+ return services_tls.analytics.value_or(default_value);
63
+
64
+ case service_type::search:
65
+ return services_tls.search.value_or(default_value);
66
+
67
+ case service_type::views:
68
+ return services_tls.views.value_or(default_value);
69
+
70
+ case service_type::management:
71
+ return services_tls.management.value_or(default_value);
72
+
73
+ case service_type::kv:
74
+ return services_tls.key_value.value_or(default_value);
75
+ }
76
+ }
77
+ switch (type) {
78
+ case service_type::query:
79
+ return services_plain.query.value_or(default_value);
80
+
81
+ case service_type::analytics:
82
+ return services_plain.analytics.value_or(default_value);
83
+
84
+ case service_type::search:
85
+ return services_plain.search.value_or(default_value);
86
+
87
+ case service_type::views:
88
+ return services_plain.views.value_or(default_value);
89
+
90
+ case service_type::management:
91
+ return services_plain.management.value_or(default_value);
92
+
93
+ case service_type::kv:
94
+ return services_plain.key_value.value_or(default_value);
95
+ }
96
+ return default_value;
97
+ }
98
+
99
+ [[nodiscard]] const std::string & hostname_for(const std::string& network) const
100
+ {
101
+ if (network == "default") {
102
+ return hostname;
103
+ }
104
+ const auto& address = alt.find(network);
105
+ if (address == alt.end()) {
106
+ spdlog::warn(R"(requested network "{}" is not found, fallback to "default" host)", network);
107
+ return hostname;
108
+ }
109
+ return address->second.hostname;
110
+ }
111
+
112
+ [[nodiscard]] std::uint16_t port_or(const std::string& network, service_type type, bool is_tls, std::uint16_t default_value) const
113
+ {
114
+ if (network == "default") {
115
+ return port_or(type, is_tls, default_value);
116
+ }
117
+ const auto& address = alt.find(network);
118
+ if (address == alt.end()) {
119
+ spdlog::warn(R"(requested network "{}" is not found, fallback to "default" port of {} service)", network, type);
120
+ return port_or(type, is_tls, default_value);
121
+ }
122
+ if (is_tls) {
123
+ switch (type) {
124
+ case service_type::query:
125
+ return address->second.services_tls.query.value_or(default_value);
126
+
127
+ case service_type::analytics:
128
+ return address->second.services_tls.analytics.value_or(default_value);
129
+
130
+ case service_type::search:
131
+ return address->second.services_tls.search.value_or(default_value);
132
+
133
+ case service_type::views:
134
+ return address->second.services_tls.views.value_or(default_value);
135
+
136
+ case service_type::management:
137
+ return address->second.services_tls.management.value_or(default_value);
138
+
139
+ case service_type::kv:
140
+ return address->second.services_tls.key_value.value_or(default_value);
141
+ }
142
+ }
143
+ switch (type) {
144
+ case service_type::query:
145
+ return address->second.services_plain.query.value_or(default_value);
146
+
147
+ case service_type::analytics:
148
+ return address->second.services_plain.analytics.value_or(default_value);
149
+
150
+ case service_type::search:
151
+ return address->second.services_plain.search.value_or(default_value);
152
+
153
+ case service_type::views:
154
+ return address->second.services_plain.views.value_or(default_value);
155
+
156
+ case service_type::management:
157
+ return address->second.services_plain.management.value_or(default_value);
158
+
159
+ case service_type::kv:
160
+ return address->second.services_plain.key_value.value_or(default_value);
161
+ }
162
+ return default_value;
163
+ }
44
164
  };
45
165
 
166
+ [[nodiscard]] std::string select_network(const std::string& bootstrap_hostname) const
167
+ {
168
+ for (const auto& n : nodes) {
169
+ if (n.this_node) {
170
+ if (n.hostname == bootstrap_hostname) {
171
+ return "default";
172
+ }
173
+ for (const auto& entry : n.alt) {
174
+ if (entry.second.hostname == bootstrap_hostname) {
175
+ return entry.first;
176
+ }
177
+ }
178
+ }
179
+ }
180
+ return "default";
181
+ }
182
+
46
183
  using vbucket_map = typename std::vector<std::vector<std::int16_t>>;
47
184
 
48
185
  std::uint64_t rev{};
@@ -143,12 +280,69 @@ struct fmt::formatter<couchbase::configuration::node> : formatter<std::string> {
143
280
  if (node.services_tls.views) {
144
281
  tls.push_back(fmt::format("capi={}", *node.services_tls.views));
145
282
  }
283
+ std::vector<std::string> alternate_addresses{};
284
+ if (!node.alt.empty()) {
285
+ alternate_addresses.reserve(node.alt.size());
286
+ for (const auto& entry : node.alt) {
287
+ std::string network = fmt::format(R"(name="{}", host="{}")", entry.second.name, entry.second.hostname);
288
+ {
289
+ std::vector<std::string> ports;
290
+ if (entry.second.services_plain.key_value) {
291
+ ports.push_back(fmt::format("kv={}", *entry.second.services_plain.key_value));
292
+ }
293
+ if (entry.second.services_plain.management) {
294
+ ports.push_back(fmt::format("mgmt={}", *entry.second.services_plain.management));
295
+ }
296
+ if (entry.second.services_plain.analytics) {
297
+ ports.push_back(fmt::format("cbas={}", *entry.second.services_plain.analytics));
298
+ }
299
+ if (entry.second.services_plain.search) {
300
+ ports.push_back(fmt::format("fts={}", *entry.second.services_plain.search));
301
+ }
302
+ if (entry.second.services_plain.query) {
303
+ ports.push_back(fmt::format("n1ql={}", *entry.second.services_plain.query));
304
+ }
305
+ if (entry.second.services_plain.views) {
306
+ ports.push_back(fmt::format("capi={}", *entry.second.services_plain.views));
307
+ }
308
+ if (!ports.empty()) {
309
+ network += fmt::format(", plain=({})", fmt::join(ports, ","));
310
+ }
311
+ }
312
+ {
313
+ std::vector<std::string> ports;
314
+ if (entry.second.services_tls.key_value) {
315
+ ports.push_back(fmt::format("kv={}", *entry.second.services_tls.key_value));
316
+ }
317
+ if (entry.second.services_tls.management) {
318
+ ports.push_back(fmt::format("mgmt={}", *entry.second.services_tls.management));
319
+ }
320
+ if (entry.second.services_tls.analytics) {
321
+ ports.push_back(fmt::format("cbas={}", *entry.second.services_tls.analytics));
322
+ }
323
+ if (entry.second.services_tls.search) {
324
+ ports.push_back(fmt::format("fts={}", *entry.second.services_tls.search));
325
+ }
326
+ if (entry.second.services_tls.query) {
327
+ ports.push_back(fmt::format("n1ql={}", *entry.second.services_tls.query));
328
+ }
329
+ if (entry.second.services_tls.views) {
330
+ ports.push_back(fmt::format("capi={}", *entry.second.services_tls.views));
331
+ }
332
+ if (!ports.empty()) {
333
+ network += fmt::format(", tls=({})", fmt::join(ports, ","));
334
+ }
335
+ }
336
+ alternate_addresses.emplace_back(network);
337
+ }
338
+ }
146
339
  format_to(ctx.out(),
147
- R"(#<node:{} hostname={}, plain=({}), tls=({})>)",
340
+ R"(#<node:{} hostname="{}", plain=({}), tls=({}), alt=[{}]>)",
148
341
  node.index,
149
342
  node.hostname,
150
343
  fmt::join(plain, ", "),
151
- fmt::join(tls, ", "));
344
+ fmt::join(tls, ", "),
345
+ fmt::join(alternate_addresses, ", "));
152
346
  return formatter<std::string>::format("", ctx);
153
347
  }
154
348
  };
@@ -208,6 +402,30 @@ struct traits<couchbase::configuration> {
208
402
  n.services_tls.analytics = s.template optional<std::uint16_t>("cbasSSL");
209
403
  n.services_tls.query = s.template optional<std::uint16_t>("n1qlSSL");
210
404
  n.services_tls.views = s.template optional<std::uint16_t>("capiSSL");
405
+ {
406
+ const auto& alt = o.find("alternateAddresses");
407
+ if (alt != o.end()) {
408
+ for (const auto& entry : alt->second.get_object()) {
409
+ couchbase::configuration::alternate_address addr;
410
+ addr.name = entry.first;
411
+ addr.hostname = entry.second.at("hostname").get_string();
412
+ const auto& ports = entry.second.find("ports");
413
+ addr.services_plain.key_value = ports->template optional<std::uint16_t>("kv");
414
+ addr.services_plain.management = ports->template optional<std::uint16_t>("mgmt");
415
+ addr.services_plain.search = ports->template optional<std::uint16_t>("fts");
416
+ addr.services_plain.analytics = ports->template optional<std::uint16_t>("cbas");
417
+ addr.services_plain.query = ports->template optional<std::uint16_t>("n1ql");
418
+ addr.services_plain.views = ports->template optional<std::uint16_t>("capi");
419
+ addr.services_tls.key_value = ports->template optional<std::uint16_t>("kvSSL");
420
+ addr.services_tls.management = ports->template optional<std::uint16_t>("mgmtSSL");
421
+ addr.services_tls.search = ports->template optional<std::uint16_t>("ftsSSL");
422
+ addr.services_tls.analytics = ports->template optional<std::uint16_t>("cbasSSL");
423
+ addr.services_tls.query = ports->template optional<std::uint16_t>("n1qlSSL");
424
+ addr.services_tls.views = ports->template optional<std::uint16_t>("capiSSL");
425
+ n.alt.emplace(entry.first, addr);
426
+ }
427
+ }
428
+ }
211
429
  result.nodes.emplace_back(n);
212
430
  }
213
431
  {
@@ -15,6 +15,8 @@
15
15
  * limitations under the License.
16
16
  */
17
17
 
18
+ #include <build_config.hxx>
19
+
18
20
  #include <openssl/crypto.h>
19
21
  #include <asio/version.hpp>
20
22
 
@@ -106,10 +108,10 @@ cb__backend_close(cb_backend_data* backend)
106
108
  auto f = barrier->get_future();
107
109
  backend->cluster->close([barrier]() { barrier->set_value(); });
108
110
  f.wait();
109
- backend->cluster.reset(nullptr);
110
111
  if (backend->worker.joinable()) {
111
112
  backend->worker.join();
112
113
  }
114
+ backend->cluster.reset(nullptr);
113
115
  backend->ctx.reset(nullptr);
114
116
  }
115
117
  }
@@ -162,7 +164,7 @@ cb_Backend_allocate(VALUE klass)
162
164
  return obj;
163
165
  }
164
166
 
165
- static VALUE eBackendError;
167
+ static VALUE eCouchbaseError;
166
168
  static VALUE eAmbiguousTimeout;
167
169
  static VALUE eAuthenticationFailure;
168
170
  static VALUE eBucketExists;
@@ -231,70 +233,71 @@ static void
231
233
  init_exceptions(VALUE mCouchbase)
232
234
  {
233
235
  VALUE mError = rb_define_module_under(mCouchbase, "Error");
234
- eBackendError = rb_define_class_under(mError, "BackendError", rb_eStandardError);
235
- eAmbiguousTimeout = rb_define_class_under(mError, "AmbiguousTimeout", rb_eStandardError);
236
- eAuthenticationFailure = rb_define_class_under(mError, "AuthenticationFailure", rb_eStandardError);
237
- eBucketExists = rb_define_class_under(mError, "BucketExists", rb_eStandardError);
238
- eBucketNotFlushable = rb_define_class_under(mError, "BucketNotFlushable", rb_eStandardError);
239
- eBucketNotFound = rb_define_class_under(mError, "BucketNotFound", rb_eStandardError);
240
- eCasMismatch = rb_define_class_under(mError, "CasMismatch", rb_eStandardError);
241
- eCollectionExists = rb_define_class_under(mError, "CollectionExists", rb_eStandardError);
242
- eCollectionNotFound = rb_define_class_under(mError, "CollectionNotFound", rb_eStandardError);
243
- eCompilationFailure = rb_define_class_under(mError, "CompilationFailure", rb_eStandardError);
244
- eDatasetExists = rb_define_class_under(mError, "DatasetExists", rb_eStandardError);
245
- eDatasetNotFound = rb_define_class_under(mError, "DatasetNotFound", rb_eStandardError);
246
- eDataverseExists = rb_define_class_under(mError, "DataverseExists", rb_eStandardError);
247
- eDataverseNotFound = rb_define_class_under(mError, "DataverseNotFound", rb_eStandardError);
248
- eDecodingFailure = rb_define_class_under(mError, "DecodingFailure", rb_eStandardError);
249
- eDeltaInvalid = rb_define_class_under(mError, "DeltaInvalid", rb_eStandardError);
250
- eDesignDocumentNotFound = rb_define_class_under(mError, "DesignDocumentNotFound", rb_eStandardError);
251
- eDocumentExists = rb_define_class_under(mError, "DocumentExists", rb_eStandardError);
252
- eDocumentIrretrievable = rb_define_class_under(mError, "DocumentIrretrievable", rb_eStandardError);
253
- eDocumentLocked = rb_define_class_under(mError, "DocumentLocked", rb_eStandardError);
254
- eDocumentNotFound = rb_define_class_under(mError, "DocumentNotFound", rb_eStandardError);
255
- eDocumentNotJson = rb_define_class_under(mError, "DocumentNotJson", rb_eStandardError);
256
- eDurabilityAmbiguous = rb_define_class_under(mError, "DurabilityAmbiguous", rb_eStandardError);
257
- eDurabilityImpossible = rb_define_class_under(mError, "DurabilityImpossible", rb_eStandardError);
258
- eDurabilityLevelNotAvailable = rb_define_class_under(mError, "DurabilityLevelNotAvailable", rb_eStandardError);
259
- eDurableWriteInProgress = rb_define_class_under(mError, "DurableWriteInProgress", rb_eStandardError);
260
- eDurableWriteReCommitInProgress = rb_define_class_under(mError, "DurableWriteReCommitInProgress", rb_eStandardError);
261
- eEncodingFailure = rb_define_class_under(mError, "EncodingFailure", rb_eStandardError);
262
- eFeatureNotAvailable = rb_define_class_under(mError, "FeatureNotAvailable", rb_eStandardError);
263
- eGroupNotFound = rb_define_class_under(mError, "GroupNotFound", rb_eStandardError);
264
- eIndexExists = rb_define_class_under(mError, "IndexExists", rb_eStandardError);
265
- eIndexFailure = rb_define_class_under(mError, "IndexFailure", rb_eStandardError);
266
- eIndexNotFound = rb_define_class_under(mError, "IndexNotFound", rb_eStandardError);
267
- eInternalServerFailure = rb_define_class_under(mError, "InternalServerFailure", rb_eStandardError);
236
+ eCouchbaseError = rb_define_class_under(mError, "CouchbaseError", rb_eStandardError);
237
+
238
+ eAmbiguousTimeout = rb_define_class_under(mError, "AmbiguousTimeout", eCouchbaseError);
239
+ eAuthenticationFailure = rb_define_class_under(mError, "AuthenticationFailure", eCouchbaseError);
240
+ eBucketExists = rb_define_class_under(mError, "BucketExists", eCouchbaseError);
241
+ eBucketNotFlushable = rb_define_class_under(mError, "BucketNotFlushable", eCouchbaseError);
242
+ eBucketNotFound = rb_define_class_under(mError, "BucketNotFound", eCouchbaseError);
243
+ eCasMismatch = rb_define_class_under(mError, "CasMismatch", eCouchbaseError);
244
+ eCollectionExists = rb_define_class_under(mError, "CollectionExists", eCouchbaseError);
245
+ eCollectionNotFound = rb_define_class_under(mError, "CollectionNotFound", eCouchbaseError);
246
+ eCompilationFailure = rb_define_class_under(mError, "CompilationFailure", eCouchbaseError);
247
+ eDatasetExists = rb_define_class_under(mError, "DatasetExists", eCouchbaseError);
248
+ eDatasetNotFound = rb_define_class_under(mError, "DatasetNotFound", eCouchbaseError);
249
+ eDataverseExists = rb_define_class_under(mError, "DataverseExists", eCouchbaseError);
250
+ eDataverseNotFound = rb_define_class_under(mError, "DataverseNotFound", eCouchbaseError);
251
+ eDecodingFailure = rb_define_class_under(mError, "DecodingFailure", eCouchbaseError);
252
+ eDeltaInvalid = rb_define_class_under(mError, "DeltaInvalid", eCouchbaseError);
253
+ eDesignDocumentNotFound = rb_define_class_under(mError, "DesignDocumentNotFound", eCouchbaseError);
254
+ eDocumentExists = rb_define_class_under(mError, "DocumentExists", eCouchbaseError);
255
+ eDocumentIrretrievable = rb_define_class_under(mError, "DocumentIrretrievable", eCouchbaseError);
256
+ eDocumentLocked = rb_define_class_under(mError, "DocumentLocked", eCouchbaseError);
257
+ eDocumentNotFound = rb_define_class_under(mError, "DocumentNotFound", eCouchbaseError);
258
+ eDocumentNotJson = rb_define_class_under(mError, "DocumentNotJson", eCouchbaseError);
259
+ eDurabilityAmbiguous = rb_define_class_under(mError, "DurabilityAmbiguous", eCouchbaseError);
260
+ eDurabilityImpossible = rb_define_class_under(mError, "DurabilityImpossible", eCouchbaseError);
261
+ eDurabilityLevelNotAvailable = rb_define_class_under(mError, "DurabilityLevelNotAvailable", eCouchbaseError);
262
+ eDurableWriteInProgress = rb_define_class_under(mError, "DurableWriteInProgress", eCouchbaseError);
263
+ eDurableWriteReCommitInProgress = rb_define_class_under(mError, "DurableWriteReCommitInProgress", eCouchbaseError);
264
+ eEncodingFailure = rb_define_class_under(mError, "EncodingFailure", eCouchbaseError);
265
+ eFeatureNotAvailable = rb_define_class_under(mError, "FeatureNotAvailable", eCouchbaseError);
266
+ eGroupNotFound = rb_define_class_under(mError, "GroupNotFound", eCouchbaseError);
267
+ eIndexExists = rb_define_class_under(mError, "IndexExists", eCouchbaseError);
268
+ eIndexFailure = rb_define_class_under(mError, "IndexFailure", eCouchbaseError);
269
+ eIndexNotFound = rb_define_class_under(mError, "IndexNotFound", eCouchbaseError);
270
+ eInternalServerFailure = rb_define_class_under(mError, "InternalServerFailure", eCouchbaseError);
268
271
  eInvalidArgument = rb_define_class_under(mError, "InvalidArgument", rb_eArgError);
269
- eJobQueueFull = rb_define_class_under(mError, "JobQueueFull", rb_eStandardError);
270
- eLinkNotFound = rb_define_class_under(mError, "LinkNotFound", rb_eStandardError);
271
- eNumberTooBig = rb_define_class_under(mError, "NumberTooBig", rb_eStandardError);
272
- eParsingFailure = rb_define_class_under(mError, "ParsingFailure", rb_eStandardError);
273
- ePathExists = rb_define_class_under(mError, "PathExists", rb_eStandardError);
274
- ePathInvalid = rb_define_class_under(mError, "PathInvalid", rb_eStandardError);
275
- ePathMismatch = rb_define_class_under(mError, "PathMismatch", rb_eStandardError);
276
- ePathNotFound = rb_define_class_under(mError, "PathNotFound", rb_eStandardError);
277
- ePathTooBig = rb_define_class_under(mError, "PathTooBig", rb_eStandardError);
278
- ePathTooDeep = rb_define_class_under(mError, "PathTooDeep", rb_eStandardError);
279
- ePlanningFailure = rb_define_class_under(mError, "PlanningFailure", rb_eStandardError);
280
- ePreparedStatementFailure = rb_define_class_under(mError, "PreparedStatementFailure", rb_eStandardError);
281
- eRequestCanceled = rb_define_class_under(mError, "RequestCanceled", rb_eStandardError);
282
- eScopeExists = rb_define_class_under(mError, "ScopeExists", rb_eStandardError);
283
- eScopeNotFound = rb_define_class_under(mError, "ScopeNotFound", rb_eStandardError);
284
- eServiceNotAvailable = rb_define_class_under(mError, "ServiceNotAvailable", rb_eStandardError);
285
- eTemporaryFailure = rb_define_class_under(mError, "TemporaryFailure", rb_eStandardError);
286
- eUnambiguousTimeout = rb_define_class_under(mError, "UnambiguousTimeout", rb_eStandardError);
287
- eUnsupportedOperation = rb_define_class_under(mError, "UnsupportedOperation", rb_eStandardError);
288
- eUserNotFound = rb_define_class_under(mError, "UserNotFound", rb_eStandardError);
289
- eUserExists = rb_define_class_under(mError, "UserExists", rb_eStandardError);
290
- eValueInvalid = rb_define_class_under(mError, "ValueInvalid", rb_eStandardError);
291
- eValueTooDeep = rb_define_class_under(mError, "ValueTooDeep", rb_eStandardError);
292
- eValueTooLarge = rb_define_class_under(mError, "ValueTooLarge", rb_eStandardError);
293
- eViewNotFound = rb_define_class_under(mError, "ViewNotFound", rb_eStandardError);
294
- eXattrCannotModifyVirtualAttribute = rb_define_class_under(mError, "XattrCannotModifyVirtualAttribute", rb_eStandardError);
295
- eXattrInvalidKeyCombo = rb_define_class_under(mError, "XattrInvalidKeyCombo", rb_eStandardError);
296
- eXattrUnknownMacro = rb_define_class_under(mError, "XattrUnknownMacro", rb_eStandardError);
297
- eXattrUnknownVirtualAttribute = rb_define_class_under(mError, "XattrUnknownVirtualAttribute", rb_eStandardError);
272
+ eJobQueueFull = rb_define_class_under(mError, "JobQueueFull", eCouchbaseError);
273
+ eLinkNotFound = rb_define_class_under(mError, "LinkNotFound", eCouchbaseError);
274
+ eNumberTooBig = rb_define_class_under(mError, "NumberTooBig", eCouchbaseError);
275
+ eParsingFailure = rb_define_class_under(mError, "ParsingFailure", eCouchbaseError);
276
+ ePathExists = rb_define_class_under(mError, "PathExists", eCouchbaseError);
277
+ ePathInvalid = rb_define_class_under(mError, "PathInvalid", eCouchbaseError);
278
+ ePathMismatch = rb_define_class_under(mError, "PathMismatch", eCouchbaseError);
279
+ ePathNotFound = rb_define_class_under(mError, "PathNotFound", eCouchbaseError);
280
+ ePathTooBig = rb_define_class_under(mError, "PathTooBig", eCouchbaseError);
281
+ ePathTooDeep = rb_define_class_under(mError, "PathTooDeep", eCouchbaseError);
282
+ ePlanningFailure = rb_define_class_under(mError, "PlanningFailure", eCouchbaseError);
283
+ ePreparedStatementFailure = rb_define_class_under(mError, "PreparedStatementFailure", eCouchbaseError);
284
+ eRequestCanceled = rb_define_class_under(mError, "RequestCanceled", eCouchbaseError);
285
+ eScopeExists = rb_define_class_under(mError, "ScopeExists", eCouchbaseError);
286
+ eScopeNotFound = rb_define_class_under(mError, "ScopeNotFound", eCouchbaseError);
287
+ eServiceNotAvailable = rb_define_class_under(mError, "ServiceNotAvailable", eCouchbaseError);
288
+ eTemporaryFailure = rb_define_class_under(mError, "TemporaryFailure", eCouchbaseError);
289
+ eUnambiguousTimeout = rb_define_class_under(mError, "UnambiguousTimeout", eCouchbaseError);
290
+ eUnsupportedOperation = rb_define_class_under(mError, "UnsupportedOperation", eCouchbaseError);
291
+ eUserNotFound = rb_define_class_under(mError, "UserNotFound", eCouchbaseError);
292
+ eUserExists = rb_define_class_under(mError, "UserExists", eCouchbaseError);
293
+ eValueInvalid = rb_define_class_under(mError, "ValueInvalid", eCouchbaseError);
294
+ eValueTooDeep = rb_define_class_under(mError, "ValueTooDeep", eCouchbaseError);
295
+ eValueTooLarge = rb_define_class_under(mError, "ValueTooLarge", eCouchbaseError);
296
+ eViewNotFound = rb_define_class_under(mError, "ViewNotFound", eCouchbaseError);
297
+ eXattrCannotModifyVirtualAttribute = rb_define_class_under(mError, "XattrCannotModifyVirtualAttribute", eCouchbaseError);
298
+ eXattrInvalidKeyCombo = rb_define_class_under(mError, "XattrInvalidKeyCombo", eCouchbaseError);
299
+ eXattrUnknownMacro = rb_define_class_under(mError, "XattrUnknownMacro", eCouchbaseError);
300
+ eXattrUnknownVirtualAttribute = rb_define_class_under(mError, "XattrUnknownVirtualAttribute", eCouchbaseError);
298
301
  }
299
302
 
300
303
  static VALUE
@@ -503,11 +506,11 @@ cb__map_error_code(std::error_code ec, const std::string& message)
503
506
  }
504
507
  }
505
508
 
506
- return rb_exc_new_cstr(eBackendError, fmt::format("{}: {}", message, ec.message()).c_str());
509
+ return rb_exc_new_cstr(eCouchbaseError, fmt::format("{}: {}", message, ec.message()).c_str());
507
510
  }
508
511
 
509
512
  static VALUE
510
- cb_Backend_open(VALUE self, VALUE hostname, VALUE username, VALUE password)
513
+ cb_Backend_open(VALUE self, VALUE connection_string, VALUE username, VALUE password, VALUE options)
511
514
  {
512
515
  cb_backend_data* backend = nullptr;
513
516
  TypedData_Get_Struct(self, cb_backend_data, &cb_backend_type, backend);
@@ -515,22 +518,25 @@ cb_Backend_open(VALUE self, VALUE hostname, VALUE username, VALUE password)
515
518
  if (!backend->cluster) {
516
519
  rb_raise(rb_eArgError, "Cluster has been closed already");
517
520
  }
518
- VALUE exc = Qnil;
521
+ Check_Type(connection_string, T_STRING);
522
+ Check_Type(username, T_STRING);
523
+ Check_Type(password, T_STRING);
524
+ if (!NIL_P(options)) {
525
+ Check_Type(options, T_HASH);
526
+ }
519
527
 
528
+ VALUE exc = Qnil;
520
529
  {
521
- Check_Type(hostname, T_STRING);
522
- Check_Type(username, T_STRING);
523
- Check_Type(password, T_STRING);
524
-
525
- couchbase::origin options;
526
- options.hostname.assign(RSTRING_PTR(hostname), static_cast<size_t>(RSTRING_LEN(hostname)));
527
- options.username.assign(RSTRING_PTR(username), static_cast<size_t>(RSTRING_LEN(username)));
528
- options.password.assign(RSTRING_PTR(password), static_cast<size_t>(RSTRING_LEN(password)));
530
+ std::string input(RSTRING_PTR(connection_string), static_cast<size_t>(RSTRING_LEN(connection_string)));
531
+ auto connstr = couchbase::utils::parse_connection_string(input);
532
+ std::string user(RSTRING_PTR(username), static_cast<size_t>(RSTRING_LEN(username)));
533
+ std::string pass(RSTRING_PTR(password), static_cast<size_t>(RSTRING_LEN(password)));
534
+ couchbase::origin origin(user, pass, std::move(connstr));
529
535
  auto barrier = std::make_shared<std::promise<std::error_code>>();
530
536
  auto f = barrier->get_future();
531
- backend->cluster->open(options, [barrier](std::error_code ec) mutable { barrier->set_value(ec); });
537
+ backend->cluster->open(origin, [barrier](std::error_code ec) mutable { barrier->set_value(ec); });
532
538
  if (auto ec = f.get()) {
533
- exc = cb__map_error_code(ec, fmt::format("unable open cluster at {}", options.hostname));
539
+ exc = cb__map_error_code(ec, fmt::format("unable open cluster at {}", origin.next_address().first));
534
540
  }
535
541
  }
536
542
  if (!NIL_P(exc)) {
@@ -550,7 +556,7 @@ cb_Backend_close(VALUE self)
550
556
  }
551
557
 
552
558
  static VALUE
553
- cb_Backend_open_bucket(VALUE self, VALUE bucket)
559
+ cb_Backend_open_bucket(VALUE self, VALUE bucket, VALUE wait_until_ready)
554
560
  {
555
561
  cb_backend_data* backend = nullptr;
556
562
  TypedData_Get_Struct(self, cb_backend_data, &cb_backend_type, backend);
@@ -560,23 +566,28 @@ cb_Backend_open_bucket(VALUE self, VALUE bucket)
560
566
  }
561
567
 
562
568
  Check_Type(bucket, T_STRING);
569
+ bool wait = RTEST(wait_until_ready);
563
570
 
564
571
  VALUE exc = Qnil;
565
572
  {
566
573
  std::string name(RSTRING_PTR(bucket), static_cast<size_t>(RSTRING_LEN(bucket)));
567
574
 
568
- auto barrier = std::make_shared<std::promise<std::error_code>>();
569
- auto f = barrier->get_future();
570
- backend->cluster->open_bucket(name, [barrier](std::error_code ec) mutable { barrier->set_value(ec); });
571
- if (auto ec = f.get()) {
572
- exc = cb__map_error_code(ec, fmt::format("unable open bucket \"{}\"", name));
575
+ if (wait) {
576
+ auto barrier = std::make_shared<std::promise<std::error_code>>();
577
+ auto f = barrier->get_future();
578
+ backend->cluster->open_bucket(name, [barrier](std::error_code ec) mutable { barrier->set_value(ec); });
579
+ if (auto ec = f.get()) {
580
+ exc = cb__map_error_code(ec, fmt::format("unable open bucket \"{}\"", name));
581
+ }
582
+ } else {
583
+ backend->cluster->open_bucket(name, [](std::error_code) {});
573
584
  }
574
585
  }
575
586
  if (!NIL_P(exc)) {
576
587
  rb_exc_raise(exc);
577
588
  }
578
589
 
579
- return Qtrue;
590
+ return Qnil;
580
591
  }
581
592
 
582
593
  template<typename Request>
@@ -643,7 +654,7 @@ cb_Backend_document_get_projected(VALUE self,
643
654
  VALUE collection,
644
655
  VALUE id,
645
656
  VALUE timeout,
646
- VALUE with_expiration,
657
+ VALUE with_expiry,
647
658
  VALUE projections,
648
659
  VALUE preserve_array_indexes)
649
660
  {
@@ -667,7 +678,7 @@ cb_Backend_document_get_projected(VALUE self,
667
678
 
668
679
  couchbase::operations::get_projected_request req{ doc_id };
669
680
  cb__extract_timeout(req, timeout);
670
- req.with_expiration = RTEST(with_expiration);
681
+ req.with_expiry = RTEST(with_expiry);
671
682
  req.preserve_array_indexes = RTEST(preserve_array_indexes);
672
683
  if (!NIL_P(projections)) {
673
684
  Check_Type(projections, T_ARRAY);
@@ -693,8 +704,8 @@ cb_Backend_document_get_projected(VALUE self,
693
704
  rb_hash_aset(res, rb_id2sym(rb_intern("content")), rb_str_new(resp.value.data(), static_cast<long>(resp.value.size())));
694
705
  rb_hash_aset(res, rb_id2sym(rb_intern("cas")), ULL2NUM(resp.cas));
695
706
  rb_hash_aset(res, rb_id2sym(rb_intern("flags")), UINT2NUM(resp.flags));
696
- if (resp.expiration) {
697
- rb_hash_aset(res, rb_id2sym(rb_intern("expiration")), UINT2NUM(resp.expiration.value()));
707
+ if (resp.expiry) {
708
+ rb_hash_aset(res, rb_id2sym(rb_intern("expiry")), UINT2NUM(resp.expiry.value()));
698
709
  }
699
710
  return res;
700
711
  } while (false);
@@ -748,7 +759,7 @@ cb_Backend_document_get_and_lock(VALUE self, VALUE bucket, VALUE collection, VAL
748
759
  }
749
760
 
750
761
  static VALUE
751
- cb_Backend_document_get_and_touch(VALUE self, VALUE bucket, VALUE collection, VALUE id, VALUE timeout, VALUE expiration)
762
+ cb_Backend_document_get_and_touch(VALUE self, VALUE bucket, VALUE collection, VALUE id, VALUE timeout, VALUE expiry)
752
763
  {
753
764
  cb_backend_data* backend = nullptr;
754
765
  TypedData_Get_Struct(self, cb_backend_data, &cb_backend_type, backend);
@@ -760,7 +771,7 @@ cb_Backend_document_get_and_touch(VALUE self, VALUE bucket, VALUE collection, VA
760
771
  Check_Type(bucket, T_STRING);
761
772
  Check_Type(collection, T_STRING);
762
773
  Check_Type(id, T_STRING);
763
- Check_Type(expiration, T_FIXNUM);
774
+ Check_Type(expiry, T_FIXNUM);
764
775
 
765
776
  VALUE exc = Qnil;
766
777
  do {
@@ -771,7 +782,7 @@ cb_Backend_document_get_and_touch(VALUE self, VALUE bucket, VALUE collection, VA
771
782
 
772
783
  couchbase::operations::get_and_touch_request req{ doc_id };
773
784
  cb__extract_timeout(req, timeout);
774
- req.expiration = NUM2UINT(expiration);
785
+ req.expiry = NUM2UINT(expiry);
775
786
 
776
787
  auto barrier = std::make_shared<std::promise<couchbase::operations::get_and_touch_response>>();
777
788
  auto f = barrier->get_future();
@@ -810,7 +821,7 @@ cb__extract_mutation_result(Response resp)
810
821
  }
811
822
 
812
823
  static VALUE
813
- cb_Backend_document_touch(VALUE self, VALUE bucket, VALUE collection, VALUE id, VALUE timeout, VALUE expiration)
824
+ cb_Backend_document_touch(VALUE self, VALUE bucket, VALUE collection, VALUE id, VALUE timeout, VALUE expiry)
814
825
  {
815
826
  cb_backend_data* backend = nullptr;
816
827
  TypedData_Get_Struct(self, cb_backend_data, &cb_backend_type, backend);
@@ -822,7 +833,7 @@ cb_Backend_document_touch(VALUE self, VALUE bucket, VALUE collection, VALUE id,
822
833
  Check_Type(bucket, T_STRING);
823
834
  Check_Type(collection, T_STRING);
824
835
  Check_Type(id, T_STRING);
825
- Check_Type(expiration, T_FIXNUM);
836
+ Check_Type(expiry, T_FIXNUM);
826
837
 
827
838
  VALUE exc = Qnil;
828
839
  do {
@@ -833,7 +844,7 @@ cb_Backend_document_touch(VALUE self, VALUE bucket, VALUE collection, VALUE id,
833
844
 
834
845
  couchbase::operations::touch_request req{ doc_id };
835
846
  cb__extract_timeout(req, timeout);
836
- req.expiration = NUM2UINT(expiration);
847
+ req.expiry = NUM2UINT(expiry);
837
848
 
838
849
  auto barrier = std::make_shared<std::promise<couchbase::operations::touch_response>>();
839
850
  auto f = barrier->get_future();
@@ -1011,10 +1022,10 @@ cb_Backend_document_upsert(VALUE self, VALUE bucket, VALUE collection, VALUE id,
1011
1022
  req.durability_timeout = FIX2UINT(durability_timeout);
1012
1023
  }
1013
1024
  }
1014
- VALUE expiration = rb_hash_aref(options, rb_id2sym(rb_intern("expiration")));
1015
- if (!NIL_P(expiration)) {
1016
- Check_Type(expiration, T_FIXNUM);
1017
- req.expiration = FIX2UINT(expiration);
1025
+ VALUE expiry = rb_hash_aref(options, rb_id2sym(rb_intern("expiry")));
1026
+ if (!NIL_P(expiry)) {
1027
+ Check_Type(expiry, T_FIXNUM);
1028
+ req.expiry = FIX2UINT(expiry);
1018
1029
  }
1019
1030
  }
1020
1031
 
@@ -1084,10 +1095,10 @@ cb_Backend_document_replace(VALUE self, VALUE bucket, VALUE collection, VALUE id
1084
1095
  req.durability_timeout = FIX2UINT(durability_timeout);
1085
1096
  }
1086
1097
  }
1087
- VALUE expiration = rb_hash_aref(options, rb_id2sym(rb_intern("expiration")));
1088
- if (!NIL_P(expiration)) {
1089
- Check_Type(expiration, T_FIXNUM);
1090
- req.expiration = FIX2UINT(expiration);
1098
+ VALUE expiry = rb_hash_aref(options, rb_id2sym(rb_intern("expiry")));
1099
+ if (!NIL_P(expiry)) {
1100
+ Check_Type(expiry, T_FIXNUM);
1101
+ req.expiry = FIX2UINT(expiry);
1091
1102
  }
1092
1103
  VALUE cas = rb_hash_aref(options, rb_id2sym(rb_intern("cas")));
1093
1104
  if (!NIL_P(cas)) {
@@ -1168,10 +1179,10 @@ cb_Backend_document_insert(VALUE self, VALUE bucket, VALUE collection, VALUE id,
1168
1179
  req.durability_timeout = FIX2UINT(durability_timeout);
1169
1180
  }
1170
1181
  }
1171
- VALUE expiration = rb_hash_aref(options, rb_id2sym(rb_intern("expiration")));
1172
- if (!NIL_P(expiration)) {
1173
- Check_Type(expiration, T_FIXNUM);
1174
- req.expiration = FIX2UINT(expiration);
1182
+ VALUE expiry = rb_hash_aref(options, rb_id2sym(rb_intern("expiry")));
1183
+ if (!NIL_P(expiry)) {
1184
+ Check_Type(expiry, T_FIXNUM);
1185
+ req.expiry = FIX2UINT(expiry);
1175
1186
  }
1176
1187
  }
1177
1188
 
@@ -1320,10 +1331,10 @@ cb_Backend_document_increment(VALUE self, VALUE bucket, VALUE collection, VALUE
1320
1331
  rb_raise(rb_eArgError, "initial_value must be an Integer");
1321
1332
  }
1322
1333
  }
1323
- VALUE expiration = rb_hash_aref(options, rb_id2sym(rb_intern("expiration")));
1324
- if (!NIL_P(expiration)) {
1325
- Check_Type(expiration, T_FIXNUM);
1326
- req.expiration = FIX2UINT(expiration);
1334
+ VALUE expiry = rb_hash_aref(options, rb_id2sym(rb_intern("expiry")));
1335
+ if (!NIL_P(expiry)) {
1336
+ Check_Type(expiry, T_FIXNUM);
1337
+ req.expiry = FIX2UINT(expiry);
1327
1338
  }
1328
1339
  }
1329
1340
 
@@ -1412,10 +1423,10 @@ cb_Backend_document_decrement(VALUE self, VALUE bucket, VALUE collection, VALUE
1412
1423
  rb_raise(rb_eArgError, "initial_value must be an Integer");
1413
1424
  }
1414
1425
  }
1415
- VALUE expiration = rb_hash_aref(options, rb_id2sym(rb_intern("expiration")));
1416
- if (!NIL_P(expiration)) {
1417
- Check_Type(expiration, T_FIXNUM);
1418
- req.expiration = FIX2UINT(expiration);
1426
+ VALUE expiry = rb_hash_aref(options, rb_id2sym(rb_intern("expiry")));
1427
+ if (!NIL_P(expiry)) {
1428
+ Check_Type(expiry, T_FIXNUM);
1429
+ req.expiry = FIX2UINT(expiry);
1419
1430
  }
1420
1431
  }
1421
1432
 
@@ -1600,7 +1611,7 @@ cb__map_subdoc_status(couchbase::protocol::status status, std::size_t index, con
1600
1611
  rb_hash_aset(
1601
1612
  entry,
1602
1613
  rb_id2sym(rb_intern("error")),
1603
- rb_exc_new_cstr(eInternalServerFailure,
1614
+ rb_exc_new_cstr(eCouchbaseError,
1604
1615
  fmt::format("unknown subdocument error status={}, index={}, path={}", status, index, path).c_str()));
1605
1616
  return;
1606
1617
  }
@@ -1762,10 +1773,10 @@ cb_Backend_document_mutate_in(VALUE self, VALUE bucket, VALUE collection, VALUE
1762
1773
  req.store_semantics = couchbase::protocol::mutate_in_request_body::store_semantics_type::upsert;
1763
1774
  }
1764
1775
  }
1765
- VALUE expiration = rb_hash_aref(options, rb_id2sym(rb_intern("expiration")));
1766
- if (!NIL_P(expiration)) {
1767
- Check_Type(expiration, T_FIXNUM);
1768
- req.expiration = FIX2UINT(expiration);
1776
+ VALUE expiry = rb_hash_aref(options, rb_id2sym(rb_intern("expiry")));
1777
+ if (!NIL_P(expiry)) {
1778
+ Check_Type(expiry, T_FIXNUM);
1779
+ req.expiry = FIX2UINT(expiry);
1769
1780
  }
1770
1781
  VALUE cas = rb_hash_aref(options, rb_id2sym(rb_intern("cas")));
1771
1782
  if (!NIL_P(cas)) {
@@ -4673,10 +4684,6 @@ cb_Backend_document_analytics(VALUE self, VALUE statement, VALUE options)
4673
4684
  if (!NIL_P(priority)) {
4674
4685
  req.priority = RTEST(priority);
4675
4686
  }
4676
- VALUE scan_wait = rb_hash_aref(options, rb_id2sym(rb_intern("scan_wait")));
4677
- if (!NIL_P(scan_wait)) {
4678
- req.scan_wait = NUM2ULONG(scan_wait);
4679
- }
4680
4687
  VALUE positional_params = rb_hash_aref(options, rb_id2sym(rb_intern("positional_parameters")));
4681
4688
  if (!NIL_P(positional_params)) {
4682
4689
  Check_Type(positional_params, T_ARRAY);
@@ -5340,9 +5347,9 @@ init_backend(VALUE mCouchbase)
5340
5347
  {
5341
5348
  VALUE cBackend = rb_define_class_under(mCouchbase, "Backend", rb_cBasicObject);
5342
5349
  rb_define_alloc_func(cBackend, cb_Backend_allocate);
5343
- rb_define_method(cBackend, "open", VALUE_FUNC(cb_Backend_open), 3);
5350
+ rb_define_method(cBackend, "open", VALUE_FUNC(cb_Backend_open), 4);
5344
5351
  rb_define_method(cBackend, "close", VALUE_FUNC(cb_Backend_close), 0);
5345
- rb_define_method(cBackend, "open_bucket", VALUE_FUNC(cb_Backend_open_bucket), 1);
5352
+ rb_define_method(cBackend, "open_bucket", VALUE_FUNC(cb_Backend_open_bucket), 2);
5346
5353
 
5347
5354
  rb_define_method(cBackend, "document_get", VALUE_FUNC(cb_Backend_document_get), 4);
5348
5355
  rb_define_method(cBackend, "document_get_projected", VALUE_FUNC(cb_Backend_document_get_projected), 7);
@@ -5424,7 +5431,7 @@ init_backend(VALUE mCouchbase)
5424
5431
  void
5425
5432
  init_logger()
5426
5433
  {
5427
- spdlog::set_pattern("[%Y-%m-%d %T.%e] [%P,%t] [%^%l%$] %v");
5434
+ spdlog::set_pattern("[%Y-%m-%d %T.%e] [%P,%t] [%^%l%$] %oms, %v");
5428
5435
 
5429
5436
  auto env_val = spdlog::details::os::getenv("COUCHBASE_BACKEND_LOG_LEVEL");
5430
5437
  if (env_val.empty()) {