couchbase 4.4.2 → 4.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/CMakeLists.txt +2 -0
  2. package/deps/couchbase-cxx-client/CMakeLists.txt +17 -14
  3. package/deps/couchbase-cxx-client/README.md +2 -2
  4. package/deps/couchbase-cxx-client/cmake/Packaging.cmake +4 -0
  5. package/deps/couchbase-cxx-client/cmake/Testing.cmake +1 -1
  6. package/deps/couchbase-cxx-client/cmake/VersionInfo.cmake +24 -2
  7. package/deps/couchbase-cxx-client/cmake/couchbase-cxx-client.spec.in +43 -4
  8. package/deps/couchbase-cxx-client/core/agent_group.cxx +8 -0
  9. package/deps/couchbase-cxx-client/core/agent_group.hxx +4 -0
  10. package/deps/couchbase-cxx-client/core/bucket.cxx +16 -20
  11. package/deps/couchbase-cxx-client/core/bucket.hxx +12 -12
  12. package/deps/couchbase-cxx-client/core/cluster.cxx +44 -52
  13. package/deps/couchbase-cxx-client/core/cluster_agent.cxx +8 -0
  14. package/deps/couchbase-cxx-client/core/cluster_agent.hxx +4 -0
  15. package/deps/couchbase-cxx-client/core/collections_component.cxx +2 -2
  16. package/deps/couchbase-cxx-client/core/columnar/agent.cxx +2 -2
  17. package/deps/couchbase-cxx-client/core/columnar/agent.hxx +1 -1
  18. package/deps/couchbase-cxx-client/core/columnar/management_component.cxx +3 -3
  19. package/deps/couchbase-cxx-client/core/columnar/query_component.cxx +103 -45
  20. package/deps/couchbase-cxx-client/core/columnar/query_component.hxx +1 -0
  21. package/deps/couchbase-cxx-client/core/free_form_http_request.hxx +8 -0
  22. package/deps/couchbase-cxx-client/core/http_component.cxx +55 -24
  23. package/deps/couchbase-cxx-client/core/http_component.hxx +4 -0
  24. package/deps/couchbase-cxx-client/core/impl/analytics_index_manager.cxx +15 -15
  25. package/deps/couchbase-cxx-client/core/impl/bootstrap_error.hxx +10 -2
  26. package/deps/couchbase-cxx-client/core/impl/bucket.cxx +1 -1
  27. package/deps/couchbase-cxx-client/core/impl/bucket_manager.cxx +6 -6
  28. package/deps/couchbase-cxx-client/core/impl/cluster.cxx +36 -40
  29. package/deps/couchbase-cxx-client/core/impl/collection.cxx +2 -2
  30. package/deps/couchbase-cxx-client/core/impl/collection_manager.cxx +5 -5
  31. package/deps/couchbase-cxx-client/core/impl/observe_poll.cxx +13 -5
  32. package/deps/couchbase-cxx-client/core/impl/observe_poll.hxx +1 -3
  33. package/deps/couchbase-cxx-client/core/impl/query_index_manager.cxx +6 -6
  34. package/deps/couchbase-cxx-client/core/impl/scan_result.cxx +1 -1
  35. package/deps/couchbase-cxx-client/core/impl/search_index_manager.cxx +12 -12
  36. package/deps/couchbase-cxx-client/core/io/http_command.hxx +31 -20
  37. package/deps/couchbase-cxx-client/core/io/http_session.cxx +5 -0
  38. package/deps/couchbase-cxx-client/core/io/http_session.hxx +17 -4
  39. package/deps/couchbase-cxx-client/core/io/http_session_manager.hxx +97 -49
  40. package/deps/couchbase-cxx-client/core/io/mcbp_command.hxx +15 -14
  41. package/deps/couchbase-cxx-client/core/io/mcbp_session.cxx +48 -33
  42. package/deps/couchbase-cxx-client/core/io/streams.cxx +256 -0
  43. package/deps/couchbase-cxx-client/core/io/streams.hxx +31 -155
  44. package/deps/couchbase-cxx-client/core/logger/configuration.hxx +5 -0
  45. package/deps/couchbase-cxx-client/core/logger/custom_rotating_file_sink.cxx +2 -3
  46. package/deps/couchbase-cxx-client/core/logger/logger.cxx +39 -7
  47. package/deps/couchbase-cxx-client/core/logger/logger.hxx +7 -0
  48. package/deps/couchbase-cxx-client/core/metrics/meter_wrapper.cxx +188 -0
  49. package/deps/couchbase-cxx-client/core/metrics/meter_wrapper.hxx +73 -0
  50. package/deps/couchbase-cxx-client/core/operations/management/bucket_describe.cxx +2 -1
  51. package/deps/couchbase-cxx-client/core/operations/management/bucket_drop.cxx +3 -1
  52. package/deps/couchbase-cxx-client/core/operations/management/bucket_flush.cxx +3 -1
  53. package/deps/couchbase-cxx-client/core/operations/management/bucket_get.cxx +3 -1
  54. package/deps/couchbase-cxx-client/core/operations/management/bucket_update.cxx +3 -1
  55. package/deps/couchbase-cxx-client/core/operations/management/collection_create.cxx +3 -2
  56. package/deps/couchbase-cxx-client/core/operations/management/collection_drop.cxx +5 -2
  57. package/deps/couchbase-cxx-client/core/operations/management/collection_update.cxx +4 -2
  58. package/deps/couchbase-cxx-client/core/operations/management/group_upsert.cxx +3 -3
  59. package/deps/couchbase-cxx-client/core/operations/management/scope_create.cxx +2 -1
  60. package/deps/couchbase-cxx-client/core/operations/management/scope_drop.cxx +4 -1
  61. package/deps/couchbase-cxx-client/core/operations/management/scope_get_all.cxx +3 -1
  62. package/deps/couchbase-cxx-client/core/operations/management/search_index_analyze_document.cxx +3 -2
  63. package/deps/couchbase-cxx-client/core/operations/management/search_index_control_ingest.cxx +3 -2
  64. package/deps/couchbase-cxx-client/core/operations/management/search_index_control_plan_freeze.cxx +3 -2
  65. package/deps/couchbase-cxx-client/core/operations/management/search_index_control_query.cxx +3 -2
  66. package/deps/couchbase-cxx-client/core/operations/management/search_index_drop.cxx +5 -2
  67. package/deps/couchbase-cxx-client/core/operations/management/search_index_get.cxx +5 -2
  68. package/deps/couchbase-cxx-client/core/operations/management/search_index_get_all.cxx +4 -2
  69. package/deps/couchbase-cxx-client/core/operations/management/search_index_get_documents_count.cxx +3 -2
  70. package/deps/couchbase-cxx-client/core/operations/management/search_index_upsert.cxx +5 -2
  71. package/deps/couchbase-cxx-client/core/operations/management/view_index_drop.cxx +2 -1
  72. package/deps/couchbase-cxx-client/core/operations/management/view_index_get.cxx +2 -1
  73. package/deps/couchbase-cxx-client/core/operations/management/view_index_get_all.cxx +3 -1
  74. package/deps/couchbase-cxx-client/core/operations/management/view_index_upsert.cxx +2 -1
  75. package/deps/couchbase-cxx-client/core/origin.cxx +37 -17
  76. package/deps/couchbase-cxx-client/core/platform/base64.cc +1 -1
  77. package/deps/couchbase-cxx-client/core/platform/random.cc +2 -0
  78. package/deps/couchbase-cxx-client/core/platform/uuid.h +6 -6
  79. package/deps/couchbase-cxx-client/core/row_streamer.cxx +1 -1
  80. package/deps/couchbase-cxx-client/core/sasl/scram-sha/stringutils.cc +1 -1
  81. package/deps/couchbase-cxx-client/core/sasl/scram-sha/stringutils.h +4 -4
  82. package/deps/couchbase-cxx-client/core/topology/configuration.hxx +2 -0
  83. package/deps/couchbase-cxx-client/core/topology/configuration_json.hxx +8 -0
  84. package/deps/couchbase-cxx-client/core/tracing/constants.hxx +3 -0
  85. package/deps/couchbase-cxx-client/core/tracing/tracer_wrapper.cxx +87 -0
  86. package/deps/couchbase-cxx-client/core/tracing/tracer_wrapper.hxx +57 -0
  87. package/deps/couchbase-cxx-client/core/transactions/attempt_context_impl.cxx +16 -15
  88. package/deps/couchbase-cxx-client/core/transactions/attempt_context_impl.hxx +2 -2
  89. package/deps/couchbase-cxx-client/core/transactions/staged_mutation.cxx +2 -2
  90. package/deps/couchbase-cxx-client/core/transactions/transactions.cxx +2 -2
  91. package/deps/couchbase-cxx-client/core/utils/connection_string.cxx +128 -52
  92. package/deps/couchbase-cxx-client/couchbase/analytics_options.hxx +4 -3
  93. package/deps/couchbase-cxx-client/couchbase/codec/tao_json_serializer.hxx +1 -1
  94. package/deps/couchbase-cxx-client/couchbase/mutate_in_specs.hxx +2 -2
  95. package/deps/couchbase-cxx-client/couchbase/query_options.hxx +4 -3
  96. package/deps/couchbase-cxx-client/couchbase/search_options.hxx +1 -1
  97. package/package.json +8 -8
  98. package/src/binding.cpp +13 -13
