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

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