couchbase 3.5.2-x86_64-darwin
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.
- checksums.yaml +7 -0
- data/LICENSE.txt +202 -0
- data/README.md +154 -0
- data/ext/extconf.rb +0 -0
- data/lib/active_support/cache/couchbase_store.rb +342 -0
- data/lib/couchbase/3.1/libcouchbase.bundle +0 -0
- data/lib/couchbase/3.2/libcouchbase.bundle +0 -0
- data/lib/couchbase/3.3/libcouchbase.bundle +0 -0
- data/lib/couchbase/analytics_options.rb +109 -0
- data/lib/couchbase/authenticator.rb +66 -0
- data/lib/couchbase/binary_collection.rb +130 -0
- data/lib/couchbase/binary_collection_options.rb +26 -0
- data/lib/couchbase/bucket.rb +146 -0
- data/lib/couchbase/cluster.rb +462 -0
- data/lib/couchbase/cluster_registry.rb +49 -0
- data/lib/couchbase/collection.rb +707 -0
- data/lib/couchbase/collection_options.rb +401 -0
- data/lib/couchbase/config_profiles.rb +57 -0
- data/lib/couchbase/configuration.rb +58 -0
- data/lib/couchbase/datastructures/couchbase_list.rb +160 -0
- data/lib/couchbase/datastructures/couchbase_map.rb +194 -0
- data/lib/couchbase/datastructures/couchbase_queue.rb +134 -0
- data/lib/couchbase/datastructures/couchbase_set.rb +128 -0
- data/lib/couchbase/datastructures.rb +26 -0
- data/lib/couchbase/diagnostics.rb +183 -0
- data/lib/couchbase/errors.rb +414 -0
- data/lib/couchbase/json_transcoder.rb +41 -0
- data/lib/couchbase/key_value_scan.rb +119 -0
- data/lib/couchbase/libcouchbase.rb +6 -0
- data/lib/couchbase/logger.rb +87 -0
- data/lib/couchbase/management/analytics_index_manager.rb +1129 -0
- data/lib/couchbase/management/bucket_manager.rb +445 -0
- data/lib/couchbase/management/collection_manager.rb +472 -0
- data/lib/couchbase/management/collection_query_index_manager.rb +224 -0
- data/lib/couchbase/management/query_index_manager.rb +619 -0
- data/lib/couchbase/management/scope_search_index_manager.rb +200 -0
- data/lib/couchbase/management/search_index_manager.rb +426 -0
- data/lib/couchbase/management/user_manager.rb +470 -0
- data/lib/couchbase/management/view_index_manager.rb +239 -0
- data/lib/couchbase/management.rb +31 -0
- data/lib/couchbase/mutation_state.rb +65 -0
- data/lib/couchbase/options.rb +2846 -0
- data/lib/couchbase/protostellar/binary_collection.rb +55 -0
- data/lib/couchbase/protostellar/bucket.rb +55 -0
- data/lib/couchbase/protostellar/client.rb +99 -0
- data/lib/couchbase/protostellar/cluster.rb +171 -0
- data/lib/couchbase/protostellar/collection.rb +152 -0
- data/lib/couchbase/protostellar/connect_options.rb +63 -0
- data/lib/couchbase/protostellar/error_handling.rb +203 -0
- data/lib/couchbase/protostellar/generated/admin/bucket/v1/bucket_pb.rb +61 -0
- data/lib/couchbase/protostellar/generated/admin/bucket/v1/bucket_services_pb.rb +35 -0
- data/lib/couchbase/protostellar/generated/admin/collection/v1/collection_pb.rb +57 -0
- data/lib/couchbase/protostellar/generated/admin/collection/v1/collection_services_pb.rb +36 -0
- data/lib/couchbase/protostellar/generated/admin/query/v1/query_pb.rb +61 -0
- data/lib/couchbase/protostellar/generated/admin/query/v1/query_services_pb.rb +37 -0
- data/lib/couchbase/protostellar/generated/admin/search/v1/search_pb.rb +72 -0
- data/lib/couchbase/protostellar/generated/admin/search/v1/search_services_pb.rb +44 -0
- data/lib/couchbase/protostellar/generated/analytics/v1/analytics_pb.rb +52 -0
- data/lib/couchbase/protostellar/generated/analytics/v1/analytics_services_pb.rb +30 -0
- data/lib/couchbase/protostellar/generated/internal/hooks/v1/hooks_pb.rb +70 -0
- data/lib/couchbase/protostellar/generated/internal/hooks/v1/hooks_services_pb.rb +36 -0
- data/lib/couchbase/protostellar/generated/kv/v1/kv_pb.rb +97 -0
- data/lib/couchbase/protostellar/generated/kv/v1/kv_services_pb.rb +46 -0
- data/lib/couchbase/protostellar/generated/query/v1/query_pb.rb +57 -0
- data/lib/couchbase/protostellar/generated/query/v1/query_services_pb.rb +30 -0
- data/lib/couchbase/protostellar/generated/routing/v1/routing_pb.rb +52 -0
- data/lib/couchbase/protostellar/generated/routing/v1/routing_services_pb.rb +30 -0
- data/lib/couchbase/protostellar/generated/search/v1/search_pb.rb +99 -0
- data/lib/couchbase/protostellar/generated/search/v1/search_services_pb.rb +30 -0
- data/lib/couchbase/protostellar/generated/transactions/v1/transactions_pb.rb +57 -0
- data/lib/couchbase/protostellar/generated/transactions/v1/transactions_services_pb.rb +36 -0
- data/lib/couchbase/protostellar/generated/view/v1/view_pb.rb +51 -0
- data/lib/couchbase/protostellar/generated/view/v1/view_services_pb.rb +30 -0
- data/lib/couchbase/protostellar/generated.rb +9 -0
- data/lib/couchbase/protostellar/management/bucket_manager.rb +67 -0
- data/lib/couchbase/protostellar/management/collection_manager.rb +94 -0
- data/lib/couchbase/protostellar/management/collection_query_index_manager.rb +124 -0
- data/lib/couchbase/protostellar/management/query_index_manager.rb +112 -0
- data/lib/couchbase/protostellar/management.rb +24 -0
- data/lib/couchbase/protostellar/request.rb +78 -0
- data/lib/couchbase/protostellar/request_behaviour.rb +42 -0
- data/lib/couchbase/protostellar/request_generator/admin/bucket.rb +124 -0
- data/lib/couchbase/protostellar/request_generator/admin/collection.rb +94 -0
- data/lib/couchbase/protostellar/request_generator/admin/query.rb +130 -0
- data/lib/couchbase/protostellar/request_generator/admin.rb +24 -0
- data/lib/couchbase/protostellar/request_generator/kv.rb +474 -0
- data/lib/couchbase/protostellar/request_generator/query.rb +133 -0
- data/lib/couchbase/protostellar/request_generator/search.rb +387 -0
- data/lib/couchbase/protostellar/request_generator.rb +26 -0
- data/lib/couchbase/protostellar/response_converter/admin/bucket.rb +55 -0
- data/lib/couchbase/protostellar/response_converter/admin/collection.rb +42 -0
- data/lib/couchbase/protostellar/response_converter/admin/query.rb +59 -0
- data/lib/couchbase/protostellar/response_converter/admin.rb +24 -0
- data/lib/couchbase/protostellar/response_converter/kv.rb +151 -0
- data/lib/couchbase/protostellar/response_converter/query.rb +84 -0
- data/lib/couchbase/protostellar/response_converter/search.rb +136 -0
- data/lib/couchbase/protostellar/response_converter.rb +26 -0
- data/lib/couchbase/protostellar/retry/action.rb +38 -0
- data/lib/couchbase/protostellar/retry/orchestrator.rb +60 -0
- data/lib/couchbase/protostellar/retry/reason.rb +67 -0
- data/lib/couchbase/protostellar/retry/strategies/best_effort.rb +49 -0
- data/lib/couchbase/protostellar/retry/strategies.rb +26 -0
- data/lib/couchbase/protostellar/retry.rb +28 -0
- data/lib/couchbase/protostellar/scope.rb +57 -0
- data/lib/couchbase/protostellar/timeout_defaults.rb +30 -0
- data/lib/couchbase/protostellar/timeouts.rb +83 -0
- data/lib/couchbase/protostellar.rb +29 -0
- data/lib/couchbase/query_options.rb +122 -0
- data/lib/couchbase/railtie.rb +47 -0
- data/lib/couchbase/raw_binary_transcoder.rb +39 -0
- data/lib/couchbase/raw_json_transcoder.rb +40 -0
- data/lib/couchbase/raw_string_transcoder.rb +42 -0
- data/lib/couchbase/scope.rb +258 -0
- data/lib/couchbase/search_options.rb +1650 -0
- data/lib/couchbase/subdoc.rb +293 -0
- data/lib/couchbase/transcoder_flags.rb +64 -0
- data/lib/couchbase/utils/generic_logger_adapter.rb +40 -0
- data/lib/couchbase/utils/stdlib_logger_adapter.rb +67 -0
- data/lib/couchbase/utils/time.rb +71 -0
- data/lib/couchbase/utils.rb +23 -0
- data/lib/couchbase/version.rb +25 -0
- data/lib/couchbase/view_options.rb +67 -0
- data/lib/couchbase.rb +30 -0
- data/lib/rails/generators/couchbase/config/config_generator.rb +29 -0
- metadata +190 -0
@@ -0,0 +1,59 @@
|
|
1
|
+
# Copyright 2023. Couchbase, Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
# frozen_string_literal: true
|
16
|
+
|
17
|
+
require "couchbase/management/query_index_manager"
|
18
|
+
|
19
|
+
module Couchbase
|
20
|
+
module Protostellar
|
21
|
+
module ResponseConverter
|
22
|
+
module Admin
|
23
|
+
class Query
|
24
|
+
INDEX_TYPE_MAP = {
|
25
|
+
:INDEX_TYPE_VIEW => :view,
|
26
|
+
:INDEX_TYPE_GSI => :gsi,
|
27
|
+
}.freeze
|
28
|
+
|
29
|
+
INDEX_STATE_MAP = {
|
30
|
+
:INDEX_STATE_DEFERRED => :deferred,
|
31
|
+
:INDEX_STATE_BUILDING => :building,
|
32
|
+
:INDEX_STATE_PENDING => :pending,
|
33
|
+
:INDEX_STATE_ONLINE => :online,
|
34
|
+
:INDEX_STATE_OFFLINE => :offline,
|
35
|
+
:INDEX_STATE_ABRIDGED => :abridged,
|
36
|
+
:INDEX_STATE_SCHEDULED => :scheduled,
|
37
|
+
}.freeze
|
38
|
+
|
39
|
+
def self.to_query_index_array(resp)
|
40
|
+
resp.indexes.map do |proto_idx|
|
41
|
+
Couchbase::Management::QueryIndex.new do |idx|
|
42
|
+
idx.bucket = proto_idx.bucket_name
|
43
|
+
idx.scope = proto_idx.scope_name
|
44
|
+
idx.collection = proto_idx.collection_name
|
45
|
+
idx.name = proto_idx.name
|
46
|
+
idx.is_primary = proto_idx.is_primary
|
47
|
+
idx.type = INDEX_TYPE_MAP[proto_idx.type]
|
48
|
+
idx.state = INDEX_STATE_MAP[proto_idx.state]
|
49
|
+
idx.index_key = proto_idx.fields.to_a
|
50
|
+
idx.condition = proto_idx.condition if proto_idx.has_condition?
|
51
|
+
idx.partition = proto_idx.partition if proto_idx.has_partition?
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# Copyright 2023. Couchbase, Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
# frozen_string_literal: true
|
16
|
+
|
17
|
+
module Couchbase
|
18
|
+
module Protostellar
|
19
|
+
module ResponseConverter
|
20
|
+
module Admin
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,151 @@
|
|
1
|
+
# Copyright 2023. Couchbase, Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
# frozen_string_literal: true
|
16
|
+
|
17
|
+
require "couchbase/collection_options"
|
18
|
+
require "couchbase/binary_collection_options"
|
19
|
+
|
20
|
+
module Couchbase
|
21
|
+
module Protostellar
|
22
|
+
module ResponseConverter
|
23
|
+
class KV
|
24
|
+
def self.to_get_result(resp, options)
|
25
|
+
Couchbase::Collection::GetResult.new do |res|
|
26
|
+
res.transcoder = options.transcoder
|
27
|
+
res.cas = resp.cas
|
28
|
+
res.expiry = extract_expiry_time(resp) if options.respond_to?(:with_expiry) && options.with_expiry
|
29
|
+
res.encoded = if resp.content_uncompressed == "null" && !options.projections.empty?
|
30
|
+
"{}"
|
31
|
+
else
|
32
|
+
resp.content_uncompressed
|
33
|
+
end
|
34
|
+
res.flags = resp.content_flags
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.to_mutation_result(resp)
|
39
|
+
Couchbase::Collection::MutationResult.new do |res|
|
40
|
+
res.cas = resp.cas
|
41
|
+
res.mutation_token = extract_mutation_token(resp)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.to_exists_result(resp)
|
46
|
+
Couchbase::Collection::ExistsResult.new do |res|
|
47
|
+
res.cas = resp.cas
|
48
|
+
res.exists = resp.result
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.to_lookup_in_result(resp, specs, options, request)
|
53
|
+
Couchbase::Collection::LookupInResult.new do |res|
|
54
|
+
res.cas = resp.cas
|
55
|
+
res.transcoder = options.transcoder
|
56
|
+
res.encoded = resp.specs.each_with_index.map do |s, idx|
|
57
|
+
Couchbase::Collection::SubDocumentField.new do |f|
|
58
|
+
# TODO: What to do with the status?
|
59
|
+
error = s.status.nil? ? nil : ErrorHandling.convert_rpc_status(s.status, request)
|
60
|
+
f.error = error unless error.nil?
|
61
|
+
f.index = idx
|
62
|
+
f.path = specs[idx].path
|
63
|
+
if specs[idx].type == :exists
|
64
|
+
f.exists = s.content == "true"
|
65
|
+
f.value = s.content
|
66
|
+
elsif s.content.empty?
|
67
|
+
f.value = nil
|
68
|
+
f.exists = false
|
69
|
+
else
|
70
|
+
f.value = s.content
|
71
|
+
f.exists = true
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.to_get_any_replica_result(resps, options)
|
79
|
+
begin
|
80
|
+
entry = resps.next
|
81
|
+
rescue StopIteration
|
82
|
+
raise Couchbase::Error::DocumentIrretrievable, "unable to get replica of the document"
|
83
|
+
end
|
84
|
+
Couchbase::Collection::GetReplicaResult.new do |res|
|
85
|
+
res.transcoder = options.transcoder
|
86
|
+
res.cas = entry.cas
|
87
|
+
res.flags = entry.content_flags
|
88
|
+
res.encoded = entry.content
|
89
|
+
res.is_replica = entry.is_replica
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.to_get_all_replicas_result(resps, options)
|
94
|
+
resps.map do |entry|
|
95
|
+
Couchbase::Collection::GetReplicaResult.new do |res|
|
96
|
+
res.transcoder = options.transcoder
|
97
|
+
res.cas = entry.cas
|
98
|
+
res.flags = entry.content_flags
|
99
|
+
res.encoded = entry.content
|
100
|
+
res.is_replica = entry.is_replica
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def self.to_mutate_in_result(resp, specs, options)
|
106
|
+
Couchbase::Collection::MutateInResult.new do |res|
|
107
|
+
res.cas = resp.cas
|
108
|
+
res.transcoder = options.transcoder
|
109
|
+
res.deleted = nil # TODO: gRPC response has no deleted field
|
110
|
+
res.mutation_token = extract_mutation_token(resp)
|
111
|
+
res.encoded = resp.specs.each_with_index.map do |s, idx|
|
112
|
+
Couchbase::Collection::SubDocumentField.new do |f|
|
113
|
+
f.index = idx
|
114
|
+
f.path = specs[idx].path
|
115
|
+
f.value = s.content
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def self.to_counter_result(resp)
|
122
|
+
Couchbase::BinaryCollection::CounterResult.new do |res|
|
123
|
+
res.cas = resp.cas
|
124
|
+
res.content = resp.content
|
125
|
+
res.mutation_token = extract_mutation_token(resp)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def self.extract_mutation_token(resp)
|
130
|
+
proto_token = resp.mutation_token
|
131
|
+
return nil if proto_token.nil?
|
132
|
+
|
133
|
+
Couchbase::MutationToken.new do |token|
|
134
|
+
token.bucket_name = proto_token.bucket_name
|
135
|
+
token.partition_id = proto_token.vbucket_id
|
136
|
+
token.partition_uuid = proto_token.vbucket_uuid
|
137
|
+
token.sequence_number = proto_token.seq_no
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def self.extract_expiry_time(resp)
|
142
|
+
timestamp = resp.expiry
|
143
|
+
|
144
|
+
return nil if timestamp.nil?
|
145
|
+
|
146
|
+
Time.at(timestamp.seconds, timestamp.nanos, :nsec)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# Copyright 2023. Couchbase, Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
# frozen_string_literal: true
|
16
|
+
|
17
|
+
require "json"
|
18
|
+
|
19
|
+
require "couchbase/query_options"
|
20
|
+
|
21
|
+
module Couchbase
|
22
|
+
module Protostellar
|
23
|
+
module ResponseConverter
|
24
|
+
class Query
|
25
|
+
STATUS_MAP = {
|
26
|
+
:STATUS_RUNNING => :running,
|
27
|
+
:STATUS_SUCCESS => :success,
|
28
|
+
:STATUS_ERRORS => :errors,
|
29
|
+
:STATUS_COMPLETED => :completed,
|
30
|
+
:STATUS_STOPPED => :stopped,
|
31
|
+
:STATUS_TIMEOUT => :timeout,
|
32
|
+
:STATUS_CLOSED => :closed,
|
33
|
+
:STATUS_FATAL => :fatal,
|
34
|
+
:STATUS_ABORTED => :aborted,
|
35
|
+
:STATUS_UNKNOWN => :unknown,
|
36
|
+
}.freeze
|
37
|
+
|
38
|
+
def self.to_query_result(resps)
|
39
|
+
Couchbase::Cluster::QueryResult.new do |res|
|
40
|
+
rows = []
|
41
|
+
resps.each do |resp|
|
42
|
+
rows.push(*resp.rows)
|
43
|
+
res.meta_data = convert_query_metadata(resp.meta_data) unless resp.meta_data.nil?
|
44
|
+
end
|
45
|
+
res.instance_variable_set(:@rows, rows)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.convert_query_metadata(proto_metadata)
|
50
|
+
Couchbase::Cluster::QueryMetaData.new do |meta|
|
51
|
+
meta.status = STATUS_MAP[proto_metadata.status]
|
52
|
+
meta.request_id = proto_metadata.request_id
|
53
|
+
meta.client_context_id = proto_metadata.client_context_id
|
54
|
+
meta.signature = JSON.parse(proto_metadata.signature) unless proto_metadata.signature.nil? || proto_metadata.signature.empty?
|
55
|
+
meta.profile = JSON.parse(proto_metadata.profile) unless proto_metadata.profile.nil? || proto_metadata.profile.empty?
|
56
|
+
meta.metrics = if proto_metadata.has_metrics?
|
57
|
+
convert_query_metrics(proto_metadata.metrics)
|
58
|
+
else
|
59
|
+
Couchbase::Cluster::QueryMetrics.new
|
60
|
+
end
|
61
|
+
meta.warnings = proto_metadata.warnings.map { |w| convert_query_warning(w) } unless proto_metadata.warnings.empty?
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.convert_query_warning(proto_warning)
|
66
|
+
Couchbase::Cluster::QueryWarning.new(proto_warning.code, proto_warning.message)
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.convert_query_metrics(proto_metrics)
|
70
|
+
Couchbase::Cluster::QueryMetrics.new do |metrics|
|
71
|
+
metrics.elapsed_time = proto_metrics.elapsed_time.nanos + (proto_metrics.elapsed_time.seconds * (10**9))
|
72
|
+
metrics.execution_time = proto_metrics.execution_time.nanos + (proto_metrics.execution_time.seconds * (10**9))
|
73
|
+
metrics.result_count = proto_metrics.result_count
|
74
|
+
metrics.result_size = proto_metrics.result_size
|
75
|
+
metrics.mutation_count = proto_metrics.mutation_count
|
76
|
+
metrics.sort_count = proto_metrics.sort_count
|
77
|
+
metrics.error_count = proto_metrics.error_count
|
78
|
+
metrics.warning_count = proto_metrics.warning_count
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
# Copyright 2023. Couchbase, Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
# frozen_string_literal: true
|
16
|
+
|
17
|
+
require "couchbase/search_options"
|
18
|
+
|
19
|
+
module Couchbase
|
20
|
+
module Protostellar
|
21
|
+
module ResponseConverter
|
22
|
+
class Search
|
23
|
+
def self.to_search_result(resps, options)
|
24
|
+
Couchbase::Cluster::SearchResult.new do |res|
|
25
|
+
res.rows = []
|
26
|
+
res.facets = {}
|
27
|
+
resps.each do |resp|
|
28
|
+
resp.hits.each do |hit|
|
29
|
+
res.rows.append(convert_search_row(hit, options))
|
30
|
+
end
|
31
|
+
resp.facets.each do |k, facet_res|
|
32
|
+
res.facets[k] = convert_facet_result(facet_res)
|
33
|
+
end
|
34
|
+
res.meta_data = convert_meta_data(resp.meta_data) if resp.has_meta_data?
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.convert_search_row(proto_row, options)
|
40
|
+
Couchbase::Cluster::SearchRow.new do |r|
|
41
|
+
r.instance_variable_set(:@fields, (proto_row.fields.to_h.transform_values { |v| JSON.parse(v) }).to_json)
|
42
|
+
r.transcoder = options.transcoder
|
43
|
+
r.index = proto_row.index
|
44
|
+
r.id = proto_row.id
|
45
|
+
r.score = proto_row.score.to_f
|
46
|
+
unless proto_row.locations.empty?
|
47
|
+
r.locations = Couchbase::Cluster::SearchRowLocations.new(
|
48
|
+
proto_row.locations.map { |loc| convert_search_row_location(loc) }
|
49
|
+
)
|
50
|
+
end
|
51
|
+
r.fragments = convert_fragments(proto_row.fragments)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.convert_fragments(proto_fragments)
|
56
|
+
proto_fragments.to_h.transform_values { |f| f.content.to_a }
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.convert_search_row_location(proto_location)
|
60
|
+
Couchbase::Cluster::SearchRowLocation.new do |loc|
|
61
|
+
loc.field = proto_location.field
|
62
|
+
loc.term = proto_location.term
|
63
|
+
loc.position = proto_location.position
|
64
|
+
loc.start_offset = proto_location.start
|
65
|
+
loc.end_offset = proto_location.end
|
66
|
+
loc.array_positions = proto_location.array_positions.to_a
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.convert_facet_result(proto_facet_res)
|
71
|
+
facet_type = proto_facet_res.search_facet
|
72
|
+
case facet_type
|
73
|
+
when :term_facet
|
74
|
+
res = proto_facet_res.term_facet
|
75
|
+
Couchbase::Cluster::SearchFacetResult::TermFacetResult.new do |f|
|
76
|
+
f.name = res.name
|
77
|
+
f.field = res.field
|
78
|
+
f.total = res.total
|
79
|
+
f.missing = res.missing
|
80
|
+
f.other = res.other
|
81
|
+
f.terms = res.terms.map do |term_res|
|
82
|
+
Couchbase::Cluster::SearchFacetResult::TermFacetResult::TermFacet.new(term_res.name, term_res.size)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
when :date_range_facet
|
86
|
+
res = proto_facet_res.date_range_facet
|
87
|
+
Couchbase::Cluster::SearchFacetResult::DateRangeFacetResult.new do |f|
|
88
|
+
f.name = res.name
|
89
|
+
f.field = res.field
|
90
|
+
f.total = res.total
|
91
|
+
f.missing = res.missing
|
92
|
+
f.other = res.other
|
93
|
+
f.date_ranges = res.date_ranges.map do |date_range|
|
94
|
+
start_time = Time.at(date_range.start.seconds).strftime("%Y-%m-%d")
|
95
|
+
end_time = Time.at(date_range.end.seconds).strftime("%Y-%m-%d")
|
96
|
+
Couchbase::Cluster::SearchFacetResult::DateRangeFacetResult::DateRangeFacet.new(
|
97
|
+
date_range.name, date_range.size, start_time, end_time
|
98
|
+
)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
when :numeric_range_facet
|
102
|
+
res = proto_facet_res.numeric_range_facet
|
103
|
+
Couchbase::Cluster::SearchFacetResult::NumericRangeFacetResult.new do |f|
|
104
|
+
f.name = res.name
|
105
|
+
f.field = res.field
|
106
|
+
f.total = res.total
|
107
|
+
f.missing = res.missing
|
108
|
+
f.other = res.other
|
109
|
+
f.numeric_ranges = res.numeric_ranges.map do |numeric_range|
|
110
|
+
Couchbase::Cluster::NumericRangeResult::NumericRangeFacetResult::NumericRangeFacet.new(
|
111
|
+
numeric_range.name, numeric_range.size, numeric_range.min, numeric_range.max
|
112
|
+
)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
else
|
116
|
+
raise ProtostellarError, "Unrecognised facet type"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def self.convert_meta_data(proto_meta_data)
|
121
|
+
Couchbase::Cluster::SearchMetaData.new do |meta|
|
122
|
+
proto_metrics = proto_meta_data.metrics
|
123
|
+
dur = proto_metrics.execution_time
|
124
|
+
meta.metrics.took = (dur.seconds * 1000) + (dur.nanos / 1000.0).round # `took` is in milliseconds
|
125
|
+
meta.metrics.total_rows = proto_metrics.total_rows
|
126
|
+
meta.metrics.max_score = proto_metrics.max_score
|
127
|
+
meta.metrics.success_partition_count = proto_metrics.success_partition_count
|
128
|
+
meta.metrics.error_partition_count = proto_metrics.error_partition_count
|
129
|
+
|
130
|
+
meta.errors = proto_meta_data.errors.to_h
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# Copyright 2023. Couchbase, Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
# frozen_string_literal: true
|
16
|
+
|
17
|
+
require_relative "response_converter/kv"
|
18
|
+
require_relative "response_converter/query"
|
19
|
+
|
20
|
+
module Couchbase
|
21
|
+
module Protostellar
|
22
|
+
# @api private
|
23
|
+
module ResponseConverter
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# Copyright 2023. Couchbase, Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
# frozen_string_literal: true
|
16
|
+
|
17
|
+
module Couchbase
|
18
|
+
module Protostellar
|
19
|
+
module Retry
|
20
|
+
# @api private
|
21
|
+
class Action
|
22
|
+
attr_reader :duration
|
23
|
+
|
24
|
+
def initialize(duration)
|
25
|
+
@duration = duration
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.with_duration(duration)
|
29
|
+
Action.new(duration)
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.no_retry
|
33
|
+
Action.new(nil)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# Copyright 2023. Couchbase, Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
# frozen_string_literal: true
|
16
|
+
|
17
|
+
require_relative '../request_behaviour'
|
18
|
+
require_relative 'action'
|
19
|
+
require 'couchbase/errors'
|
20
|
+
require 'couchbase/logger'
|
21
|
+
|
22
|
+
module Couchbase
|
23
|
+
module Protostellar
|
24
|
+
module Retry
|
25
|
+
# @api private
|
26
|
+
class Orchestrator
|
27
|
+
def self.maybe_retry(request, reason)
|
28
|
+
if reason.always_retry
|
29
|
+
retry_duration = get_controlled_backoff(request)
|
30
|
+
request.add_retry_attempt(reason)
|
31
|
+
# TODO: Log retry
|
32
|
+
RequestBehaviour.retry(retry_duration)
|
33
|
+
else
|
34
|
+
retry_action = request.retry_strategy.retry_after(request, reason)
|
35
|
+
duration = retry_action.duration
|
36
|
+
if duration.nil?
|
37
|
+
# TODO: Log not retried
|
38
|
+
RequestBehaviour.fail(Couchbase::Error::RequestCanceled.new('Cannot retry request', request.error_context))
|
39
|
+
else
|
40
|
+
request.add_retry_attempt(reason)
|
41
|
+
# TODO: Log retry
|
42
|
+
RequestBehaviour.retry(duration)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.get_controlled_backoff(request)
|
48
|
+
case request.retry_attempts
|
49
|
+
when 0 then 1
|
50
|
+
when 1 then 10
|
51
|
+
when 2 then 50
|
52
|
+
when 3 then 100
|
53
|
+
when 4 then 500
|
54
|
+
else 1000
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# Copyright 2023. Couchbase, Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
# frozen_string_literal: true
|
16
|
+
|
17
|
+
module Couchbase
|
18
|
+
module Protostellar
|
19
|
+
module Retry
|
20
|
+
class Reason
|
21
|
+
attr_reader :allows_non_idempotent_retry
|
22
|
+
attr_reader :always_retry
|
23
|
+
attr_reader :name
|
24
|
+
|
25
|
+
def self.reason(name, allows_non_idempotent_retry:, always_retry:)
|
26
|
+
const_set(
|
27
|
+
name,
|
28
|
+
new(name: name,
|
29
|
+
allows_non_idempotent_retry: allows_non_idempotent_retry,
|
30
|
+
always_retry: always_retry).freeze
|
31
|
+
)
|
32
|
+
end
|
33
|
+
|
34
|
+
def initialize(name:, allows_non_idempotent_retry:, always_retry:)
|
35
|
+
@name = name
|
36
|
+
@allows_non_idempotent_retry = allows_non_idempotent_retry
|
37
|
+
@always_retry = always_retry
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_s
|
41
|
+
@name.downcase.to_s
|
42
|
+
end
|
43
|
+
|
44
|
+
reason :UNKNOWN, allows_non_idempotent_retry: false, always_retry: false
|
45
|
+
reason :SOCKET_NOT_AVAILABLE, allows_non_idempotent_retry: true, always_retry: false
|
46
|
+
reason :SERVICE_NOT_AVAILABLE, allows_non_idempotent_retry: true, always_retry: false
|
47
|
+
reason :NODE_NOT_AVAILABLE, allows_non_idempotent_retry: true, always_retry: false
|
48
|
+
reason :KV_NOT_MY_VBUCKET, allows_non_idempotent_retry: true, always_retry: true
|
49
|
+
reason :KV_COLLECTION_OUTDATED, allows_non_idempotent_retry: true, always_retry: true
|
50
|
+
reason :KV_ERROR_MAP_RETRY_INDICATED, allows_non_idempotent_retry: true, always_retry: false
|
51
|
+
reason :KV_LOCKED, allows_non_idempotent_retry: true, always_retry: false
|
52
|
+
reason :KV_TEMPORARY_FAILURE, allows_non_idempotent_retry: true, always_retry: false
|
53
|
+
reason :KV_SYNC_WRITE_IN_PROGRESS, allows_non_idempotent_retry: true, always_retry: false
|
54
|
+
reason :KV_SYNC_WRITE_RE_COMMIT_IN_PROGRESS, allows_non_idempotent_retry: true, always_retry: false
|
55
|
+
reason :SERVICE_RESPONSE_CODE_INDICATED, allows_non_idempotent_retry: true, always_retry: false
|
56
|
+
reason :SOCKET_CLOSED_WHILE_IN_FLIGHT, allows_non_idempotent_retry: false, always_retry: false
|
57
|
+
reason :CIRCUIT_BREAKER_OPEN, allows_non_idempotent_retry: true, always_retry: false
|
58
|
+
reason :QUERY_PREPARED_STATEMENT_FAILURE, allows_non_idempotent_retry: true, always_retry: false
|
59
|
+
reason :QUERY_INDEX_NOT_FOUND, allows_non_idempotent_retry: true, always_retry: false
|
60
|
+
reason :ANALYTICS_TEMPORARY_FAILURE, allows_non_idempotent_retry: true, always_retry: false
|
61
|
+
reason :SEARCH_TOO_MANY_REQUESTS, allows_non_idempotent_retry: true, always_retry: false
|
62
|
+
reason :VIEWS_TEMPORARY_FAILURE, allows_non_idempotent_retry: true, always_retry: false
|
63
|
+
reason :VIEWS_NO_ACTIVE_PARTITION, allows_non_idempotent_retry: true, always_retry: true
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|