couchbase 3.0.0.alpha.2 → 3.0.0.alpha.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/tests-dev-preview.yml +52 -0
  3. data/.gitmodules +3 -0
  4. data/.idea/vcs.xml +1 -0
  5. data/.yardopts +1 -0
  6. data/README.md +1 -1
  7. data/Rakefile +5 -1
  8. data/bin/init-cluster +13 -5
  9. data/couchbase.gemspec +2 -1
  10. data/examples/managing_query_indexes.rb +1 -1
  11. data/examples/managing_search_indexes.rb +62 -0
  12. data/examples/search.rb +187 -0
  13. data/ext/.clang-tidy +1 -0
  14. data/ext/build_version.hxx.in +1 -1
  15. data/ext/couchbase/bucket.hxx +0 -40
  16. data/ext/couchbase/couchbase.cxx +2578 -1368
  17. data/ext/couchbase/io/http_session.hxx +27 -7
  18. data/ext/couchbase/io/mcbp_parser.hxx +2 -0
  19. data/ext/couchbase/io/mcbp_session.hxx +53 -24
  20. data/ext/couchbase/io/session_manager.hxx +6 -1
  21. data/ext/couchbase/operations.hxx +13 -0
  22. data/ext/couchbase/operations/bucket_create.hxx +1 -0
  23. data/ext/couchbase/operations/bucket_drop.hxx +1 -0
  24. data/ext/couchbase/operations/bucket_flush.hxx +1 -0
  25. data/ext/couchbase/operations/bucket_get.hxx +1 -0
  26. data/ext/couchbase/operations/bucket_get_all.hxx +1 -0
  27. data/ext/couchbase/operations/bucket_update.hxx +1 -0
  28. data/ext/couchbase/operations/cluster_developer_preview_enable.hxx +1 -0
  29. data/ext/couchbase/operations/collection_create.hxx +6 -1
  30. data/ext/couchbase/operations/collection_drop.hxx +1 -0
  31. data/ext/couchbase/operations/command.hxx +86 -11
  32. data/ext/couchbase/operations/document_decrement.hxx +1 -0
  33. data/ext/couchbase/operations/document_exists.hxx +1 -0
  34. data/ext/couchbase/operations/document_get.hxx +1 -0
  35. data/ext/couchbase/operations/document_get_and_lock.hxx +1 -0
  36. data/ext/couchbase/operations/document_get_and_touch.hxx +1 -0
  37. data/ext/couchbase/operations/document_get_projected.hxx +243 -0
  38. data/ext/couchbase/operations/document_increment.hxx +4 -1
  39. data/ext/couchbase/operations/document_insert.hxx +1 -0
  40. data/ext/couchbase/operations/document_lookup_in.hxx +1 -0
  41. data/ext/couchbase/operations/document_mutate_in.hxx +1 -0
  42. data/ext/couchbase/operations/document_query.hxx +13 -2
  43. data/ext/couchbase/operations/document_remove.hxx +1 -0
  44. data/ext/couchbase/operations/document_replace.hxx +1 -0
  45. data/ext/couchbase/operations/document_search.hxx +337 -0
  46. data/ext/couchbase/operations/document_touch.hxx +1 -0
  47. data/ext/couchbase/operations/document_unlock.hxx +1 -0
  48. data/ext/couchbase/operations/document_upsert.hxx +1 -0
  49. data/ext/couchbase/operations/query_index_build_deferred.hxx +1 -0
  50. data/ext/couchbase/operations/query_index_create.hxx +1 -0
  51. data/ext/couchbase/operations/query_index_drop.hxx +1 -0
  52. data/ext/couchbase/operations/query_index_get_all.hxx +1 -0
  53. data/ext/couchbase/operations/scope_create.hxx +1 -0
  54. data/ext/couchbase/operations/scope_drop.hxx +1 -0
  55. data/ext/couchbase/operations/scope_get_all.hxx +2 -0
  56. data/ext/couchbase/operations/search_index.hxx +62 -0
  57. data/ext/couchbase/operations/search_index_analyze_document.hxx +92 -0
  58. data/ext/couchbase/operations/search_index_control_ingest.hxx +78 -0
  59. data/ext/couchbase/operations/search_index_control_plan_freeze.hxx +80 -0
  60. data/ext/couchbase/operations/search_index_control_query.hxx +80 -0
  61. data/ext/couchbase/operations/search_index_drop.hxx +77 -0
  62. data/ext/couchbase/operations/search_index_get.hxx +80 -0
  63. data/ext/couchbase/operations/search_index_get_all.hxx +82 -0
  64. data/ext/couchbase/operations/search_index_get_documents_count.hxx +81 -0
  65. data/ext/couchbase/operations/search_index_upsert.hxx +106 -0
  66. data/ext/couchbase/protocol/client_opcode.hxx +10 -0
  67. data/ext/couchbase/protocol/cmd_get_collection_id.hxx +117 -0
  68. data/ext/couchbase/timeout_defaults.hxx +32 -0
  69. data/ext/couchbase/version.hxx +1 -1
  70. data/ext/test/main.cxx +5 -5
  71. data/lib/couchbase/binary_collection.rb +16 -12
  72. data/lib/couchbase/binary_collection_options.rb +4 -0
  73. data/lib/couchbase/cluster.rb +88 -8
  74. data/lib/couchbase/collection.rb +39 -15
  75. data/lib/couchbase/collection_options.rb +19 -2
  76. data/lib/couchbase/json_transcoder.rb +2 -2
  77. data/lib/couchbase/management/bucket_manager.rb +37 -23
  78. data/lib/couchbase/management/collection_manager.rb +15 -6
  79. data/lib/couchbase/management/query_index_manager.rb +16 -6
  80. data/lib/couchbase/management/search_index_manager.rb +61 -14
  81. data/lib/couchbase/search_options.rb +1492 -0
  82. data/lib/couchbase/version.rb +1 -1
  83. metadata +22 -2