@@ -49,7 +49,7 @@ public:
49
49
 
50
50
  auto free_form_http_request(const http_request& request,
51
51
  free_form_http_request_callback&& callback)
52
- -> tl::expected<std::shared_ptr<pending_operation>, std::error_code>
52
+ -> tl::expected<std::shared_ptr<pending_operation>, error_union>
53
53
  {
54
54
  return http_.do_http_request(request, std::move(callback));
55
55
  }
@@ -102,7 +102,7 @@ agent::agent(asio::io_context& io, couchbase::core::columnar::agent_config confi
102
102
  auto
103
103
  agent::free_form_http_request(const http_request& request,
104
104
  free_form_http_request_callback&& callback)
105
- -> tl::expected<std::shared_ptr<pending_operation>, std::error_code>
105
+ -> tl::expected<std::shared_ptr<pending_operation>, error_union>
106
106
  {
107
107
  return impl_->free_form_http_request(request, std::move(callback));
108
108
  }
@@ -46,7 +46,7 @@ public:
46
46
 
47
47
  auto free_form_http_request(const http_request& request,
48
48
  free_form_http_request_callback&& callback)
49
- -> tl::expected<std::shared_ptr<pending_operation>, std::error_code>;
49
+ -> tl::expected<std::shared_ptr<pending_operation>, error_union>;
50
50
 
51
51
  auto free_form_http_request_buffered(const http_request& request,
52
52
  buffered_free_form_http_request_callback&& callback)
@@ -189,7 +189,7 @@ public:
189
189
  "SELECT d.* FROM `System`.`Metadata`.`Database` AS d",
190
190
  options.timeout,
191
191
  };
