couchbase 4.2.11 → 4.3.0
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.
- package/deps/couchbase-cxx-cache/mozilla-ca-bundle.crt +49 -2
- package/deps/couchbase-cxx-cache/mozilla-ca-bundle.sha256 +1 -1
- package/deps/couchbase-cxx-client/core/impl/cluster.cxx +51 -5
- package/deps/couchbase-cxx-client/core/impl/collection.cxx +224 -209
- package/deps/couchbase-cxx-client/core/impl/query_error_context.cxx +2 -2
- package/deps/couchbase-cxx-client/core/impl/query_index_manager.cxx +1 -0
- package/deps/couchbase-cxx-client/core/io/dns_client.cxx +4 -0
- package/deps/couchbase-cxx-client/core/io/dns_config.cxx +15 -4
- package/deps/couchbase-cxx-client/core/io/dns_config.hxx +1 -1
- package/deps/couchbase-cxx-client/core/io/mcbp_session.cxx +84 -53
- package/deps/couchbase-cxx-client/core/mcbp/operation_queue.cxx +1 -0
- package/deps/couchbase-cxx-client/core/meta/features.hxx +5 -0
- package/deps/couchbase-cxx-client/core/operations/document_lookup_in_all_replicas.hxx +116 -105
- package/deps/couchbase-cxx-client/core/operations/document_lookup_in_any_replica.hxx +116 -108
- package/deps/couchbase-cxx-client/core/operations/document_search.cxx +97 -81
- package/deps/couchbase-cxx-client/core/operations/document_search.hxx +5 -0
- package/deps/couchbase-cxx-client/core/range_scan_orchestrator_options.hxx +2 -1
- package/deps/couchbase-cxx-client/core/transactions/atr_cleanup_entry.cxx +16 -7
- package/deps/couchbase-cxx-client/core/transactions/attempt_context_impl.cxx +578 -483
- package/deps/couchbase-cxx-client/core/transactions/attempt_context_testing_hooks.cxx +51 -50
- package/deps/couchbase-cxx-client/core/transactions/attempt_context_testing_hooks.hxx +4 -2
- package/deps/couchbase-cxx-client/core/transactions/cleanup_testing_hooks.cxx +6 -6
- package/deps/couchbase-cxx-client/core/transactions/cleanup_testing_hooks.hxx +3 -2
- package/deps/couchbase-cxx-client/core/transactions/internal/transactions_cleanup.hxx +2 -0
- package/deps/couchbase-cxx-client/core/transactions/internal/utils.hxx +5 -1
- package/deps/couchbase-cxx-client/core/transactions/staged_mutation.cxx +222 -179
- package/deps/couchbase-cxx-client/core/transactions/staged_mutation.hxx +23 -12
- package/deps/couchbase-cxx-client/core/transactions/transactions.cxx +61 -24
- package/deps/couchbase-cxx-client/core/transactions/transactions_cleanup.cxx +36 -16
- package/deps/couchbase-cxx-client/core/transactions/utils.cxx +9 -0
- package/deps/couchbase-cxx-client/core/transactions.hxx +40 -7
- package/deps/couchbase-cxx-client/couchbase/cluster.hxx +19 -0
- package/deps/couchbase-cxx-client/couchbase/fork_event.hxx +39 -0
- package/dist/binding.d.ts +8 -0
- package/dist/bindingutilities.d.ts +6 -1
- package/dist/bindingutilities.js +15 -1
- package/dist/bucketmanager.d.ts +0 -12
- package/dist/cluster.d.ts +0 -2
- package/dist/cluster.js +0 -2
- package/dist/collection.d.ts +3 -3
- package/dist/collection.js +3 -1
- package/dist/querytypes.d.ts +0 -2
- package/dist/rangeScan.d.ts +0 -8
- package/dist/rangeScan.js +0 -8
- package/dist/scope.d.ts +0 -5
- package/dist/scope.js +0 -5
- package/dist/scopesearchindexmanager.d.ts +0 -2
- package/dist/scopesearchindexmanager.js +0 -2
- package/dist/searchexecutor.js +3 -1
- package/dist/searchtypes.d.ts +16 -6
- package/dist/searchtypes.js +2 -6
- package/dist/transactions.d.ts +23 -0
- package/dist/transactions.js +16 -10
- package/dist/vectorsearch.d.ts +8 -8
- package/dist/vectorsearch.js +7 -7
- package/package.json +7 -7
- package/src/instance.cpp +11 -1
- package/src/instance.hpp +1 -0
- package/src/jstocbpp_autogen.hpp +8 -0
- package/src/jstocbpp_transactions.hpp +40 -3
- package/src/transactions.cpp +12 -1
- package/tools/gen-bindings-json.py +0 -1
@@ -62,123 +62,131 @@ struct lookup_in_any_replica_request {
|
|
62
62
|
template<typename Core, typename Handler>
|
63
63
|
void execute(Core core, Handler handler)
|
64
64
|
{
|
65
|
-
core->
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
65
|
+
core->open_bucket(id.bucket(),
|
66
|
+
[core, id = id, timeout = timeout, specs = specs, parent_span = parent_span, h = std::forward<Handler>(handler)](
|
67
|
+
std::error_code ec) mutable {
|
68
|
+
if (ec) {
|
69
|
+
std::optional<std::string> first_error_path{};
|
70
|
+
std::optional<std::size_t> first_error_index{};
|
71
|
+
h(response_type{ make_subdocument_error_context(
|
72
|
+
make_key_value_error_context(ec, id), ec, first_error_path, first_error_index, false) });
|
73
|
+
return;
|
74
|
+
}
|
75
|
+
return core->with_bucket_configuration(
|
76
|
+
id.bucket(),
|
77
|
+
[core, id = id, timeout = timeout, specs = specs, parent_span = parent_span, h = std::forward<Handler>(h)](
|
78
|
+
std::error_code ec, const topology::configuration& config) mutable {
|
79
|
+
if (!config.capabilities.supports_subdoc_read_replica()) {
|
80
|
+
ec = errc::common::feature_not_available;
|
81
|
+
}
|
75
82
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
+
if (ec) {
|
84
|
+
std::optional<std::string> first_error_path{};
|
85
|
+
std::optional<std::size_t> first_error_index{};
|
86
|
+
return h(response_type{ make_subdocument_error_context(
|
87
|
+
make_key_value_error_context(ec, id), ec, first_error_path, first_error_index, false) });
|
88
|
+
}
|
89
|
+
using handler_type = utils::movable_function<void(response_type)>;
|
83
90
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
91
|
+
struct replica_context {
|
92
|
+
replica_context(handler_type&& handler, std::uint32_t expected_responses)
|
93
|
+
: handler_(std::move(handler))
|
94
|
+
, expected_responses_(expected_responses)
|
95
|
+
{
|
96
|
+
}
|
90
97
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
98
|
+
handler_type handler_;
|
99
|
+
std::uint32_t expected_responses_;
|
100
|
+
bool done_{ false };
|
101
|
+
std::mutex mutex_{};
|
102
|
+
};
|
103
|
+
auto ctx = std::make_shared<replica_context>(std::move(h), config.num_replicas.value_or(0U) + 1U);
|
97
104
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
105
|
+
for (std::size_t idx = 1U; idx <= config.num_replicas.value_or(0U); ++idx) {
|
106
|
+
document_id replica_id{ id };
|
107
|
+
replica_id.node_index(idx);
|
108
|
+
core->execute(impl::lookup_in_replica_request{ std::move(replica_id), specs, timeout, parent_span },
|
109
|
+
[ctx](impl::lookup_in_replica_response&& resp) {
|
110
|
+
handler_type local_handler;
|
111
|
+
{
|
112
|
+
std::scoped_lock lock(ctx->mutex_);
|
113
|
+
if (ctx->done_) {
|
114
|
+
return;
|
115
|
+
}
|
116
|
+
--ctx->expected_responses_;
|
117
|
+
if (resp.ctx.ec()) {
|
118
|
+
if (ctx->expected_responses_ > 0) {
|
119
|
+
// just ignore the response
|
120
|
+
return;
|
121
|
+
}
|
122
|
+
// consider document irretrievable and give up
|
123
|
+
resp.ctx.override_ec(errc::key_value::document_irretrievable);
|
124
|
+
}
|
125
|
+
ctx->done_ = true;
|
126
|
+
std::swap(local_handler, ctx->handler_);
|
127
|
+
}
|
128
|
+
if (local_handler) {
|
129
|
+
response_type res{};
|
130
|
+
res.ctx = resp.ctx;
|
131
|
+
res.cas = resp.cas;
|
132
|
+
res.deleted = resp.deleted;
|
133
|
+
res.is_replica = true;
|
134
|
+
for (auto& field : resp.fields) {
|
135
|
+
auto lookup_in_entry = lookup_in_any_replica_response::entry{};
|
136
|
+
lookup_in_entry.path = field.path;
|
137
|
+
lookup_in_entry.value = field.value;
|
138
|
+
lookup_in_entry.status = field.status;
|
139
|
+
lookup_in_entry.ec = field.ec;
|
140
|
+
lookup_in_entry.exists = field.exists;
|
141
|
+
lookup_in_entry.original_index = field.original_index;
|
142
|
+
lookup_in_entry.opcode = field.opcode;
|
143
|
+
res.fields.emplace_back(lookup_in_entry);
|
144
|
+
}
|
145
|
+
return local_handler(res);
|
146
|
+
}
|
147
|
+
});
|
148
|
+
}
|
149
|
+
core->execute(lookup_in_request{ id, {}, {}, false, specs, timeout }, [ctx](lookup_in_response&& resp) {
|
150
|
+
handler_type local_handler{};
|
151
|
+
{
|
152
|
+
std::scoped_lock lock(ctx->mutex_);
|
153
|
+
if (ctx->done_) {
|
113
154
|
return;
|
114
155
|
}
|
115
|
-
|
116
|
-
resp.ctx.
|
156
|
+
--ctx->expected_responses_;
|
157
|
+
if (resp.ctx.ec()) {
|
158
|
+
if (ctx->expected_responses_ > 0) {
|
159
|
+
// just ignore the response
|
160
|
+
return;
|
161
|
+
}
|
162
|
+
// consider document irretrievable and give up
|
163
|
+
resp.ctx.override_ec(errc::key_value::document_irretrievable);
|
164
|
+
}
|
165
|
+
ctx->done_ = true;
|
166
|
+
std::swap(local_handler, ctx->handler_);
|
117
167
|
}
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
res.fields.emplace_back(lookup_in_entry);
|
168
|
+
if (local_handler) {
|
169
|
+
auto res = response_type{};
|
170
|
+
res.ctx = resp.ctx;
|
171
|
+
res.cas = resp.cas;
|
172
|
+
res.deleted = resp.deleted;
|
173
|
+
res.is_replica = false;
|
174
|
+
for (auto& field : resp.fields) {
|
175
|
+
auto lookup_in_entry = lookup_in_any_replica_response::entry{};
|
176
|
+
lookup_in_entry.path = field.path;
|
177
|
+
lookup_in_entry.value = field.value;
|
178
|
+
lookup_in_entry.status = field.status;
|
179
|
+
lookup_in_entry.ec = field.ec;
|
180
|
+
lookup_in_entry.exists = field.exists;
|
181
|
+
lookup_in_entry.original_index = field.original_index;
|
182
|
+
lookup_in_entry.opcode = field.opcode;
|
183
|
+
res.fields.emplace_back(lookup_in_entry);
|
184
|
+
}
|
185
|
+
return local_handler(res);
|
137
186
|
}
|
138
|
-
|
139
|
-
}
|
187
|
+
});
|
140
188
|
});
|
141
|
-
|
142
|
-
core->execute(lookup_in_request{ id, {}, {}, false, specs, timeout }, [ctx](lookup_in_response&& resp) {
|
143
|
-
handler_type local_handler{};
|
144
|
-
{
|
145
|
-
std::scoped_lock lock(ctx->mutex_);
|
146
|
-
if (ctx->done_) {
|
147
|
-
return;
|
148
|
-
}
|
149
|
-
--ctx->expected_responses_;
|
150
|
-
if (resp.ctx.ec()) {
|
151
|
-
if (ctx->expected_responses_ > 0) {
|
152
|
-
// just ignore the response
|
153
|
-
return;
|
154
|
-
}
|
155
|
-
// consider document irretrievable and give up
|
156
|
-
resp.ctx.override_ec(errc::key_value::document_irretrievable);
|
157
|
-
}
|
158
|
-
ctx->done_ = true;
|
159
|
-
std::swap(local_handler, ctx->handler_);
|
160
|
-
}
|
161
|
-
if (local_handler) {
|
162
|
-
auto res = response_type{};
|
163
|
-
res.ctx = resp.ctx;
|
164
|
-
res.cas = resp.cas;
|
165
|
-
res.deleted = resp.deleted;
|
166
|
-
res.is_replica = false;
|
167
|
-
for (auto& field : resp.fields) {
|
168
|
-
auto lookup_in_entry = lookup_in_any_replica_response::entry{};
|
169
|
-
lookup_in_entry.path = field.path;
|
170
|
-
lookup_in_entry.value = field.value;
|
171
|
-
lookup_in_entry.status = field.status;
|
172
|
-
lookup_in_entry.ec = field.ec;
|
173
|
-
lookup_in_entry.exists = field.exists;
|
174
|
-
lookup_in_entry.original_index = field.original_index;
|
175
|
-
lookup_in_entry.opcode = field.opcode;
|
176
|
-
res.fields.emplace_back(lookup_in_entry);
|
177
|
-
}
|
178
|
-
return local_handler(res);
|
179
|
-
}
|
180
|
-
});
|
181
|
-
});
|
189
|
+
});
|
182
190
|
}
|
183
191
|
};
|
184
192
|
|
@@ -133,10 +133,10 @@ search_request::encode_to(search_request::encoded_request_type& encoded, http_co
|
|
133
133
|
encoded.method = "POST";
|
134
134
|
body_str = utils::json::generate(body);
|
135
135
|
encoded.body = body_str;
|
136
|
-
if (context.options.show_queries) {
|
137
|
-
CB_LOG_INFO("SEARCH: {}", utils::json::generate(body
|
136
|
+
if (context.options.show_queries || (log_request.has_value() && log_request.value())) {
|
137
|
+
CB_LOG_INFO("SEARCH: {}", utils::json::generate(body));
|
138
138
|
} else {
|
139
|
-
CB_LOG_DEBUG("SEARCH: {}", utils::json::generate(body
|
139
|
+
CB_LOG_DEBUG("SEARCH: {}", utils::json::generate(body));
|
140
140
|
}
|
141
141
|
if (row_callback) {
|
142
142
|
encoded.streaming.emplace(couchbase::core::io::streaming_settings{
|
@@ -165,6 +165,9 @@ search_request::make_response(error_context::search&& ctx, const encoded_respons
|
|
165
165
|
response.ctx.ec = errc::common::parsing_failure;
|
166
166
|
return response;
|
167
167
|
}
|
168
|
+
if (log_response.has_value() && log_response.value()) {
|
169
|
+
CB_LOG_INFO("SEARCH RESPONSE: {}", utils::json::generate(payload));
|
170
|
+
}
|
168
171
|
response.meta.metrics.took = std::chrono::nanoseconds(payload.at("took").get_unsigned());
|
169
172
|
response.meta.metrics.max_score = payload.at("max_score").as<double>();
|
170
173
|
response.meta.metrics.total_rows = payload.at("total_hits").get_unsigned();
|
@@ -187,106 +190,119 @@ search_request::make_response(error_context::search&& ctx, const encoded_respons
|
|
187
190
|
return response;
|
188
191
|
}
|
189
192
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
for (const auto& [
|
199
|
-
for (const auto&
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
193
|
+
try {
|
194
|
+
if (const auto* rows = payload.find("hits"); rows != nullptr && rows->is_array()) {
|
195
|
+
for (const auto& entry : rows->get_array()) {
|
196
|
+
search_response::search_row row{};
|
197
|
+
row.index = entry.optional<std::string>("index").value_or(std::string());
|
198
|
+
row.id = entry.optional<std::string>("id").value_or(std::string());
|
199
|
+
row.score = entry.optional<double>("score").value_or(0);
|
200
|
+
if (const auto* locations_map = entry.find("locations"); locations_map != nullptr && locations_map->is_object()) {
|
201
|
+
for (const auto& [field, terms] : locations_map->get_object()) {
|
202
|
+
for (const auto& [term, locations] : terms.get_object()) {
|
203
|
+
for (const auto& loc : locations.get_array()) {
|
204
|
+
search_response::search_location location{};
|
205
|
+
location.field = field;
|
206
|
+
location.term = term;
|
207
|
+
location.position = loc.at("pos").get_unsigned();
|
208
|
+
location.start_offset = loc.at("start").get_unsigned();
|
209
|
+
location.end_offset = loc.at("end").get_unsigned();
|
210
|
+
if (const auto* array_positions = loc.find("array_positions");
|
211
|
+
array_positions != nullptr && array_positions->is_array()) {
|
212
|
+
location.array_positions.emplace(array_positions->as<std::vector<std::uint64_t>>());
|
213
|
+
}
|
214
|
+
row.locations.emplace_back(location);
|
209
215
|
}
|
210
|
-
row.locations.emplace_back(location);
|
211
216
|
}
|
212
217
|
}
|
213
218
|
}
|
214
|
-
}
|
215
219
|
|
216
|
-
|
217
|
-
|
218
|
-
|
220
|
+
if (const auto* fragments_map = entry.find("fragments"); fragments_map != nullptr && fragments_map->is_object()) {
|
221
|
+
for (const auto& [field, fragments] : fragments_map->get_object()) {
|
222
|
+
row.fragments.try_emplace(field, fragments.as<std::vector<std::string>>());
|
223
|
+
}
|
219
224
|
}
|
225
|
+
if (const auto* response_fields = entry.find("fields");
|
226
|
+
response_fields != nullptr && response_fields->is_object()) {
|
227
|
+
row.fields = utils::json::generate(*response_fields);
|
228
|
+
}
|
229
|
+
if (const auto* explanation = entry.find("explanation"); explanation != nullptr && explanation->is_object()) {
|
230
|
+
row.explanation = utils::json::generate(*explanation);
|
231
|
+
}
|
232
|
+
response.rows.emplace_back(row);
|
220
233
|
}
|
221
|
-
if (const auto* response_fields = entry.find("fields"); response_fields != nullptr && response_fields->is_object()) {
|
222
|
-
row.fields = utils::json::generate(*response_fields);
|
223
|
-
}
|
224
|
-
if (const auto* explanation = entry.find("explanation"); explanation != nullptr && explanation->is_object()) {
|
225
|
-
row.explanation = utils::json::generate(*explanation);
|
226
|
-
}
|
227
|
-
response.rows.emplace_back(row);
|
228
234
|
}
|
235
|
+
} catch (const std::out_of_range& e) {
|
236
|
+
CB_LOG_ERROR("Error parsing search results. Error: {}.", e.what());
|
237
|
+
response.ctx.ec = errc::common::parsing_failure;
|
238
|
+
return response;
|
229
239
|
}
|
230
240
|
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
241
|
+
try {
|
242
|
+
if (const auto* response_facets = payload.find("facets"); response_facets != nullptr && response_facets->is_object()) {
|
243
|
+
for (const auto& [name, object] : response_facets->get_object()) {
|
244
|
+
search_response::search_facet facet;
|
245
|
+
facet.name = name;
|
246
|
+
facet.field = object.at("field").get_string();
|
247
|
+
facet.total = object.at("total").get_unsigned();
|
248
|
+
facet.missing = object.at("missing").get_unsigned();
|
249
|
+
facet.other = object.at("other").get_unsigned();
|
239
250
|
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
251
|
+
if (const auto* date_ranges = object.find("date_ranges"); date_ranges != nullptr && date_ranges->is_array()) {
|
252
|
+
for (const auto& date_range : date_ranges->get_array()) {
|
253
|
+
search_response::search_facet::date_range_facet date_range_facet;
|
254
|
+
date_range_facet.name = date_range.at("name").get_string();
|
255
|
+
date_range_facet.count = date_range.at("count").get_unsigned();
|
256
|
+
if (const auto* start = date_range.find("start"); start != nullptr && start->is_string()) {
|
257
|
+
date_range_facet.start = start->get_string();
|
258
|
+
}
|
259
|
+
if (const auto* end = date_range.find("end"); end != nullptr && end->is_string()) {
|
260
|
+
date_range_facet.end = end->get_string();
|
261
|
+
}
|
262
|
+
facet.date_ranges.emplace_back(date_range_facet);
|
250
263
|
}
|
251
|
-
facet.date_ranges.emplace_back(date_range_facet);
|
252
264
|
}
|
253
|
-
}
|
254
265
|
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
+
if (const auto& numeric_ranges = object.find("numeric_ranges");
|
267
|
+
numeric_ranges != nullptr && numeric_ranges->is_array()) {
|
268
|
+
for (const auto& numeric_range : numeric_ranges->get_array()) {
|
269
|
+
search_response::search_facet::numeric_range_facet numeric_range_facet;
|
270
|
+
numeric_range_facet.name = numeric_range.at("name").get_string();
|
271
|
+
numeric_range_facet.count = numeric_range.at("count").get_unsigned();
|
272
|
+
if (const auto* min = numeric_range.find("min"); min != nullptr) {
|
273
|
+
if (min->is_double()) {
|
274
|
+
numeric_range_facet.min = min->as<double>();
|
275
|
+
} else if (min->is_integer()) {
|
276
|
+
numeric_range_facet.min = min->get_unsigned();
|
277
|
+
}
|
266
278
|
}
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
279
|
+
if (const auto* max = numeric_range.find("max"); max != nullptr) {
|
280
|
+
if (max->is_double()) {
|
281
|
+
numeric_range_facet.max = max->as<double>();
|
282
|
+
} else if (max->is_integer()) {
|
283
|
+
numeric_range_facet.max = max->get_unsigned();
|
284
|
+
}
|
273
285
|
}
|
286
|
+
facet.numeric_ranges.emplace_back(numeric_range_facet);
|
274
287
|
}
|
275
|
-
facet.numeric_ranges.emplace_back(numeric_range_facet);
|
276
288
|
}
|
277
|
-
}
|
278
289
|
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
290
|
+
if (const auto* terms = object.find("terms"); terms != nullptr && terms->is_array()) {
|
291
|
+
for (const auto& term : terms->get_array()) {
|
292
|
+
search_response::search_facet::term_facet term_facet;
|
293
|
+
term_facet.term = term.at("term").get_string();
|
294
|
+
term_facet.count = term.at("count").get_unsigned();
|
295
|
+
facet.terms.emplace_back(term_facet);
|
296
|
+
}
|
285
297
|
}
|
286
|
-
}
|
287
298
|
|
288
|
-
|
299
|
+
response.facets.emplace_back(facet);
|
300
|
+
}
|
289
301
|
}
|
302
|
+
} catch (const std::out_of_range& e) {
|
303
|
+
CB_LOG_ERROR("Error parsing search facets. Error: {}.", e.what());
|
304
|
+
response.ctx.ec = errc::common::parsing_failure;
|
305
|
+
return response;
|
290
306
|
}
|
291
307
|
return response;
|
292
308
|
}
|
@@ -155,6 +155,11 @@ struct search_request {
|
|
155
155
|
std::optional<std::function<utils::json::stream_control(std::string)>> row_callback{};
|
156
156
|
std::optional<std::string> client_context_id{};
|
157
157
|
std::optional<std::chrono::milliseconds> timeout{};
|
158
|
+
/**
|
159
|
+
* UNCOMMITTED: If set to true, will log the request to and/or the response from the search service.
|
160
|
+
*/
|
161
|
+
std::optional<bool> log_request{ false };
|
162
|
+
std::optional<bool> log_response{ false };
|
158
163
|
|
159
164
|
[[nodiscard]] std::error_code encode_to(encoded_request_type& encoded, http_context& context);
|
160
165
|
|
@@ -18,6 +18,7 @@
|
|
18
18
|
#include "range_scan_options.hxx"
|
19
19
|
#include "timeout_defaults.hxx"
|
20
20
|
|
21
|
+
#include <couchbase/best_effort_retry_strategy.hxx>
|
21
22
|
#include <couchbase/mutation_token.hxx>
|
22
23
|
#include <couchbase/retry_strategy.hxx>
|
23
24
|
|
@@ -51,7 +52,7 @@ struct range_scan_orchestrator_options {
|
|
51
52
|
std::uint32_t batch_byte_limit{ range_scan_continue_options::default_batch_byte_limit };
|
52
53
|
std::uint16_t concurrency{ default_concurrency };
|
53
54
|
|
54
|
-
std::shared_ptr<couchbase::retry_strategy> retry_strategy{
|
55
|
+
std::shared_ptr<couchbase::retry_strategy> retry_strategy{ make_best_effort_retry_strategy() };
|
55
56
|
std::chrono::milliseconds timeout{ timeout_defaults::key_value_scan_timeout };
|
56
57
|
std::shared_ptr<couchbase::tracing::request_span> parent_span{};
|
57
58
|
};
|
@@ -131,12 +131,13 @@ atr_cleanup_entry::check_atr_and_cleanup(transactions_cleanup_attempt* result)
|
|
131
131
|
throw *err;
|
132
132
|
}
|
133
133
|
cleanup_docs(durability_level);
|
134
|
-
auto ec =
|
134
|
+
auto ec =
|
135
|
+
wait_for_hook([this](auto handler) { return cleanup_->config().cleanup_hooks->on_cleanup_docs_completed(std::move(handler)); });
|
135
136
|
if (ec) {
|
136
137
|
throw client_error(*ec, "on_cleanup_docs_completed hook threw error");
|
137
138
|
}
|
138
139
|
cleanup_entry(durability_level);
|
139
|
-
ec = cleanup_->config().cleanup_hooks->on_cleanup_completed();
|
140
|
+
ec = wait_for_hook([this](auto handler) { return cleanup_->config().cleanup_hooks->on_cleanup_completed(std::move(handler)); });
|
140
141
|
if (ec) {
|
141
142
|
throw client_error(*ec, "on_cleanup_completed hook threw error");
|
142
143
|
}
|
@@ -246,7 +247,9 @@ atr_cleanup_entry::commit_docs(std::optional<std::vector<doc_record>> docs, dura
|
|
246
247
|
do_per_doc(*docs, true, [&](transaction_get_result& doc, bool) {
|
247
248
|
if (doc.links().has_staged_content()) {
|
248
249
|
auto content = doc.links().staged_content();
|
249
|
-
auto ec =
|
250
|
+
auto ec = wait_for_hook([this, key = doc.id().key()](auto handler) {
|
251
|
+
return cleanup_->config().cleanup_hooks->before_commit_doc(key, std::move(handler));
|
252
|
+
});
|
250
253
|
if (ec) {
|
251
254
|
throw client_error(*ec, "before_commit_doc hook threw error");
|
252
255
|
}
|
@@ -288,7 +291,9 @@ atr_cleanup_entry::remove_docs(std::optional<std::vector<doc_record>> docs, dura
|
|
288
291
|
{
|
289
292
|
if (docs) {
|
290
293
|
do_per_doc(*docs, true, [&](transaction_get_result& doc, bool is_deleted) {
|
291
|
-
auto ec =
|
294
|
+
auto ec = wait_for_hook([this, key = doc.id().key()](auto handler) mutable {
|
295
|
+
return cleanup_->config().cleanup_hooks->before_remove_doc(key, std::move(handler));
|
296
|
+
});
|
292
297
|
if (ec) {
|
293
298
|
throw client_error(*ec, "before_remove_doc hook threw error");
|
294
299
|
}
|
@@ -330,7 +335,9 @@ atr_cleanup_entry::remove_docs_staged_for_removal(std::optional<std::vector<doc_
|
|
330
335
|
if (docs) {
|
331
336
|
do_per_doc(*docs, true, [&](transaction_get_result& doc, bool) {
|
332
337
|
if (doc.links().is_document_being_removed()) {
|
333
|
-
auto ec =
|
338
|
+
auto ec = wait_for_hook([this, key = doc.id().key()](auto handler) mutable {
|
339
|
+
return cleanup_->config().cleanup_hooks->before_remove_doc_staged_for_removal(key, std::move(handler));
|
340
|
+
});
|
334
341
|
if (ec) {
|
335
342
|
throw client_error(*ec, "before_remove_doc_staged_for_removal hook threw error");
|
336
343
|
}
|
@@ -358,7 +365,9 @@ atr_cleanup_entry::remove_txn_links(std::optional<std::vector<doc_record>> docs,
|
|
358
365
|
{
|
359
366
|
if (docs) {
|
360
367
|
do_per_doc(*docs, false, [&](transaction_get_result& doc, bool) {
|
361
|
-
auto ec =
|
368
|
+
auto ec = wait_for_hook([this, key = doc.id().key()](auto handler) mutable {
|
369
|
+
return cleanup_->config().cleanup_hooks->before_remove_links(key, std::move(handler));
|
370
|
+
});
|
362
371
|
if (ec) {
|
363
372
|
throw client_error(*ec, "before_remove_links hook threw error");
|
364
373
|
}
|
@@ -385,7 +394,7 @@ void
|
|
385
394
|
atr_cleanup_entry::cleanup_entry(durability_level dl)
|
386
395
|
{
|
387
396
|
try {
|
388
|
-
auto ec = cleanup_->config().cleanup_hooks->before_atr_remove();
|
397
|
+
auto ec = wait_for_hook([this](auto handler) { return cleanup_->config().cleanup_hooks->before_atr_remove(std::move(handler)); });
|
389
398
|
if (ec) {
|
390
399
|
throw client_error(*ec, "before_atr_remove hook threw error");
|
391
400
|
}
|