@@ -37,6 +37,7 @@ struct touch_request {
37
37
  std::uint16_t partition{};
38
38
  std::uint32_t opaque{};
39
39
  std::uint32_t expiration{};
40
+ std::chrono::milliseconds timeout{ timeout_defaults::key_value_timeout };
40
41
 
41
42
  void encode_to(encoded_request_type& encoded)
42
43
  {
@@ -37,6 +37,7 @@ struct unlock_request {
37
37
  uint16_t partition{};
38
38
  uint32_t opaque{};
39
39
  uint64_t cas{};
40
+ std::chrono::milliseconds timeout{ timeout_defaults::key_value_timeout };
40
41
 
41
42
  void encode_to(encoded_request_type& encoded)
42
43
  {
@@ -43,6 +43,7 @@ struct upsert_request {
43
43
  uint32_t expiration{ 0 };
44
44
  protocol::durability_level durability_level{ protocol::durability_level::none };
45
45
  std::optional<std::uint16_t> durability_timeout{};
46
+ std::chrono::milliseconds timeout{ timeout_defaults::key_value_timeout };
46
47
 
47
48
  void encode_to(encoded_request_type& encoded)
48
49
  {
@@ -43,6 +43,7 @@ struct query_index_build_deferred_request {
43
43
 
44
44
  uuid::uuid_t client_context_id{ uuid::random() };
45
45
  std::string bucket_name;
46
+ std::chrono::milliseconds timeout{ timeout_defaults::management_timeout };
46
47
 
47
48
  void encode_to(encoded_request_type& encoded)
48
49
  {
@@ -50,6 +50,7 @@ struct query_index_create_request {
50
50
  std::optional<std::string> condition{};
51
51
  std::optional<bool> deferred{};
52
52
  std::optional<int> num_replicas{};
53
+ std::chrono::milliseconds timeout{ timeout_defaults::management_timeout };
53
54
 
54
55
  void encode_to(encoded_request_type& encoded)
55
56
  {
@@ -46,6 +46,7 @@ struct query_index_drop_request {
46
46
  std::string index_name;
47
47
  bool is_primary{ false };
48
48
  bool ignore_if_does_not_exist{ false };
49
+ std::chrono::milliseconds timeout{ timeout_defaults::management_timeout };
49
50
 
50
51
  void encode_to(encoded_request_type& encoded)
51
52
  {
@@ -51,6 +51,7 @@ struct query_index_get_all_request {
51
51
 
52
52
  uuid::uuid_t client_context_id{ uuid::random() };
53
53
  std::string bucket_name;
54
+ std::chrono::milliseconds timeout{ timeout_defaults::management_timeout };
54
55
 
55
56
  void encode_to(encoded_request_type& encoded)
56
57
  {
@@ -40,6 +40,7 @@ struct scope_create_request {
40
40
 
41
41
  std::string bucket_name;
42
42
  std::string scope_name;
43
+ std::chrono::milliseconds timeout{ timeout_defaults::management_timeout };
43
44
 
44
45
  void encode_to(encoded_request_type& encoded)
45
46
  {
@@ -40,6 +40,7 @@ struct scope_drop_request {
40
40
 
41
41
  std::string bucket_name;
42
42
  std::string scope_name;
43
+ std::chrono::milliseconds timeout{ timeout_defaults::management_timeout };
43
44
 
44
45
  void encode_to(encoded_request_type& encoded)
45
46
  {
@@ -21,6 +21,7 @@
21
21
 
22
22
  #include <version.hxx>
23
23
  #include <operations/bucket_settings.hxx>
24
+ #include <collections_manifest.hxx>
24
25
 
25
26
  namespace couchbase::operations
26
27
  {
@@ -38,6 +39,7 @@ struct scope_get_all_request {
38
39
  static const inline service_type type = service_type::management;
39
40
 
40
41
  std::string bucket_name;
42
+ std::chrono::milliseconds timeout{ timeout_defaults::management_timeout };
41
43
 
42
44
  void encode_to(encoded_request_type& encoded)
43
45
  {
@@ -0,0 +1,62 @@
1
+ #pragma once
2
+
3
+ namespace couchbase::operations
4
+ {
5
+ struct search_index {
6
+ std::string uuid;
7
+ std::string name;
8
+ std::string type;
9
+ std::string params_json;
10
+
11
+ std::string source_uuid;
12
+ std::string source_name;
13
+ std::string source_type;
14
+ std::string source_params_json;
15
+
16
+ std::string plan_params_json;
17
+ };
18
+
19
+ } // namespace couchbase::operations
20
+
21
+ namespace tao::json
22
+ {
23
+ template<>
24
+ struct traits<couchbase::operations::search_index> {
25
+ template<template<typename...> class Traits>
26
+ static couchbase::operations::search_index as(const tao::json::basic_value<Traits>& v)
27
+ {
28
+ couchbase::operations::search_index result;
29
+ result.uuid = v.at("uuid").get_string();
30
+ result.name = v.at("name").get_string();
31
+ result.type = v.at("type").get_string();
32
+ {
33
+ const auto* params = v.find("params");
34
+ if (params != nullptr && params->is_object()) {
35
+ result.params_json = tao::json::to_string(*params);
36
+ }
37
+ }
38
+ if (v.find("sourceUUID") != nullptr) {
39
+ result.source_uuid = v.at("sourceUUID").get_string();
40
+ }
41
+ if (v.find("sourceName") != nullptr) {
42
+ result.source_name = v.at("sourceName").get_string();
43
+ }
44
+ if (v.find("sourceType") != nullptr) {
45
+ result.source_type = v.at("sourceType").get_string();
46
+ }
47
+ {
48
+ const auto* params = v.find("sourceParams");
49
+ if (params != nullptr && params->is_object()) {
50
+ result.source_params_json = tao::json::to_string(*params);
51
+ }
52
+ }
53
+ {
54
+ const auto* params = v.find("planParams");
55
+ if (params != nullptr && params->is_object()) {
56
+ result.plan_params_json = tao::json::to_string(*params);
57
+ }
58
+ }
59
+ return result;
60
+ }
61
+ };
62
+ } // namespace tao::json
@@ -0,0 +1,92 @@
1
+ /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Copyright 2020 Couchbase, Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ #pragma once
19
+
20
+ #include <tao/json.hpp>
21
+
22
+ #include <version.hxx>
23
+
24
+ namespace couchbase::operations
25
+ {
26
+ struct search_index_analyze_document_response {
27
+ uuid::uuid_t client_context_id;
28
+ std::error_code ec;
29
+ std::string status{};
30
+ std::string error{};
31
+ std::string analysis{};
32
+ };
33
+
34
+ struct search_index_analyze_document_request {
35
+ using response_type = search_index_analyze_document_response;
36
+ using encoded_request_type = io::http_request;
37
+ using encoded_response_type = io::http_response;
38
+
39
+ static const inline service_type type = service_type::search;
40
+
41
+ uuid::uuid_t client_context_id{ uuid::random() };
42
+ std::chrono::milliseconds timeout{ timeout_defaults::management_timeout };
43
+
44
+ std::string index_name;
45
+ std::string encoded_document;
46
+
47
+ void encode_to(encoded_request_type& encoded)
48
+ {
49
+ encoded.method = "POST";
50
+ encoded.headers["cache-control"] = "no-cache";
51
+ encoded.headers["content-type"] = "application/json";
52
+ encoded.path = fmt::format("/api/index/{}/analyzeDoc", index_name);
53
+ encoded.body = encoded_document;
54
+ }
55
+ };
56
+
57
+ search_index_analyze_document_response
58
+ make_response(std::error_code ec,
59
+ search_index_analyze_document_request& request,
60
+ search_index_analyze_document_request::encoded_response_type encoded)
61
+ {
62
+ search_index_analyze_document_response response{ request.client_context_id, ec };
63
+ if (!ec) {
64
+ if (encoded.status_code == 200) {
65
+ auto payload = tao::json::from_string(encoded.body);
66
+ response.status = payload.at("status").get_string();
67
+ if (response.status == "ok") {
68
+ response.analysis = tao::json::to_string(payload.at("analyzed"));
69
+ return response;
70
+ }
71
+ } else if (encoded.status_code == 400) {
72
+ if (encoded.body.find("no indexName:") != std::string::npos) {
73
+ response.ec = std::make_error_code(error::common_errc::index_not_found);
74
+ return response;
75
+ }
76
+ auto payload = tao::json::from_string(encoded.body);
77
+ response.status = payload.at("status").get_string();
78
+ response.error = payload.at("error").get_string();
79
+ if (response.error.find("index not found") != std::string::npos) {
80
+ response.ec = std::make_error_code(error::common_errc::index_not_found);
81
+ return response;
82
+ } else if (response.error.find("index with the same name already exists") != std::string::npos) {
83
+ response.ec = std::make_error_code(error::common_errc::index_exists);
84
+ return response;
85
+ }
86
+ }
87
+ response.ec = std::make_error_code(error::common_errc::internal_server_failure);
88
+ }
89
+ return response;
90
+ }
91
+
92
+ } // namespace couchbase::operations
@@ -0,0 +1,78 @@
1
+ /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Copyright 2020 Couchbase, Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ #pragma once
19
+
20
+ #include <tao/json.hpp>
21
+
22
+ #include <version.hxx>
23
+
24
+ namespace couchbase::operations
25
+ {
26
+ struct search_index_control_ingest_response {
27
+ uuid::uuid_t client_context_id;
28
+ std::error_code ec;
29
+ std::string status{};
30
+ std::string error{};
31
+ };
32
+
33
+ struct search_index_control_ingest_request {
34
+ using response_type = search_index_control_ingest_response;
35
+ using encoded_request_type = io::http_request;
36
+ using encoded_response_type = io::http_response;
37
+
38
+ static const inline service_type type = service_type::search;
39
+
40
+ uuid::uuid_t client_context_id{ uuid::random() };
41
+ std::chrono::milliseconds timeout{ timeout_defaults::management_timeout };
42
+
43
+ std::string index_name;
44
+ bool pause;
45
+
46
+ void encode_to(encoded_request_type& encoded)
47
+ {
48
+ encoded.method = "POST";
49
+ encoded.path = fmt::format("/api/index/{}/ingestControl/{}", index_name, pause ? "pause" : "resume");
50
+ }
51
+ };
52
+
53
+ search_index_control_ingest_response
54
+ make_response(std::error_code ec, search_index_control_ingest_request& request, search_index_control_ingest_request::encoded_response_type encoded)
55
+ {
56
+ search_index_control_ingest_response response{ request.client_context_id, ec };
57
+ if (!ec) {
58
+ if (encoded.status_code == 200) {
59
+ auto payload = tao::json::from_string(encoded.body);
60
+ response.status = payload.at("status").get_string();
61
+ if (response.status == "ok") {
62
+ return response;
63
+ }
64
+ } else if (encoded.status_code == 400) {
65
+ auto payload = tao::json::from_string(encoded.body);
66
+ response.status = payload.at("status").get_string();
67
+ response.error = payload.at("error").get_string();
68
+ if (response.error.find("index not found") != std::string::npos) {
69
+ response.ec = std::make_error_code(error::common_errc::index_not_found);
70
+ return response;
71
+ }
72
+ }
73
+ response.ec = std::make_error_code(error::common_errc::internal_server_failure);
74
+ }
75
+ return response;
76
+ }
77
+
78
+ } // namespace couchbase::operations
@@ -0,0 +1,80 @@
1
+ /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Copyright 2020 Couchbase, Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ #pragma once
19
+
20
+ #include <tao/json.hpp>
21
+
22
+ #include <version.hxx>
23
+
24
+ namespace couchbase::operations
25
+ {
26
+ struct search_index_control_plan_freeze_response {
27
+ uuid::uuid_t client_context_id;
28
+ std::error_code ec;
29
+ std::string status{};
30
+ std::string error{};
31
+ };
32
+
33
+ struct search_index_control_plan_freeze_request {
34
+ using response_type = search_index_control_plan_freeze_response;
35
+ using encoded_request_type = io::http_request;
36
+ using encoded_response_type = io::http_response;
37
+
38
+ static const inline service_type type = service_type::search;
39
+
40
+ uuid::uuid_t client_context_id{ uuid::random() };
41
+ std::chrono::milliseconds timeout{ timeout_defaults::management_timeout };
42
+
43
+ std::string index_name;
44
+ bool freeze;
45
+
46
+ void encode_to(encoded_request_type& encoded)
47
+ {
48
+ encoded.method = "POST";
49
+ encoded.path = fmt::format("/api/index/{}/planFreezeControl/{}", index_name, freeze ? "freeze" : "unfreeze");
50
+ }
51
+ };
52
+
53
+ search_index_control_plan_freeze_response
54
+ make_response(std::error_code ec,
55
+ search_index_control_plan_freeze_request& request,
56
+ search_index_control_plan_freeze_request::encoded_response_type encoded)
57
+ {
58
+ search_index_control_plan_freeze_response response{ request.client_context_id, ec };
59
+ if (!ec) {
60
+ if (encoded.status_code == 200) {
61
+ auto payload = tao::json::from_string(encoded.body);
62
+ response.status = payload.at("status").get_string();
63
+ if (response.status == "ok") {
64
+ return response;
65
+ }
66
+ } else if (encoded.status_code == 400) {
67
+ auto payload = tao::json::from_string(encoded.body);
68
+ response.status = payload.at("status").get_string();
69
+ response.error = payload.at("error").get_string();
70
+ if (response.error.find("index not found") != std::string::npos) {
71
+ response.ec = std::make_error_code(error::common_errc::index_not_found);
72
+ return response;
73
+ }
74
+ }
75
+ response.ec = std::make_error_code(error::common_errc::internal_server_failure);
76
+ }
77
+ return response;
78
+ }
79
+
80
+ } // namespace couchbase::operations
@@ -0,0 +1,80 @@
1
+ /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Copyright 2020 Couchbase, Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ #pragma once
19
+
20
+ #include <tao/json.hpp>
21
+
22
+ #include <version.hxx>
23
+
24
+ namespace couchbase::operations
25
+ {
26
+ struct search_index_control_query_response {
27
+ uuid::uuid_t client_context_id;
28
+ std::error_code ec;
29
+ std::string status{};
30
+ std::string error{};
31
+ };
32
+
33
+ struct search_index_control_query_request {
34
+ using response_type = search_index_control_query_response;
35
+ using encoded_request_type = io::http_request;
36
+ using encoded_response_type = io::http_response;
37
+
38
+ static const inline service_type type = service_type::search;
39
+
40
+ uuid::uuid_t client_context_id{ uuid::random() };
41
+ std::chrono::milliseconds timeout{ timeout_defaults::management_timeout };
42
+
43
+ std::string index_name;
44
+ bool allow;
45
+
46
+ void encode_to(encoded_request_type& encoded)
47
+ {
48
+ encoded.method = "POST";
49
+ encoded.path = fmt::format("/api/index/{}/queryControl/{}", index_name, allow ? "allow" : "disallow");
50
+ }
51
+ };
52
+
53
+ search_index_control_query_response
54
+ make_response(std::error_code ec,
55
+ search_index_control_query_request& request,
56
+ search_index_control_query_request::encoded_response_type encoded)
57
+ {
58
+ search_index_control_query_response response{ request.client_context_id, ec };
59
+ if (!ec) {
60
+ if (encoded.status_code == 200) {
61
+ auto payload = tao::json::from_string(encoded.body);
62
+ response.status = payload.at("status").get_string();
63
+ if (response.status == "ok") {
64
+ return response;
65
+ }
66
+ } else if (encoded.status_code == 400) {
67
+ auto payload = tao::json::from_string(encoded.body);
68
+ response.status = payload.at("status").get_string();
69
+ response.error = payload.at("error").get_string();
70
+ if (response.error.find("index not found") != std::string::npos) {
71
+ response.ec = std::make_error_code(error::common_errc::index_not_found);
72
+ return response;
73
+ }
74
+ }
75
+ response.ec = std::make_error_code(error::common_errc::internal_server_failure);
76
+ }
77
+ return response;
78
+ }
79
+
80
+ } // namespace couchbase::operations