192
- return execute(std::move(req), [cb = std::move(callback)](auto raw_res, auto err) {
192
+ return execute(std::move(req), [cb = std::move(callback)](const auto& raw_res, auto err) {
193
193
  if (err) {
194
194
  cb({}, std::move(err));
195
195
  return;
@@ -216,7 +216,7 @@ public:
216
216
  if (options.ignore_if_exists) {
217
217
  req.statement += " IF NOT EXISTS";
218
218
  }
219
- return execute(std::move(req), [cb = std::move(callback)](auto /*raw_res*/, auto err) {
219
+ return execute(std::move(req), [cb = std::move(callback)](const auto& /*raw_res*/, auto err) {
220
220
  cb(std::move(err));
221
221
  });
222
222
  }
@@ -231,7 +231,7 @@ public:
231
231
  if (options.ignore_if_not_exists) {
232
232
  req.statement += " IF EXISTS";
233
233
  }
234
- return execute(std::move(req), [cb = std::move(callback)](auto /*raw_res*/, auto err) {
234
+ return execute(std::move(req), [cb = std::move(callback)](const auto& /*raw_res*/, auto err) {
235
235
  cb(std::move(err));
236
236
  });
237
237
  }
@@ -79,17 +79,28 @@ public:
79
79
 
80
80
  auto dispatch() -> error
81
81
  {
82
- auto op =
83
- http_.do_http_request(http_req_, [self = shared_from_this()](auto resp, auto ec) mutable {
82
+ auto op = http_.do_http_request(
83
+ http_req_, [self = shared_from_this()](auto resp, error_union err) mutable {
84
84
  std::shared_ptr<pending_operation> op;
85
85
  {
86
86
  const std::scoped_lock lock{ self->pending_op_mutex_ };
87
87
  std::swap(op, self->pending_op_);
88
88
  }
89
- if (ec) {
90
- self->invoke_callback(
91
- {},
92
- { maybe_convert_error_code(ec), "Failed to execute the HTTP request for the query" });
89
+ if (!std::holds_alternative<std::monostate>(err)) {
90
+ if (std::holds_alternative<impl::bootstrap_error>(err)) {
91
+ auto bootstrap_error = std::get<impl::bootstrap_error>(err);
92
+ auto message = fmt::format(
93
+ "Failed to execute the HTTP request for the query due to a bootstrap error. "
94
+ "See logs for further details. bootstrap_error.message={}",
95
+ bootstrap_error.error_message);
96
+ self->invoke_callback({}, { maybe_convert_error_code(bootstrap_error.ec), message });
97
+ } else {
98
+ auto ec = maybe_convert_error_code(std::get<std::error_code>(err));
99
+ if (ec == errc::timeout) {
100
+ return self->trigger_timeout();
101
+ }
102
+ self->invoke_callback({}, { ec, "Failed to execute the HTTP request for the query" });
103
+ }
93
104
  return;
94
105
  }
95
106
  // op can be null if the pending_query_operation was cancelled.
@@ -101,7 +112,7 @@ public:
101
112
  }
102
113
  auto streamer = std::make_shared<row_streamer>(self->io_, resp.body(), "/results/^");
103
114
  return streamer->start(
104
- [self, streamer, resp = std::move(resp)](auto metadata_header, auto ec) mutable {
115
+ [self, streamer, resp = std::move(resp)](const auto& metadata_header, auto ec) mutable {
105
116
  if (ec) {
106
117
  self->invoke_callback({}, { maybe_convert_error_code(ec) });
107
118
  return;
@@ -127,7 +138,27 @@ public:
127
138
  pending_op_ = op.value();
128
139
  return {};
129
140
  }
130
- return error{ op.error() };
141
+ retry_timer_.cancel();
142
+ deadline_.cancel();
143
+ error return_error{};
144
+ #ifdef COUCHBASE_CXX_CLIENT_COLUMNAR
145
+ if (std::holds_alternative<impl::bootstrap_error>(op.error())) {
146
+ auto bootstrap_error = std::get<impl::bootstrap_error>(op.error());
147
+ auto message =
148
+ fmt::format("Failed to create the HTTP pending operation due to a bootstrap error. "
149
+ "See logs for further details. bootstrap_error.message={}",
150
+ bootstrap_error.error_message);
151
+ return_error.ec = bootstrap_error.ec;
152
+ return_error.message = message;
153
+ } else {
154
+ return_error.ec = std::get<std::error_code>(op.error());
155
+ return_error.message = "Failed to create the HTTP pending operation.";
156
+ }
157
+ #else
158
+ return_error.ec = op.error();
159
+ #endif
160
+ invoke_callback({}, return_error);
161
+ return return_error;
131
162
  }
132
163
 
133
164
  auto start(query_callback&& callback) -> error
@@ -252,11 +283,13 @@ private:
252
283
  break;
253
284
  }
254
285
  }
286
+
287
+ const std::chrono::milliseconds server_timeout = timeout_ + std::chrono::seconds(5);
288
+ payload["timeout"] = fmt::format("{}ms", server_timeout.count());
289
+
255
290
  for (const auto& [key, val] : options.raw) {
256
291
  payload[key] = utils::json::parse(val);
257
292
  }
258
- const std::chrono::milliseconds server_timeout = timeout_ + std::chrono::seconds(5);
259
- payload["timeout"] = fmt::format("{}ms", server_timeout.count());
260
293
 
261
294
  return payload;
262
295
  }
@@ -296,7 +329,7 @@ private:
296
329
  // retryable errors should be listed.
297
330
  if (err.ec == errc::timeout && retry_info_.last_error) {
298
331
  if (const auto* e = retry_info_.last_error.ctx.find("errors"); e != nullptr) {
299
- err.ctx["last_errors"] = e;
332
+ err.ctx["last_errors"] = e->get_array();
300
333
  }
301
334
  }
302
335
  }
@@ -334,53 +367,71 @@ private:
334
367
  std::int32_t first_error_code{ 0 };
335
368
  std::string first_error_msg{};
336
369
 
370
+ std::int32_t first_non_retr_error_code{ 0 };
371
+ std::string first_non_retr_error_msg{};
372
+
337
373
  for (auto error_json : errors_json->get_array()) {
338
- auto* retr = error_json.find("retriable");
339
- if (retr == nullptr) {
340
- // An error is assumed to not be retriable if the field is missing
341
- res.retriable = false;
342
- } else if (!retr->is_boolean()) {
343
- return { { errc::generic,
344
- "Could not parse error from server response - 'retriable' was not boolean" } };
345
- } else {
346
- // Operation is retriable iff all errors are retriable
347
- res.retriable = res.retriable && retr->get_boolean();
374
+ bool retr{ false }; // An error is assumed to not be retriable if the field is missing
375
+ {
376
+ auto* r = error_json.find("retriable");
377
+ if (r != nullptr) {
378
+ if (!r->is_boolean()) {
379
+ return {
380
+ { errc::generic,
381
+ "Could not parse error from server response - 'retriable' was not boolean" }
382
+ };
383
+ }
384
+ retr = r->get_boolean();
385
+ }
348
386
  }
349
387
 
350
- auto* msg = error_json.find("msg");
351
- if (msg == nullptr) {
352
- return { { errc::generic,
353
- "Could not parse error from server response - could not find 'msg' field" } };
354
- }
355
- if (!msg->is_string()) {
356
- return { { errc::generic,
357
- "Could not parse error from server response - 'msg' field was not string" } };
358
- }
388
+ // Operation is retriable iff all errors are retriable
389
+ res.retriable = res.retriable && retr;
359
390
 
360
- auto* c = error_json.find("code");
361
- if (c == nullptr) {
362
- return { { errc::generic,
363
- "Could not parse error from server response - could not find 'code' field" } };
364
- }
365
- if (!(c->is_unsigned() || c->is_signed())) {
366
- return {
367
- { errc::generic,
368
- "Could not parse error from server response - 'code' field was not an integer" }
369
- };
391
+ std::string msg{};
392
+ {
393
+ auto* m = error_json.find("msg");
394
+ if (m == nullptr) {
395
+ return { { errc::generic,
396
+ "Could not parse error from server response - could not find 'msg' field" } };
397
+ }
398
+ if (!m->is_string()) {
399
+ return { { errc::generic,
400
+ "Could not parse error from server response - 'msg' field was not string" } };
401
+ }
402
+ msg = m->get_string();
370
403
  }
371
404
 
372
- std::int32_t code = c->is_signed() ? gsl::narrow_cast<std::int32_t>(c->get_signed())
373
- : gsl::narrow_cast<std::int32_t>(c->get_unsigned());
405
+ std::int32_t code{};
406
+ {
407
+ auto* c = error_json.find("code");
408
+ if (c == nullptr) {
409
+ return { { errc::generic,
410
+ "Could not parse error from server response - could not find 'code' field" } };
411
+ }
412
+ if (!(c->is_unsigned() || c->is_signed())) {
413
+ return {
414
+ { errc::generic,
415
+ "Could not parse error from server response - 'code' field was not an integer" }
416
+ };
417
+ }
418
+ code = c->is_signed() ? gsl::narrow_cast<std::int32_t>(c->get_signed())
419
+ : gsl::narrow_cast<std::int32_t>(c->get_unsigned());
420
+ }
374
421
 
375
422
  tao::json::value error = {
376
423
  { "code", code },
377
- { "msg", msg->get_string() },
424
+ { "msg", msg },
378
425
  };
379
426
  res.err.ctx["errors"].get_array().emplace_back(std::move(error));
380
427
 
381
428
  if (first_error_code == 0) {
382
429
  first_error_code = code;
383
- first_error_msg = msg->get_string();
430
+ first_error_msg = msg;
431
+ }
432
+ if (!retr && first_non_retr_error_code == 0) {
433
+ first_non_retr_error_code = code;
434
+ first_non_retr_error_msg = msg;
384
435
  }
385
436
 
386
437
  switch (code) {
@@ -396,7 +447,14 @@ private:
396
447
  }
397
448
 
398
449
  if (res.err.ec == errc::query_error) {
399
- res.err.properties = query_error_properties{ first_error_code, first_error_msg };
450
+ // If any of the errors is not retriable, report the first non-retriable code/message in the
451
+ // error properties
452
+ if (first_non_retr_error_code != 0) {
453
+ res.err.properties =
454
+ query_error_properties{ first_non_retr_error_code, first_non_retr_error_msg };
455
+ } else {
456
+ res.err.properties = query_error_properties{ first_error_code, first_error_msg };
457
+ }
400
458
  }
401
459
 
402
460
  return res;
@@ -17,6 +17,7 @@
17
17
 
18
18
  #pragma once
19
19
 
20
+ #include "core/impl/bootstrap_error.hxx"
20
21
  #include "core/pending_operation.hxx"
21
22
  #include "error.hxx"
22
23
  #include "query_options.hxx"
@@ -15,6 +15,9 @@
15
15
 
16
16
  #pragma once
17
17
 
18
+ #include <couchbase/build_config.hxx>
19
+
20
+ #include "core/impl/bootstrap_error.hxx"
18
21
  #include "service_type.hxx"
19
22
  #include "utils/movable_function.hxx"
20
23
 
@@ -101,8 +104,13 @@ private:
101
104
  std::shared_ptr<http_response_impl> impl_;
102
105
  };
103
106
 
107
+ #ifdef COUCHBASE_CXX_CLIENT_COLUMNAR
108
+ using free_form_http_request_callback =
109
+ utils::movable_function<void(http_response response, couchbase::core::error_union err)>;
110
+ #else
104
111
  using free_form_http_request_callback =
105
112
  utils::movable_function<void(http_response response, std::error_code ec)>;
113
+ #endif
106
114
 
107
115
  class buffered_http_response_impl;
108
116
 
@@ -131,19 +131,22 @@ public:
131
131
  invoke_response_handler(errc::common::request_canceled, {});
132
132
  }
133
133
 
134
- void invoke_response_handler(std::error_code ec, io::http_streaming_response resp)
135
- {
136
- deadline_.cancel();
137
134
  #ifdef COUCHBASE_CXX_CLIENT_COLUMNAR
135
+ void invoke_response_handler(error_union err, io::http_streaming_response resp)
136
+ {
138
137
  dispatch_deadline_.cancel();
138
+ #else
139
+ void invoke_response_handler(std::error_code err, io::http_streaming_response resp)
140
+ {
139
141
  #endif
142
+ deadline_.cancel();
140
143
  free_form_http_request_callback callback{};
141
144
  {
142
145
  const std::scoped_lock lock(callback_mutex_);
143
146
  std::swap(callback, callback_);
144
147
  }
145
148
  if (callback) {
146
- callback(http_response{ std::move(resp) }, ec);
149
+ callback(http_response{ std::move(resp) }, err);
147
150
  }
148
151
  }
149
152
 
@@ -157,12 +160,22 @@ public:
157
160
  auto start_op = [self = shared_from_this()]() {
158
161
  self->session_->write_and_stream(
159
162
  self->encoded_,
163
+ #ifdef COUCHBASE_CXX_CLIENT_COLUMNAR
164
+ [self](error_union err, io::http_streaming_response resp) {
165
+ if (std::holds_alternative<std::error_code>(err) &&
166
+ std::get<std::error_code>(err) == asio::error::operation_aborted) {
167
+ return;
168
+ }
169
+ self->invoke_response_handler(err, std::move(resp));
170
+ },
171
+ #else
160
172
  [self](std::error_code ec, io::http_streaming_response resp) {
161
173
  if (ec == asio::error::operation_aborted) {
162
174
  return;
163
175
  }
164
176
  self->invoke_response_handler(ec, std::move(resp));
165
177
  },
178
+ #endif
166
179
  [self]() {
167
180
  self->stream_end_callback_();
168
181
  });
@@ -409,8 +422,13 @@ public:
409
422
  {
410
423
  }
411
424
 
425
+ #ifdef COUCHBASE_CXX_CLIENT_COLUMNAR
426
+ auto do_http_request(const http_request& request, free_form_http_request_callback&& callback)
427
+ -> tl::expected<std::shared_ptr<pending_operation>, error_union>
428
+ #else
412
429
  auto do_http_request(const http_request& request, free_form_http_request_callback&& callback)
413
430
  -> tl::expected<std::shared_ptr<pending_operation>, std::error_code>
431
+ #endif
414
432
  {
415
433
  std::shared_ptr<io::http_session_manager> session_manager;
416
434
  {
@@ -436,9 +454,9 @@ public:
436
454
  auto op =
437
455
  std::make_shared<pending_http_operation>(io_, request, session_manager->dispatch_timeout());
438
456
  if (!session_manager->is_configured()) {
439
- auto ec = defer_command(op, session_manager, credentials, std::move(callback));
440
- if (ec) {
441
- return tl::unexpected{ ec };
457
+ auto err = defer_command(op, session_manager, credentials, std::move(callback));
458
+ if (!std::holds_alternative<std::monostate>(err)) {
459
+ return tl::unexpected{ err };
442
460
  }
443
461
  return op;
444
462
  }
@@ -478,8 +496,11 @@ public:
478
496
  auto op = std::make_shared<pending_buffered_http_operation>(
479
497
  io_, request, session_manager->dispatch_timeout());
480
498
  if (!session_manager->is_configured()) {
481
- auto ec = defer_command(op, session_manager, credentials, std::move(callback));
482
- if (ec) {
499
+ auto err = defer_command(op, session_manager, credentials, std::move(callback));
500
+ if (!std::holds_alternative<std::monostate>(err)) {
501
+ auto ec = std::holds_alternative<impl::bootstrap_error>(err)
502
+ ? std::get<impl::bootstrap_error>(err).ec
503
+ : std::get<std::error_code>(err);
483
504
  return tl::unexpected{ ec };
484
505
  }
485
506
  return op;
@@ -498,16 +519,19 @@ private:
498
519
  const couchbase::core::cluster_credentials& credentials,
499
520
  free_form_http_request_callback&& callback)
500
521
  {
501
- op->start([callback = std::move(callback)](auto resp, auto ec) mutable {
502
- callback(std::move(resp), ec);
503
- });
504
-
505
522
  #ifdef COUCHBASE_CXX_CLIENT_COLUMNAR
523
+ op->start([callback = std::move(callback)](auto resp, error_union err) mutable {
524
+ callback(std::move(resp), err);
525
+ });
506
526
  // don't do anything if the op wasn't dispatched or has already timed out
507
527
  auto now = std::chrono::steady_clock::now();
508
528
  if (op->dispatch_deadline_expiry() < now || op->deadline_expiry() < now) {
509
529
  return;
510
530
  }
531
+ #else
532
+ op->start([callback = std::move(callback)](auto resp, auto ec) mutable {
533
+ callback(std::move(resp), ec);
534
+ });
511
535
  #endif
512
536
  std::shared_ptr<io::http_session> session;
513
537
  {
@@ -592,10 +616,10 @@ private:
592
616
  auto defer_command(std::shared_ptr<PendingHttpOp> pending_op,
593
617
  const std::shared_ptr<io::http_session_manager>& session_manager,
594
618
  const couchbase::core::cluster_credentials& credentials,
595
- Callback&& callback) -> std::error_code
619
+ Callback&& callback) -> error_union
596
620
  {
597
621
  if (auto last_error = session_manager->last_bootstrap_error(); last_error.has_value()) {
598
- return last_error->ec;
622
+ return last_error.value();
599
623
  }
600
624
  CB_LOG_DEBUG(
601
625
  R"(Adding pending HTTP operation to deferred queue: service={}, client_context_id={})",
@@ -605,26 +629,26 @@ private:
605
629
  callback = std::forward<Callback>(callback),
606
630
  op = std::move(pending_op),
607
631
  session_manager,
608
- credentials](std::error_code ec) mutable {
609
- if (ec) {
632
+ credentials](error_union err) mutable {
633
+ if (!std::holds_alternative<std::monostate>(err)) {
610
634
  // The deferred operation was cancelled - currently this can happen due to closing the
611
635
  // cluster
612
- return callback({}, ec);
636
+ return callback({}, err);
613
637
  }
614
638
 
615
639
  return send_http_operation(
616
640
  op, session_manager, credentials, std::forward<Callback>(callback));
617
641
  });
618
- return {};
642
+ return std::monostate{};
619
643
  }
620
644
 
621
645
  auto defer_command(std::shared_ptr<pending_buffered_http_operation> pending_op,
622
646
  const std::shared_ptr<io::http_session_manager>& session_manager,
623
647
  const couchbase::core::cluster_credentials& credentials,
624
- buffered_free_form_http_request_callback&& callback) -> std::error_code
648
+ buffered_free_form_http_request_callback&& callback) -> error_union
625
649
  {
626
650
  if (auto last_error = session_manager->last_bootstrap_error(); last_error.has_value()) {
627
- return last_error->ec;
651
+ return last_error.value();
628
652
  }
629
653
  CB_LOG_DEBUG(
630
654
  R"(Adding pending HTTP operation to deferred queue: service={}, client_context_id={})",
@@ -634,8 +658,11 @@ private:
634
658
  callback = std::move(callback),
635
659
  op = std::move(pending_op),
636
660
  session_manager,
637
- credentials](std::error_code ec) mutable {
638
- if (ec) {
661
+ credentials](error_union err) mutable {
662
+ if (!std::holds_alternative<std::monostate>(err)) {
663
+ auto ec = std::holds_alternative<impl::bootstrap_error>(err)
664
+ ? std::get<impl::bootstrap_error>(err).ec
665
+ : std::get<std::error_code>(err);
639
666
  // The deferred operation was cancelled - currently this can happen due to closing the
640
667
  // cluster
641
668
  return callback({}, ec);
@@ -643,7 +670,7 @@ private:
643
670
 
644
671
  return send_http_operation(op, session_manager, credentials, std::move(callback));
645
672
  });
646
- return {};
673
+ return std::monostate{};
647
674
  }
648
675
  #endif
649
676
 
@@ -664,7 +691,11 @@ http_component::http_component(asio::io_context& io,
664
691
  auto
665
692
  http_component::do_http_request(const http_request& request,
666
693
  free_form_http_request_callback&& callback)
694
+ #ifdef COUCHBASE_CXX_CLIENT_COLUMNAR
695
+ -> tl::expected<std::shared_ptr<pending_operation>, error_union>
696
+ #else
667
697
  -> tl::expected<std::shared_ptr<pending_operation>, std::error_code>
698
+ #endif
668
699
  {
669
700
  return impl_->do_http_request(request, std::move(callback));
670
701
  }
@@ -49,7 +49,11 @@ public:
49
49
  std::shared_ptr<retry_strategy> default_retry_strategy = {});
50
50
 
51
51
  auto do_http_request(const http_request& request, free_form_http_request_callback&& callback)
52
+ #ifdef COUCHBASE_CXX_CLIENT_COLUMNAR
53
+ -> tl::expected<std::shared_ptr<pending_operation>, error_union>;
54
+ #else
52
55
  -> tl::expected<std::shared_ptr<pending_operation>, std::error_code>;
56
+ #endif
53
57
 
54
58
  auto do_http_request_buffered(const http_request& request,
55
59
  buffered_free_form_http_request_callback&& callback)
@@ -159,7 +159,7 @@ public:
159
159
  {},
160
160
  options.timeout,
161
161
  },
162
- [dataverse_name, handler = std::move(handler)](auto resp) {
162
+ [dataverse_name, handler = std::move(handler)](const auto& resp) {
163
163
  CB_LOG_DEBUG(
164
164
  "Dataverse create for {} error code = {}", dataverse_name, resp.ctx.ec.value());
165
165
  handler(core::impl::make_error(resp.ctx));
@@ -177,7 +177,7 @@ public:
177
177
  {},
178
178
  options.timeout,
179
179
  },
180
- [handler = std::move(handler)](auto resp) {
180
+ [handler = std::move(handler)](const auto& resp) {
181
181
  handler(core::impl::make_error(resp.ctx));
182
182
  });
183
183
  }
@@ -197,7 +197,7 @@ public:
197
197
  options.timeout,
198
198
  options.ignore_if_exists,
199
199
  },
200
- [handler = std::move(handler)](auto resp) {
200
+ [handler = std::move(handler)](const auto& resp) {
201
201
  handler(core::impl::make_error(resp.ctx));
202
202
  });
203
203
  }
@@ -214,7 +214,7 @@ public:
214
214
  {},
215
215
  options.timeout,
216
216
  },
217
- [handler = std::move(handler)](auto resp) {
217
+ [handler = std::move(handler)](const auto& resp) {
218
218
  handler(core::impl::make_error(resp.ctx));
219
219
  });
220
220
  }
@@ -262,7 +262,7 @@ public:
262
262
  {},
263
263
  options.timeout,
264
264
  },
265
- [handler = std::move(handler)](auto resp) {
265
+ [handler = std::move(handler)](const auto& resp) {
266
266
  handler(core::impl::make_error(resp.ctx));
267
267
  });
268
268
  }
@@ -281,7 +281,7 @@ public:
281
281
  {},
282
282
  options.timeout,
283
283
  },
284
- [handler = std::move(handler)](auto resp) {
284
+ [handler = std::move(handler)](const auto& resp) {
285
285
  handler(core::impl::make_error(resp.ctx));
286
286
  });
287
287
  }
@@ -324,7 +324,7 @@ public:
324
324
  {},
325
325
  options.timeout,
326
326
  },
327
- [handler = std::move(handler)](auto resp) {
327
+ [handler = std::move(handler)](const auto& resp) {
328
328
  handler(core::impl::make_error(resp.ctx));
329
329
  });
330
330
  }
@@ -339,7 +339,7 @@ public:
339
339
  {},
340
340
  options.timeout,
341
341
  },
342
- [handler = std::move(handler)](auto resp) {
342
+ [handler = std::move(handler)](const auto& resp) {
343
343
  handler(core::impl::make_error(resp.ctx));
344
344
  });
345
345
  }
@@ -386,7 +386,7 @@ public:
386
386
  {},
387
387
  options.timeout,
388
388
  },
389
- [handler = std::move(handler)](auto resp) {
389
+ [handler = std::move(handler)](const auto& resp) {
390
390
  handler(core::impl::make_error(resp.ctx));
391
391
  });
392
392
 
@@ -398,7 +398,7 @@ public:
398
398
  {},
399
399
  options.timeout,
400
400
  },
401
- [handler = std::move(handler)](auto resp) {
401
+ [handler = std::move(handler)](const auto& resp) {
402
402
  handler(core::impl::make_error(resp.ctx));
403
403
  });
404
404
 
@@ -410,7 +410,7 @@ public:
410
410
  {},
411
411
  options.timeout,
412
412
  },
413
- [handler = std::move(handler)](auto resp) {
413
+ [handler = std::move(handler)](const auto& resp) {
414
414
  handler(core::impl::make_error(resp.ctx));
415
415
  });
416
416
  }
@@ -429,7 +429,7 @@ public:
429
429
  {},
430
430
  options.timeout,
431
431
  },
432
- [handler = std::move(handler)](auto resp) {
432
+ [handler = std::move(handler)](const auto& resp) {
433
433
  handler(core::impl::make_error(resp.ctx));
434
434
  });
435
435
 
@@ -441,7 +441,7 @@ public:
441
441
  {},
442
442
  options.timeout,
443
443
  },
