couchbase 3.5.0-arm64-darwin-22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +202 -0
  3. data/README.md +154 -0
  4. data/ext/extconf.rb +0 -0
  5. data/lib/active_support/cache/couchbase_store.rb +339 -0
  6. data/lib/couchbase/3.0/libcouchbase.bundle +0 -0
  7. data/lib/couchbase/3.1/libcouchbase.bundle +0 -0
  8. data/lib/couchbase/3.2/libcouchbase.bundle +0 -0
  9. data/lib/couchbase/3.3/libcouchbase.bundle +0 -0
  10. data/lib/couchbase/analytics_options.rb +107 -0
  11. data/lib/couchbase/authenticator.rb +64 -0
  12. data/lib/couchbase/binary_collection.rb +128 -0
  13. data/lib/couchbase/binary_collection_options.rb +24 -0
  14. data/lib/couchbase/bucket.rb +144 -0
  15. data/lib/couchbase/cluster.rb +460 -0
  16. data/lib/couchbase/cluster_registry.rb +49 -0
  17. data/lib/couchbase/collection.rb +705 -0
  18. data/lib/couchbase/collection_options.rb +399 -0
  19. data/lib/couchbase/config_profiles.rb +55 -0
  20. data/lib/couchbase/configuration.rb +56 -0
  21. data/lib/couchbase/datastructures/couchbase_list.rb +160 -0
  22. data/lib/couchbase/datastructures/couchbase_map.rb +194 -0
  23. data/lib/couchbase/datastructures/couchbase_queue.rb +134 -0
  24. data/lib/couchbase/datastructures/couchbase_set.rb +128 -0
  25. data/lib/couchbase/datastructures.rb +24 -0
  26. data/lib/couchbase/diagnostics.rb +181 -0
  27. data/lib/couchbase/errors.rb +376 -0
  28. data/lib/couchbase/json_transcoder.rb +39 -0
  29. data/lib/couchbase/key_value_scan.rb +117 -0
  30. data/lib/couchbase/libcouchbase.rb +6 -0
  31. data/lib/couchbase/logger.rb +85 -0
  32. data/lib/couchbase/management/analytics_index_manager.rb +1127 -0
  33. data/lib/couchbase/management/bucket_manager.rb +443 -0
  34. data/lib/couchbase/management/collection_manager.rb +470 -0
  35. data/lib/couchbase/management/collection_query_index_manager.rb +222 -0
  36. data/lib/couchbase/management/query_index_manager.rb +617 -0
  37. data/lib/couchbase/management/scope_search_index_manager.rb +198 -0
  38. data/lib/couchbase/management/search_index_manager.rb +424 -0
  39. data/lib/couchbase/management/user_manager.rb +468 -0
  40. data/lib/couchbase/management/view_index_manager.rb +237 -0
  41. data/lib/couchbase/management.rb +29 -0
  42. data/lib/couchbase/mutation_state.rb +63 -0
  43. data/lib/couchbase/options.rb +2837 -0
  44. data/lib/couchbase/protostellar/binary_collection.rb +55 -0
  45. data/lib/couchbase/protostellar/bucket.rb +51 -0
  46. data/lib/couchbase/protostellar/client.rb +99 -0
  47. data/lib/couchbase/protostellar/cluster.rb +163 -0
  48. data/lib/couchbase/protostellar/collection.rb +152 -0
  49. data/lib/couchbase/protostellar/connect_options.rb +63 -0
  50. data/lib/couchbase/protostellar/error_handling.rb +203 -0
  51. data/lib/couchbase/protostellar/generated/admin/bucket/v1/bucket_pb.rb +61 -0
  52. data/lib/couchbase/protostellar/generated/admin/bucket/v1/bucket_services_pb.rb +35 -0
  53. data/lib/couchbase/protostellar/generated/admin/collection/v1/collection_pb.rb +57 -0
  54. data/lib/couchbase/protostellar/generated/admin/collection/v1/collection_services_pb.rb +36 -0
  55. data/lib/couchbase/protostellar/generated/admin/query/v1/query_pb.rb +61 -0
  56. data/lib/couchbase/protostellar/generated/admin/query/v1/query_services_pb.rb +37 -0
  57. data/lib/couchbase/protostellar/generated/admin/search/v1/search_pb.rb +72 -0
  58. data/lib/couchbase/protostellar/generated/admin/search/v1/search_services_pb.rb +44 -0
  59. data/lib/couchbase/protostellar/generated/analytics/v1/analytics_pb.rb +52 -0
  60. data/lib/couchbase/protostellar/generated/analytics/v1/analytics_services_pb.rb +30 -0
  61. data/lib/couchbase/protostellar/generated/internal/hooks/v1/hooks_pb.rb +70 -0
  62. data/lib/couchbase/protostellar/generated/internal/hooks/v1/hooks_services_pb.rb +36 -0
  63. data/lib/couchbase/protostellar/generated/kv/v1/kv_pb.rb +97 -0
  64. data/lib/couchbase/protostellar/generated/kv/v1/kv_services_pb.rb +46 -0
  65. data/lib/couchbase/protostellar/generated/query/v1/query_pb.rb +57 -0
  66. data/lib/couchbase/protostellar/generated/query/v1/query_services_pb.rb +30 -0
  67. data/lib/couchbase/protostellar/generated/routing/v1/routing_pb.rb +52 -0
  68. data/lib/couchbase/protostellar/generated/routing/v1/routing_services_pb.rb +30 -0
  69. data/lib/couchbase/protostellar/generated/search/v1/search_pb.rb +99 -0
  70. data/lib/couchbase/protostellar/generated/search/v1/search_services_pb.rb +30 -0
  71. data/lib/couchbase/protostellar/generated/transactions/v1/transactions_pb.rb +57 -0
  72. data/lib/couchbase/protostellar/generated/transactions/v1/transactions_services_pb.rb +36 -0
  73. data/lib/couchbase/protostellar/generated/view/v1/view_pb.rb +51 -0
  74. data/lib/couchbase/protostellar/generated/view/v1/view_services_pb.rb +30 -0
  75. data/lib/couchbase/protostellar/generated.rb +9 -0
  76. data/lib/couchbase/protostellar/management/bucket_manager.rb +67 -0
  77. data/lib/couchbase/protostellar/management/collection_manager.rb +94 -0
  78. data/lib/couchbase/protostellar/management/collection_query_index_manager.rb +124 -0
  79. data/lib/couchbase/protostellar/management/query_index_manager.rb +112 -0
  80. data/lib/couchbase/protostellar/management.rb +24 -0
  81. data/lib/couchbase/protostellar/request.rb +78 -0
  82. data/lib/couchbase/protostellar/request_behaviour.rb +42 -0
  83. data/lib/couchbase/protostellar/request_generator/admin/bucket.rb +124 -0
  84. data/lib/couchbase/protostellar/request_generator/admin/collection.rb +94 -0
  85. data/lib/couchbase/protostellar/request_generator/admin/query.rb +130 -0
  86. data/lib/couchbase/protostellar/request_generator/admin.rb +24 -0
  87. data/lib/couchbase/protostellar/request_generator/kv.rb +474 -0
  88. data/lib/couchbase/protostellar/request_generator/query.rb +133 -0
  89. data/lib/couchbase/protostellar/request_generator/search.rb +387 -0
  90. data/lib/couchbase/protostellar/request_generator.rb +26 -0
  91. data/lib/couchbase/protostellar/response_converter/admin/bucket.rb +55 -0
  92. data/lib/couchbase/protostellar/response_converter/admin/collection.rb +42 -0
  93. data/lib/couchbase/protostellar/response_converter/admin/query.rb +59 -0
  94. data/lib/couchbase/protostellar/response_converter/admin.rb +24 -0
  95. data/lib/couchbase/protostellar/response_converter/kv.rb +151 -0
  96. data/lib/couchbase/protostellar/response_converter/query.rb +84 -0
  97. data/lib/couchbase/protostellar/response_converter/search.rb +136 -0
  98. data/lib/couchbase/protostellar/response_converter.rb +26 -0
  99. data/lib/couchbase/protostellar/retry/action.rb +38 -0
  100. data/lib/couchbase/protostellar/retry/orchestrator.rb +60 -0
  101. data/lib/couchbase/protostellar/retry/reason.rb +67 -0
  102. data/lib/couchbase/protostellar/retry/strategies/best_effort.rb +49 -0
  103. data/lib/couchbase/protostellar/retry/strategies.rb +26 -0
  104. data/lib/couchbase/protostellar/retry.rb +28 -0
  105. data/lib/couchbase/protostellar/scope.rb +57 -0
  106. data/lib/couchbase/protostellar/timeout_defaults.rb +30 -0
  107. data/lib/couchbase/protostellar/timeouts.rb +83 -0
  108. data/lib/couchbase/protostellar.rb +29 -0
  109. data/lib/couchbase/query_options.rb +120 -0
  110. data/lib/couchbase/railtie.rb +45 -0
  111. data/lib/couchbase/raw_binary_transcoder.rb +37 -0
  112. data/lib/couchbase/raw_json_transcoder.rb +38 -0
  113. data/lib/couchbase/raw_string_transcoder.rb +40 -0
  114. data/lib/couchbase/scope.rb +256 -0
  115. data/lib/couchbase/search_options.rb +1622 -0
  116. data/lib/couchbase/subdoc.rb +290 -0
  117. data/lib/couchbase/transcoder_flags.rb +62 -0
  118. data/lib/couchbase/utils/generic_logger_adapter.rb +38 -0
  119. data/lib/couchbase/utils/stdlib_logger_adapter.rb +65 -0
  120. data/lib/couchbase/utils/time.rb +69 -0
  121. data/lib/couchbase/utils.rb +21 -0
  122. data/lib/couchbase/version.rb +23 -0
  123. data/lib/couchbase/view_options.rb +65 -0
  124. data/lib/couchbase.rb +28 -0
  125. data/lib/rails/generators/couchbase/config/config_generator.rb +27 -0
  126. metadata +191 -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