couchbase 4.2.9 → 4.2.10
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-client/CMakeLists.txt +4 -0
- package/deps/couchbase-cxx-client/cmake/CompilerWarnings.cmake +7 -3
- package/deps/couchbase-cxx-client/cmake/OpenSSL.cmake +1 -0
- package/deps/couchbase-cxx-client/core/bucket.cxx +52 -2
- package/deps/couchbase-cxx-client/core/bucket.hxx +1 -1
- package/deps/couchbase-cxx-client/core/cluster.cxx +38 -0
- package/deps/couchbase-cxx-client/core/impl/bucket.cxx +24 -0
- package/deps/couchbase-cxx-client/core/impl/cluster.cxx +73 -0
- package/deps/couchbase-cxx-client/core/impl/diagnostics.cxx +294 -0
- package/deps/couchbase-cxx-client/core/impl/diagnostics.hxx +39 -0
- package/deps/couchbase-cxx-client/core/impl/scope.cxx +19 -4
- package/deps/couchbase-cxx-client/core/impl/search.cxx +75 -2
- package/deps/couchbase-cxx-client/core/impl/search.hxx +8 -0
- package/deps/couchbase-cxx-client/core/impl/search_index_manager.cxx +261 -18
- package/deps/couchbase-cxx-client/core/impl/search_request.cxx +139 -0
- package/deps/couchbase-cxx-client/core/impl/vector_query.cxx +42 -0
- package/deps/couchbase-cxx-client/core/impl/vector_search.cxx +40 -0
- package/deps/couchbase-cxx-client/core/io/http_session.hxx +6 -3
- package/deps/couchbase-cxx-client/core/io/mcbp_session.cxx +24 -32
- package/deps/couchbase-cxx-client/core/io/mcbp_session.hxx +1 -0
- package/deps/couchbase-cxx-client/core/logger/logger.cxx +1 -1
- package/deps/couchbase-cxx-client/core/meta/features.hxx +10 -0
- package/deps/couchbase-cxx-client/core/operations/document_query.cxx +6 -1
- package/deps/couchbase-cxx-client/core/operations/document_search.cxx +37 -1
- package/deps/couchbase-cxx-client/core/operations/document_search.hxx +11 -0
- package/deps/couchbase-cxx-client/core/operations/management/collection_create.cxx +7 -6
- package/deps/couchbase-cxx-client/core/operations/management/collection_create.hxx +1 -1
- package/deps/couchbase-cxx-client/core/operations/management/collection_update.cxx +7 -8
- package/deps/couchbase-cxx-client/core/operations/management/collection_update.hxx +1 -1
- package/deps/couchbase-cxx-client/core/operations/management/error_utils.cxx +3 -0
- package/deps/couchbase-cxx-client/core/operations/management/search_index_analyze_document.cxx +17 -1
- package/deps/couchbase-cxx-client/core/operations/management/search_index_analyze_document.hxx +3 -0
- package/deps/couchbase-cxx-client/core/operations/management/search_index_control_ingest.cxx +21 -1
- package/deps/couchbase-cxx-client/core/operations/management/search_index_control_ingest.hxx +3 -0
- package/deps/couchbase-cxx-client/core/operations/management/search_index_control_plan_freeze.cxx +21 -1
- package/deps/couchbase-cxx-client/core/operations/management/search_index_control_plan_freeze.hxx +3 -0
- package/deps/couchbase-cxx-client/core/operations/management/search_index_control_query.cxx +21 -1
- package/deps/couchbase-cxx-client/core/operations/management/search_index_control_query.hxx +3 -0
- package/deps/couchbase-cxx-client/core/operations/management/search_index_drop.cxx +17 -1
- package/deps/couchbase-cxx-client/core/operations/management/search_index_drop.hxx +3 -0
- package/deps/couchbase-cxx-client/core/operations/management/search_index_get.cxx +17 -1
- package/deps/couchbase-cxx-client/core/operations/management/search_index_get.hxx +2 -0
- package/deps/couchbase-cxx-client/core/operations/management/search_index_get_all.cxx +39 -22
- package/deps/couchbase-cxx-client/core/operations/management/search_index_get_all.hxx +3 -0
- package/deps/couchbase-cxx-client/core/operations/management/search_index_get_documents_count.cxx +18 -1
- package/deps/couchbase-cxx-client/core/operations/management/search_index_get_documents_count.hxx +3 -0
- package/deps/couchbase-cxx-client/core/operations/management/search_index_upsert.cxx +17 -1
- package/deps/couchbase-cxx-client/core/operations/management/search_index_upsert.hxx +3 -0
- package/deps/couchbase-cxx-client/core/topology/collections_manifest.hxx +1 -1
- package/deps/couchbase-cxx-client/core/topology/collections_manifest_json.hxx +1 -1
- package/deps/couchbase-cxx-client/core/transactions/internal/utils.hxx +4 -0
- package/deps/couchbase-cxx-client/core/vector_query_combination.hxx +23 -0
- package/deps/couchbase-cxx-client/couchbase/bucket.hxx +29 -0
- package/deps/couchbase-cxx-client/couchbase/cluster.hxx +110 -0
- package/deps/couchbase-cxx-client/couchbase/codec/json_transcoder.hxx +1 -1
- package/deps/couchbase-cxx-client/couchbase/codec/raw_binary_transcoder.hxx +2 -1
- package/deps/couchbase-cxx-client/couchbase/codec/raw_json_transcoder.hxx +78 -0
- package/deps/couchbase-cxx-client/couchbase/codec/raw_string_transcoder.hxx +72 -0
- package/deps/couchbase-cxx-client/couchbase/create_collection_options.hxx +29 -1
- package/deps/couchbase-cxx-client/couchbase/diagnostics_options.hxx +75 -0
- package/deps/couchbase-cxx-client/couchbase/diagnostics_result.hxx +124 -0
- package/deps/couchbase-cxx-client/couchbase/endpoint_diagnostics.hxx +206 -0
- package/deps/couchbase-cxx-client/couchbase/endpoint_ping_report.hxx +205 -0
- package/deps/couchbase-cxx-client/couchbase/get_options.hxx +1 -6
- package/deps/couchbase-cxx-client/couchbase/management/collection_spec.hxx +1 -1
- package/deps/couchbase-cxx-client/couchbase/ping_options.hxx +93 -0
- package/deps/couchbase-cxx-client/couchbase/ping_result.hxx +118 -0
- package/deps/couchbase-cxx-client/couchbase/scope.hxx +24 -8
- package/deps/couchbase-cxx-client/couchbase/scope_search_index_manager.hxx +291 -0
- package/deps/couchbase-cxx-client/couchbase/search_request.hxx +120 -0
- package/deps/couchbase-cxx-client/couchbase/service_type.hxx +58 -0
- package/deps/couchbase-cxx-client/couchbase/update_collection_options.hxx +32 -3
- package/deps/couchbase-cxx-client/couchbase/vector_query.hxx +99 -0
- package/deps/couchbase-cxx-client/couchbase/vector_search.hxx +85 -0
- package/deps/couchbase-cxx-client/couchbase/vector_search_options.hxx +76 -0
- package/dist/binding.d.ts +9 -0
- package/dist/binding.js +4 -1
- package/dist/bindingutilities.d.ts +6 -1
- package/dist/bindingutilities.js +15 -1
- package/dist/cluster.d.ts +12 -1
- package/dist/cluster.js +22 -0
- package/dist/couchbase.d.ts +1 -0
- package/dist/couchbase.js +1 -0
- package/dist/searchexecutor.d.ts +2 -2
- package/dist/searchexecutor.js +19 -3
- package/dist/searchtypes.d.ts +46 -0
- package/dist/searchtypes.js +81 -1
- package/dist/vectorsearch.d.ts +99 -0
- package/dist/vectorsearch.js +132 -0
- package/package.json +7 -7
- package/src/constants.cpp +11 -0
- package/src/jstocbpp_autogen.hpp +24 -7
- package/tools/gen-bindings-json.py +2 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
2
|
+
/*
|
|
3
|
+
* Copyright 2023-Present 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
|
+
#include "core/impl/encoded_search_query.hxx"
|
|
19
|
+
|
|
20
|
+
#include <couchbase/search_request.hxx>
|
|
21
|
+
|
|
22
|
+
namespace couchbase
|
|
23
|
+
{
|
|
24
|
+
class search_request_impl
|
|
25
|
+
{
|
|
26
|
+
public:
|
|
27
|
+
explicit search_request_impl(std::optional<encoded_search_query> search_query,
|
|
28
|
+
std::optional<encoded_search_query> vector_search,
|
|
29
|
+
std::optional<vector_search_options::built> options)
|
|
30
|
+
: search_query_(std::move(search_query))
|
|
31
|
+
, vector_search_(std::move(vector_search))
|
|
32
|
+
, vector_search_options_(std::move(options))
|
|
33
|
+
{
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
static search_request_impl create(const search_query& query)
|
|
37
|
+
{
|
|
38
|
+
auto encoded = query.encode();
|
|
39
|
+
if (encoded.ec) {
|
|
40
|
+
throw std::system_error(encoded.ec, "unable to encode the search_query");
|
|
41
|
+
}
|
|
42
|
+
return search_request_impl(encoded, {}, {});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
static search_request_impl create(const vector_search& search)
|
|
46
|
+
{
|
|
47
|
+
auto encoded = search.encode();
|
|
48
|
+
if (encoded.ec) {
|
|
49
|
+
throw std::system_error(encoded.ec, "unable to encode the vector_search");
|
|
50
|
+
}
|
|
51
|
+
return search_request_impl({}, encoded, search.options());
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
void search_query(const couchbase::search_query& query)
|
|
55
|
+
{
|
|
56
|
+
search_query_ = query.encode();
|
|
57
|
+
if (search_query_.value().ec) {
|
|
58
|
+
throw std::system_error(search_query_.value().ec, "unable to encode the search_query");
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
void vector_search(const couchbase::vector_search& search)
|
|
63
|
+
{
|
|
64
|
+
vector_search_ = search.encode();
|
|
65
|
+
if (vector_search_.value().ec) {
|
|
66
|
+
throw std::system_error(vector_search_.value().ec, "unable to encode the vector_search");
|
|
67
|
+
}
|
|
68
|
+
vector_search_options_ = search.options();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
[[nodiscard]] std::optional<encoded_search_query> search_query() const
|
|
72
|
+
{
|
|
73
|
+
return search_query_;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
[[nodiscard]] std::optional<encoded_search_query> vector_search() const
|
|
77
|
+
{
|
|
78
|
+
return vector_search_;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
[[nodiscard]] std::optional<vector_search_options::built> vector_options() const
|
|
82
|
+
{
|
|
83
|
+
return vector_search_options_;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
private:
|
|
87
|
+
std::optional<encoded_search_query> search_query_;
|
|
88
|
+
std::optional<encoded_search_query> vector_search_;
|
|
89
|
+
std::optional<vector_search_options::built> vector_search_options_;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
search_request::search_request(const couchbase::search_query& query)
|
|
93
|
+
: impl_{ std::make_shared<search_request_impl>(search_request_impl::create(query)) }
|
|
94
|
+
{
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
search_request::search_request(const couchbase::vector_search& search)
|
|
98
|
+
: impl_{ std::make_shared<search_request_impl>(search_request_impl::create(search)) }
|
|
99
|
+
{
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
auto
|
|
103
|
+
search_request::search_query(const couchbase::search_query& search_query) -> search_request&
|
|
104
|
+
{
|
|
105
|
+
if (impl_->search_query().has_value()) {
|
|
106
|
+
throw std::invalid_argument("There can only be one search_query in a search request");
|
|
107
|
+
}
|
|
108
|
+
impl_->search_query(search_query);
|
|
109
|
+
return *this;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
auto
|
|
113
|
+
search_request::vector_search(const couchbase::vector_search& vector_search) -> search_request&
|
|
114
|
+
{
|
|
115
|
+
if (impl_->vector_search().has_value()) {
|
|
116
|
+
throw std::invalid_argument("There can only be one vector_search in a search request");
|
|
117
|
+
}
|
|
118
|
+
impl_->vector_search(vector_search);
|
|
119
|
+
return *this;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
[[nodiscard]] std::optional<encoded_search_query>
|
|
123
|
+
search_request::search_query() const
|
|
124
|
+
{
|
|
125
|
+
return impl_->search_query();
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
[[nodiscard]] std::optional<encoded_search_query>
|
|
129
|
+
search_request::vector_search() const
|
|
130
|
+
{
|
|
131
|
+
return impl_->vector_search();
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
[[nodiscard]] std::optional<couchbase::vector_search_options::built>
|
|
135
|
+
search_request::vector_options()
|
|
136
|
+
{
|
|
137
|
+
return impl_->vector_options();
|
|
138
|
+
}
|
|
139
|
+
} // namespace couchbase
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
2
|
+
/*
|
|
3
|
+
* Copyright 2023-Present 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
|
+
#include "encoded_search_query.hxx"
|
|
19
|
+
|
|
20
|
+
#include <couchbase/vector_query.hxx>
|
|
21
|
+
|
|
22
|
+
namespace couchbase
|
|
23
|
+
{
|
|
24
|
+
auto
|
|
25
|
+
vector_query::encode() const -> encoded_search_query
|
|
26
|
+
{
|
|
27
|
+
encoded_search_query built;
|
|
28
|
+
built.query = tao::json::empty_object;
|
|
29
|
+
if (boost_) {
|
|
30
|
+
built.query["boost"] = boost_.value();
|
|
31
|
+
}
|
|
32
|
+
built.query["field"] = vector_field_name_;
|
|
33
|
+
|
|
34
|
+
tao::json::value vector_values = tao::json::empty_array;
|
|
35
|
+
for (const auto value : vector_query_) {
|
|
36
|
+
vector_values.push_back(value);
|
|
37
|
+
}
|
|
38
|
+
built.query["vector"] = vector_values;
|
|
39
|
+
built.query["k"] = num_candidates_;
|
|
40
|
+
return built;
|
|
41
|
+
}
|
|
42
|
+
} // namespace couchbase
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
2
|
+
/*
|
|
3
|
+
* Copyright 2023-Present 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
|
+
#include "encoded_search_query.hxx"
|
|
19
|
+
|
|
20
|
+
#include <couchbase/vector_search.hxx>
|
|
21
|
+
|
|
22
|
+
namespace couchbase
|
|
23
|
+
{
|
|
24
|
+
auto
|
|
25
|
+
vector_search::encode() const -> encoded_search_query
|
|
26
|
+
{
|
|
27
|
+
encoded_search_query built;
|
|
28
|
+
|
|
29
|
+
built.query = tao::json::empty_array;
|
|
30
|
+
|
|
31
|
+
for (const auto& query : vector_queries_) {
|
|
32
|
+
auto encoded = query.encode();
|
|
33
|
+
if (encoded.ec) {
|
|
34
|
+
return { encoded.ec };
|
|
35
|
+
}
|
|
36
|
+
built.query.push_back(encoded.query);
|
|
37
|
+
}
|
|
38
|
+
return built;
|
|
39
|
+
}
|
|
40
|
+
} // namespace couchbase
|
|
@@ -370,11 +370,12 @@ class http_session : public std::enable_shared_from_this<http_session>
|
|
|
370
370
|
return;
|
|
371
371
|
}
|
|
372
372
|
if (ec) {
|
|
373
|
-
CB_LOG_ERROR("{} error on resolve: {}", info_.log_prefix(), ec.message());
|
|
373
|
+
CB_LOG_ERROR("{} error on resolve \"{}:{}\": {}", info_.log_prefix(), hostname_, service_, ec.message());
|
|
374
374
|
return;
|
|
375
375
|
}
|
|
376
376
|
last_active_ = std::chrono::steady_clock::now();
|
|
377
377
|
endpoints_ = endpoints;
|
|
378
|
+
CB_LOG_TRACE("{} resolved \"{}:{}\" to {} endpoint(s)", info_.log_prefix(), hostname_, service_, endpoints_.size());
|
|
378
379
|
do_connect(endpoints_.begin());
|
|
379
380
|
deadline_timer_.async_wait(std::bind(&http_session::check_deadline, shared_from_this(), std::placeholders::_1));
|
|
380
381
|
}
|
|
@@ -385,15 +386,17 @@ class http_session : public std::enable_shared_from_this<http_session>
|
|
|
385
386
|
return;
|
|
386
387
|
}
|
|
387
388
|
if (it != endpoints_.end()) {
|
|
388
|
-
CB_LOG_DEBUG("{} connecting to {}:{}, timeout={}ms",
|
|
389
|
+
CB_LOG_DEBUG("{} connecting to {}:{} (\"{}:{}\"), timeout={}ms",
|
|
389
390
|
info_.log_prefix(),
|
|
390
391
|
it->endpoint().address().to_string(),
|
|
391
392
|
it->endpoint().port(),
|
|
393
|
+
hostname_,
|
|
394
|
+
service_,
|
|
392
395
|
http_ctx_.options.connect_timeout.count());
|
|
393
396
|
deadline_timer_.expires_after(http_ctx_.options.connect_timeout);
|
|
394
397
|
stream_->async_connect(it->endpoint(), std::bind(&http_session::on_connect, shared_from_this(), std::placeholders::_1, it));
|
|
395
398
|
} else {
|
|
396
|
-
CB_LOG_ERROR("{} no more endpoints left to connect", info_.log_prefix());
|
|
399
|
+
CB_LOG_ERROR("{} no more endpoints left to connect, \"{}:{}\" is not reachable", info_.log_prefix(), hostname_, service_);
|
|
397
400
|
stop();
|
|
398
401
|
}
|
|
399
402
|
}
|
|
@@ -542,17 +542,11 @@ class mcbp_session_impl
|
|
|
542
542
|
{
|
|
543
543
|
private:
|
|
544
544
|
std::shared_ptr<mcbp_session_impl> session_;
|
|
545
|
-
asio::steady_timer heartbeat_timer_;
|
|
546
|
-
std::chrono::milliseconds heartbeat_interval_;
|
|
547
545
|
std::atomic_bool stopped_{ false };
|
|
548
546
|
|
|
549
547
|
public:
|
|
550
548
|
explicit message_handler(std::shared_ptr<mcbp_session_impl> session)
|
|
551
549
|
: session_(std::move(session))
|
|
552
|
-
, heartbeat_timer_(session_->ctx_)
|
|
553
|
-
, heartbeat_interval_{ session_->origin_.options().config_poll_floor > session_->origin_.options().config_poll_interval
|
|
554
|
-
? session_->origin_.options().config_poll_floor
|
|
555
|
-
: session_->origin_.options().config_poll_interval }
|
|
556
550
|
{
|
|
557
551
|
}
|
|
558
552
|
|
|
@@ -563,16 +557,10 @@ class mcbp_session_impl
|
|
|
563
557
|
|
|
564
558
|
void start()
|
|
565
559
|
{
|
|
566
|
-
if (session_->supports_gcccp_) {
|
|
567
|
-
fetch_config({});
|
|
568
|
-
}
|
|
569
560
|
}
|
|
570
561
|
|
|
571
562
|
void stop()
|
|
572
563
|
{
|
|
573
|
-
if (bool expected_state{ false }; stopped_.compare_exchange_strong(expected_state, true)) {
|
|
574
|
-
heartbeat_timer_.cancel();
|
|
575
|
-
}
|
|
576
564
|
}
|
|
577
565
|
|
|
578
566
|
void handle(mcbp_message&& msg)
|
|
@@ -709,23 +697,6 @@ class mcbp_session_impl
|
|
|
709
697
|
break;
|
|
710
698
|
}
|
|
711
699
|
}
|
|
712
|
-
|
|
713
|
-
void fetch_config(std::error_code ec)
|
|
714
|
-
{
|
|
715
|
-
if (ec == asio::error::operation_aborted || stopped_ || !session_) {
|
|
716
|
-
return;
|
|
717
|
-
}
|
|
718
|
-
protocol::client_request<protocol::get_cluster_config_request_body> req;
|
|
719
|
-
req.opaque(session_->next_opaque());
|
|
720
|
-
session_->write_and_flush(req.data());
|
|
721
|
-
heartbeat_timer_.expires_after(heartbeat_interval_);
|
|
722
|
-
heartbeat_timer_.async_wait([self = shared_from_this()](std::error_code e) {
|
|
723
|
-
if (e == asio::error::operation_aborted) {
|
|
724
|
-
return;
|
|
725
|
-
}
|
|
726
|
-
self->fetch_config(e);
|
|
727
|
-
});
|
|
728
|
-
}
|
|
729
700
|
};
|
|
730
701
|
|
|
731
702
|
public:
|
|
@@ -1400,6 +1371,7 @@ class mcbp_session_impl
|
|
|
1400
1371
|
return initiate_bootstrap();
|
|
1401
1372
|
}
|
|
1402
1373
|
endpoints_ = endpoints;
|
|
1374
|
+
CB_LOG_TRACE("{} resolved \"{}:{}\" to {} endpoint(s)", log_prefix_, bootstrap_hostname_, bootstrap_port_, endpoints_.size());
|
|
1403
1375
|
do_connect(endpoints_.begin());
|
|
1404
1376
|
connection_deadline_.expires_after(origin_.options().resolve_timeout);
|
|
1405
1377
|
connection_deadline_.async_wait([self = shared_from_this()](const auto timer_ec) {
|
|
@@ -1419,19 +1391,33 @@ class mcbp_session_impl
|
|
|
1419
1391
|
if (it != endpoints_.end()) {
|
|
1420
1392
|
auto hostname = it->endpoint().address().to_string();
|
|
1421
1393
|
auto port = it->endpoint().port();
|
|
1422
|
-
CB_LOG_DEBUG("{} connecting to {}:{}, timeout={}ms",
|
|
1394
|
+
CB_LOG_DEBUG("{} connecting to {}:{} (\"{}:{}\"), timeout={}ms",
|
|
1395
|
+
log_prefix_,
|
|
1396
|
+
hostname,
|
|
1397
|
+
port,
|
|
1398
|
+
bootstrap_hostname_,
|
|
1399
|
+
bootstrap_port_,
|
|
1400
|
+
origin_.options().connect_timeout.count());
|
|
1423
1401
|
connection_deadline_.expires_after(origin_.options().connect_timeout);
|
|
1424
1402
|
connection_deadline_.async_wait([self = shared_from_this(), hostname, port](const auto timer_ec) {
|
|
1425
1403
|
if (timer_ec == asio::error::operation_aborted || self->stopped_) {
|
|
1426
1404
|
return;
|
|
1427
1405
|
}
|
|
1428
|
-
CB_LOG_DEBUG("{} unable to connect to {}:{} in time, reconnecting",
|
|
1406
|
+
CB_LOG_DEBUG("{} unable to connect to {}:{} (\"{}:{}\") in time, reconnecting",
|
|
1407
|
+
self->log_prefix_,
|
|
1408
|
+
hostname,
|
|
1409
|
+
port,
|
|
1410
|
+
self->bootstrap_hostname_,
|
|
1411
|
+
self->bootstrap_port_);
|
|
1429
1412
|
return self->stream_->close([self](std::error_code) { self->initiate_bootstrap(); });
|
|
1430
1413
|
});
|
|
1431
1414
|
stream_->async_connect(it->endpoint(),
|
|
1432
1415
|
std::bind(&mcbp_session_impl::on_connect, shared_from_this(), std::placeholders::_1, it));
|
|
1433
1416
|
} else {
|
|
1434
|
-
CB_LOG_ERROR("{} no more endpoints left to connect, will try another address",
|
|
1417
|
+
CB_LOG_ERROR("{} no more endpoints left to connect to \"{}:{}\", will try another address",
|
|
1418
|
+
log_prefix_,
|
|
1419
|
+
bootstrap_hostname_,
|
|
1420
|
+
bootstrap_port_);
|
|
1435
1421
|
if (state_listener_) {
|
|
1436
1422
|
state_listener_->report_bootstrap_error(fmt::format("{}:{}", bootstrap_hostname_, bootstrap_port_),
|
|
1437
1423
|
errc::network::no_endpoints_left);
|
|
@@ -1892,4 +1878,10 @@ mcbp_session::write_and_subscribe(std::shared_ptr<mcbp::queue_request> request,
|
|
|
1892
1878
|
return impl_->write_and_subscribe(std::move(request), std::move(handler));
|
|
1893
1879
|
}
|
|
1894
1880
|
|
|
1881
|
+
void
|
|
1882
|
+
mcbp_session::write_and_flush(std::vector<std::byte>&& buffer)
|
|
1883
|
+
{
|
|
1884
|
+
return impl_->write_and_flush(std::move(buffer));
|
|
1885
|
+
}
|
|
1886
|
+
|
|
1895
1887
|
} // namespace couchbase::core::io
|
|
@@ -109,6 +109,7 @@ class mcbp_session
|
|
|
109
109
|
[[nodiscard]] const std::string& bootstrap_hostname() const;
|
|
110
110
|
[[nodiscard]] const std::string& bootstrap_port() const;
|
|
111
111
|
[[nodiscard]] std::uint16_t bootstrap_port_number() const;
|
|
112
|
+
void write_and_flush(std::vector<std::byte>&& buffer);
|
|
112
113
|
void write_and_subscribe(std::shared_ptr<mcbp::queue_request>, std::shared_ptr<response_handler> handler);
|
|
113
114
|
void write_and_subscribe(std::uint32_t opaque, std::vector<std::byte>&& data, command_handler&& handler);
|
|
114
115
|
void bootstrap(utils::movable_function<void(std::error_code, topology::configuration)>&& handler,
|
|
@@ -30,7 +30,7 @@ static const std::string protocol_logger_name{ "couchbase_cxx_client_protocol_lo
|
|
|
30
30
|
* This pattern is duplicated for some test cases. If you need to update it,
|
|
31
31
|
* please also update in all relevant places.
|
|
32
32
|
*/
|
|
33
|
-
static const std::string log_pattern{ "[%Y-%m-%d %T.%e]
|
|
33
|
+
static const std::string log_pattern{ "[%Y-%m-%d %T.%e] %4oms [%^%4!l%$] [%P,%t] %v" };
|
|
34
34
|
|
|
35
35
|
/**
|
|
36
36
|
* Instances of spdlog (async) file logger.
|
|
@@ -101,3 +101,13 @@
|
|
|
101
101
|
* The document not locked (couchbase::errc::key_value::document_not_locked) error code is supported
|
|
102
102
|
*/
|
|
103
103
|
#define COUCHBASE_CXX_CLIENT_HAS_ERRC_DOCUMENT_NOT_LOCKED 1
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Vector search is supported via couchbase::cluster::search() or couchbase::scope::search()
|
|
107
|
+
*/
|
|
108
|
+
#define COUCHBASE_CXX_CLIENT_HAS_VECTOR_SEARCH 1
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Scope level search index management is supported via couchbase::scope::search_indexes()
|
|
112
|
+
*/
|
|
113
|
+
#define COUCHBASE_CXX_CLIENT_HAS_SCOPE_SEARCH_INDEX_MANAGEMENT 1
|
|
@@ -327,7 +327,12 @@ query_request::make_response(error_context::query&& ctx, const encoded_response_
|
|
|
327
327
|
response.ctx.first_error_message = response.meta.errors->front().message;
|
|
328
328
|
switch (response.ctx.first_error_code) {
|
|
329
329
|
case 1065: /* IKey: "service.io.request.unrecognized_parameter" */
|
|
330
|
-
response.ctx.
|
|
330
|
+
if ((response.ctx.first_error_message.find("Unrecognized parameter in request") != std::string::npos) &&
|
|
331
|
+
(response.ctx.first_error_message.find("preserve_expiry") != std::string::npos)) {
|
|
332
|
+
response.ctx.ec = errc::common::feature_not_available;
|
|
333
|
+
} else {
|
|
334
|
+
response.ctx.ec = errc::common::invalid_argument;
|
|
335
|
+
}
|
|
331
336
|
break;
|
|
332
337
|
case 1080: /* IKey: "timeout" */
|
|
333
338
|
response.ctx.ec = errc::common::unambiguous_timeout;
|
|
@@ -34,6 +34,25 @@ search_request::encode_to(search_request::encoded_request_type& encoded, http_co
|
|
|
34
34
|
{ "query", utils::json::parse(query) },
|
|
35
35
|
{ "ctl", { { "timeout", encoded.timeout.count() } } },
|
|
36
36
|
};
|
|
37
|
+
|
|
38
|
+
if (show_request.has_value()) {
|
|
39
|
+
body["showrequest"] = show_request.value() ? "true" : "false";
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (vector_search.has_value()) {
|
|
43
|
+
body["knn"] = utils::json::parse(vector_search.value());
|
|
44
|
+
}
|
|
45
|
+
if (vector_query_combination.has_value()) {
|
|
46
|
+
switch (*vector_query_combination) {
|
|
47
|
+
case couchbase::core::vector_query_combination::combination_or:
|
|
48
|
+
body["knn_operator"] = "or";
|
|
49
|
+
break;
|
|
50
|
+
case couchbase::core::vector_query_combination::combination_and:
|
|
51
|
+
body["knn_operator"] = "and";
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
37
56
|
if (explain) {
|
|
38
57
|
body["explain"] = *explain;
|
|
39
58
|
}
|
|
@@ -103,10 +122,15 @@ search_request::encode_to(search_request::encoded_request_type& encoded, http_co
|
|
|
103
122
|
body[key] = utils::json::parse(value);
|
|
104
123
|
}
|
|
105
124
|
|
|
125
|
+
if (bucket_name.has_value() && scope_name.has_value()) {
|
|
126
|
+
encoded.path = fmt::format("/api/bucket/{}/scope/{}/index/{}/query", bucket_name.value(), scope_name.value(), index_name);
|
|
127
|
+
} else {
|
|
128
|
+
encoded.path = fmt::format("/api/index/{}/query", index_name);
|
|
129
|
+
}
|
|
130
|
+
|
|
106
131
|
encoded.type = type;
|
|
107
132
|
encoded.headers["content-type"] = "application/json";
|
|
108
133
|
encoded.method = "POST";
|
|
109
|
-
encoded.path = fmt::format("/api/index/{}/query", index_name);
|
|
110
134
|
body_str = utils::json::generate(body);
|
|
111
135
|
encoded.body = body_str;
|
|
112
136
|
if (context.options.show_queries) {
|
|
@@ -310,6 +334,18 @@ search_request::make_response(error_context::search&& ctx, const encoded_respons
|
|
|
310
334
|
response.ctx.ec = errc::common::rate_limited;
|
|
311
335
|
return response;
|
|
312
336
|
}
|
|
337
|
+
} else if (encoded.status_code == 404) {
|
|
338
|
+
tao::json::value payload{};
|
|
339
|
+
try {
|
|
340
|
+
payload = utils::json::parse(encoded.body.data());
|
|
341
|
+
} catch (const tao::pegtl::parse_error&) {
|
|
342
|
+
response.ctx.ec = errc::common::parsing_failure;
|
|
343
|
+
return response;
|
|
344
|
+
}
|
|
345
|
+
response.status = payload.at("status").get_string();
|
|
346
|
+
response.error = payload.at("error").get_string();
|
|
347
|
+
response.ctx.ec = errc::common::feature_not_available;
|
|
348
|
+
return response;
|
|
313
349
|
}
|
|
314
350
|
response.ctx.ec = errc::common::internal_server_failure;
|
|
315
351
|
}
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
#include "core/search_highlight_style.hxx"
|
|
28
28
|
#include "core/search_scan_consistency.hxx"
|
|
29
29
|
#include "core/timeout_defaults.hxx"
|
|
30
|
+
#include "core/vector_query_combination.hxx"
|
|
30
31
|
|
|
31
32
|
#include <couchbase/mutation_token.hxx>
|
|
32
33
|
|
|
@@ -118,6 +119,16 @@ struct search_request {
|
|
|
118
119
|
|
|
119
120
|
std::string index_name;
|
|
120
121
|
couchbase::core::json_string query;
|
|
122
|
+
std::optional<std::string> bucket_name;
|
|
123
|
+
std::optional<std::string> scope_name;
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* UNCOMMITTED: This should be set to false if using the .search() API, leave unset for old .search_query() API
|
|
127
|
+
*/
|
|
128
|
+
std::optional<bool> show_request;
|
|
129
|
+
|
|
130
|
+
std::optional<couchbase::core::json_string> vector_search;
|
|
131
|
+
std::optional<couchbase::core::vector_query_combination> vector_query_combination;
|
|
121
132
|
|
|
122
133
|
std::optional<std::uint32_t> limit{};
|
|
123
134
|
std::optional<std::uint32_t> skip{};
|
|
@@ -28,14 +28,18 @@
|
|
|
28
28
|
namespace couchbase::core::operations::management
|
|
29
29
|
{
|
|
30
30
|
std::error_code
|
|
31
|
-
collection_create_request::encode_to(encoded_request_type& encoded, http_context& /*
|
|
31
|
+
collection_create_request::encode_to(encoded_request_type& encoded, http_context& /*context*/) const
|
|
32
32
|
{
|
|
33
33
|
encoded.method = "POST";
|
|
34
34
|
encoded.path = fmt::format("/pools/default/buckets/{}/scopes/{}/collections", bucket_name, scope_name);
|
|
35
35
|
encoded.headers["content-type"] = "application/x-www-form-urlencoded";
|
|
36
36
|
encoded.body = fmt::format("name={}", utils::string_codec::form_encode(collection_name));
|
|
37
|
-
if (max_expiry
|
|
38
|
-
|
|
37
|
+
if (max_expiry >= -1) {
|
|
38
|
+
if (max_expiry != 0) {
|
|
39
|
+
encoded.body.append(fmt::format("&maxTTL={}", max_expiry));
|
|
40
|
+
}
|
|
41
|
+
} else {
|
|
42
|
+
return couchbase::errc::common::invalid_argument;
|
|
39
43
|
}
|
|
40
44
|
if (history.has_value()) {
|
|
41
45
|
encoded.body.append(fmt::format("&history={}", history.value()));
|
|
@@ -53,9 +57,6 @@ collection_create_request::make_response(error_context::http&& ctx, const encode
|
|
|
53
57
|
std::regex collection_exists("Collection with name .+ already exists");
|
|
54
58
|
if (std::regex_search(encoded.body.data(), collection_exists)) {
|
|
55
59
|
response.ctx.ec = errc::management::collection_exists;
|
|
56
|
-
} else if (encoded.body.data().find("Not allowed on this version of cluster") != std::string::npos ||
|
|
57
|
-
encoded.body.data().find("Bucket must have storage_mode=magma") != std::string::npos) {
|
|
58
|
-
response.ctx.ec = errc::common::feature_not_available;
|
|
59
60
|
} else {
|
|
60
61
|
response.ctx.ec = errc::common::invalid_argument;
|
|
61
62
|
}
|
|
@@ -41,7 +41,7 @@ struct collection_create_request {
|
|
|
41
41
|
std::string bucket_name;
|
|
42
42
|
std::string scope_name;
|
|
43
43
|
std::string collection_name;
|
|
44
|
-
std::
|
|
44
|
+
std::int32_t max_expiry{ 0 };
|
|
45
45
|
std::optional<bool> history{};
|
|
46
46
|
|
|
47
47
|
std::optional<std::string> client_context_id{};
|
|
@@ -28,14 +28,18 @@
|
|
|
28
28
|
namespace couchbase::core::operations::management
|
|
29
29
|
{
|
|
30
30
|
std::error_code
|
|
31
|
-
collection_update_request::encode_to(encoded_request_type& encoded, http_context& /*
|
|
31
|
+
collection_update_request::encode_to(encoded_request_type& encoded, http_context& /*context*/) const
|
|
32
32
|
{
|
|
33
33
|
encoded.method = "PATCH";
|
|
34
34
|
encoded.path = fmt::format("/pools/default/buckets/{}/scopes/{}/collections/{}", bucket_name, scope_name, collection_name);
|
|
35
35
|
encoded.headers["content-type"] = "application/x-www-form-urlencoded";
|
|
36
36
|
std::map<std::string, std::string> values{};
|
|
37
37
|
if (max_expiry.has_value()) {
|
|
38
|
-
|
|
38
|
+
if (max_expiry.value() >= -1) {
|
|
39
|
+
values["maxTTL"] = std::to_string(max_expiry.value());
|
|
40
|
+
} else {
|
|
41
|
+
return errc::common::invalid_argument;
|
|
42
|
+
}
|
|
39
43
|
}
|
|
40
44
|
if (history.has_value()) {
|
|
41
45
|
values["history"] = history.value() ? "true" : "false";
|
|
@@ -51,12 +55,7 @@ collection_update_request::make_response(error_context::http&& ctx, const encode
|
|
|
51
55
|
if (!response.ctx.ec) {
|
|
52
56
|
switch (encoded.status_code) {
|
|
53
57
|
case 400: {
|
|
54
|
-
|
|
55
|
-
encoded.body.data().find("Bucket must have storage_mode=magma") != std::string::npos) {
|
|
56
|
-
response.ctx.ec = errc::common::feature_not_available;
|
|
57
|
-
} else {
|
|
58
|
-
response.ctx.ec = errc::common::invalid_argument;
|
|
59
|
-
}
|
|
58
|
+
response.ctx.ec = errc::common::invalid_argument;
|
|
60
59
|
} break;
|
|
61
60
|
case 404: {
|
|
62
61
|
std::regex scope_not_found("Scope with name .+ is not found");
|
|
@@ -41,7 +41,7 @@ struct collection_update_request {
|
|
|
41
41
|
std::string bucket_name;
|
|
42
42
|
std::string scope_name;
|
|
43
43
|
std::string collection_name;
|
|
44
|
-
std::optional<std::
|
|
44
|
+
std::optional<std::int32_t> max_expiry{};
|
|
45
45
|
std::optional<bool> history{};
|
|
46
46
|
|
|
47
47
|
std::optional<std::string> client_context_id{};
|
|
@@ -47,6 +47,9 @@ extract_common_query_error_code(std::uint64_t code, const std::string& message)
|
|
|
47
47
|
case 1194: /* ICode: E_SERVICE_USER_RESULT_SIZE_EXCEEDED, IKey: "service.result.size.exceeded" */
|
|
48
48
|
return errc::common::rate_limited;
|
|
49
49
|
|
|
50
|
+
case 13014: /*ICode: E_DATASTORE_INSUFFICIENT_CREDENTIALS, IKey: "datastore.couchbase.insufficient_credentials" */
|
|
51
|
+
return errc::common::authentication_failure;
|
|
52
|
+
|
|
50
53
|
case 5000:
|
|
51
54
|
if (message.find("Limit for number of indexes that can be created per scope has been reached") != std::string::npos) {
|
|
52
55
|
return errc::common::quota_limited;
|
package/deps/couchbase-cxx-client/core/operations/management/search_index_analyze_document.cxx
CHANGED
|
@@ -33,7 +33,11 @@ search_index_analyze_document_request::encode_to(encoded_request_type& encoded,
|
|
|
33
33
|
encoded.method = "POST";
|
|
34
34
|
encoded.headers["cache-control"] = "no-cache";
|
|
35
35
|
encoded.headers["content-type"] = "application/json";
|
|
36
|
-
|
|
36
|
+
if (bucket_name.has_value() && scope_name.has_value()) {
|
|
37
|
+
encoded.path = fmt::format("/api/bucket/{}/scope/{}/index/{}/analyzeDoc", bucket_name.value(), scope_name.value(), index_name);
|
|
38
|
+
} else {
|
|
39
|
+
encoded.path = fmt::format("/api/index/{}/analyzeDoc", index_name);
|
|
40
|
+
}
|
|
37
41
|
encoded.body = encoded_document;
|
|
38
42
|
return {};
|
|
39
43
|
}
|
|
@@ -78,6 +82,18 @@ search_index_analyze_document_request::make_response(error_context::http&& ctx,
|
|
|
78
82
|
response.ctx.ec = errc::common::index_exists;
|
|
79
83
|
return response;
|
|
80
84
|
}
|
|
85
|
+
} else if (encoded.status_code == 404) {
|
|
86
|
+
tao::json::value payload{};
|
|
87
|
+
try {
|
|
88
|
+
payload = utils::json::parse(encoded.body.data());
|
|
89
|
+
} catch (const tao::pegtl::parse_error&) {
|
|
90
|
+
response.ctx.ec = errc::common::parsing_failure;
|
|
91
|
+
return response;
|
|
92
|
+
}
|
|
93
|
+
response.status = payload.at("status").get_string();
|
|
94
|
+
response.error = payload.at("error").get_string();
|
|
95
|
+
response.ctx.ec = errc::common::feature_not_available;
|
|
96
|
+
return response;
|
|
81
97
|
}
|
|
82
98
|
response.ctx.ec = extract_common_error_code(encoded.status_code, encoded.body.data());
|
|
83
99
|
}
|
package/deps/couchbase-cxx-client/core/operations/management/search_index_analyze_document.hxx
CHANGED
|
@@ -43,6 +43,9 @@ struct search_index_analyze_document_request {
|
|
|
43
43
|
std::string index_name;
|
|
44
44
|
std::string encoded_document;
|
|
45
45
|
|
|
46
|
+
std::optional<std::string> bucket_name;
|
|
47
|
+
std::optional<std::string> scope_name;
|
|
48
|
+
|
|
46
49
|
std::optional<std::string> client_context_id{};
|
|
47
50
|
std::optional<std::chrono::milliseconds> timeout{};
|
|
48
51
|
|