444
- [handler = std::move(handler)](auto resp) {
444
+ [handler = std::move(handler)](const auto& resp) {
445
445
  handler(core::impl::make_error(resp.ctx));
446
446
  });
447
447
 
@@ -453,7 +453,7 @@ public:
453
453
  {},
454
454
  options.timeout,
455
455
  },
456
- [handler = std::move(handler)](auto resp) {
456
+ [handler = std::move(handler)](const auto& resp) {
457
457
  handler(core::impl::make_error(resp.ctx));
458
458
  });
459
459
  }
@@ -471,7 +471,7 @@ public:
471
471
  {},
472
472
  options.timeout,
473
473
  },
474
- [handler = std::move(handler)](auto resp) {
474
+ [handler = std::move(handler)](const auto& resp) {
475
475
  handler(core::impl::make_error(resp.ctx));
476
476
  });
477
477
  }
@@ -20,8 +20,12 @@
20
20
  #include <optional>
21
21
  #include <string>
22
22
  #include <system_error>
23
+ #include <variant>
23
24
 
24
- namespace couchbase::core::impl
25
+ namespace couchbase::core
26
+ {
27
+
28
+ namespace impl
25
29
  {
26
30
 
27
31
  struct bootstrap_error {
@@ -31,4 +35,8 @@ struct bootstrap_error {
31
35
  std::optional<std::string> port;
32
36
  };
33
37
 
34
- } // namespace couchbase::core::impl
38
+ } // namespace impl
39
+
40
+ using error_union = std::variant<std::monostate, std::error_code, impl::bootstrap_error>;
41
+
42
+ } // namespace couchbase::core
@@ -59,7 +59,7 @@ public:
59
59
  name_,
60
60
  core::impl::to_core_service_types(options.service_types),
61
61
  options.timeout,
62
- [handler = std::move(handler)](auto resp) mutable {
62
+ [handler = std::move(handler)](const auto& resp) mutable {
63
63
  return handler({}, core::impl::build_result(resp));
64
64
  });
65
65
  }