couchbase 3.5.0-x86_64-linux-musl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (125) 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.1/libcouchbase.so +0 -0
  7. data/lib/couchbase/3.2/libcouchbase.so +0 -0
  8. data/lib/couchbase/3.3/libcouchbase.so +0 -0
  9. data/lib/couchbase/analytics_options.rb +107 -0
  10. data/lib/couchbase/authenticator.rb +64 -0
  11. data/lib/couchbase/binary_collection.rb +128 -0
  12. data/lib/couchbase/binary_collection_options.rb +24 -0
  13. data/lib/couchbase/bucket.rb +144 -0
  14. data/lib/couchbase/cluster.rb +460 -0
  15. data/lib/couchbase/cluster_registry.rb +49 -0
  16. data/lib/couchbase/collection.rb +705 -0
  17. data/lib/couchbase/collection_options.rb +399 -0
  18. data/lib/couchbase/config_profiles.rb +55 -0
  19. data/lib/couchbase/configuration.rb +56 -0
  20. data/lib/couchbase/datastructures/couchbase_list.rb +160 -0
  21. data/lib/couchbase/datastructures/couchbase_map.rb +194 -0
  22. data/lib/couchbase/datastructures/couchbase_queue.rb +134 -0
  23. data/lib/couchbase/datastructures/couchbase_set.rb +128 -0
  24. data/lib/couchbase/datastructures.rb +24 -0
  25. data/lib/couchbase/diagnostics.rb +181 -0
  26. data/lib/couchbase/errors.rb +376 -0
  27. data/lib/couchbase/json_transcoder.rb +39 -0
  28. data/lib/couchbase/key_value_scan.rb +117 -0
  29. data/lib/couchbase/libcouchbase.rb +6 -0
  30. data/lib/couchbase/logger.rb +85 -0
  31. data/lib/couchbase/management/analytics_index_manager.rb +1127 -0
  32. data/lib/couchbase/management/bucket_manager.rb +443 -0
  33. data/lib/couchbase/management/collection_manager.rb +470 -0
  34. data/lib/couchbase/management/collection_query_index_manager.rb +222 -0
  35. data/lib/couchbase/management/query_index_manager.rb +617 -0
  36. data/lib/couchbase/management/scope_search_index_manager.rb +198 -0
  37. data/lib/couchbase/management/search_index_manager.rb +424 -0
  38. data/lib/couchbase/management/user_manager.rb +468 -0
  39. data/lib/couchbase/management/view_index_manager.rb +237 -0
  40. data/lib/couchbase/management.rb +29 -0
  41. data/lib/couchbase/mutation_state.rb +63 -0
  42. data/lib/couchbase/options.rb +2837 -0
  43. data/lib/couchbase/protostellar/binary_collection.rb +55 -0
  44. data/lib/couchbase/protostellar/bucket.rb +51 -0
  45. data/lib/couchbase/protostellar/client.rb +99 -0
  46. data/lib/couchbase/protostellar/cluster.rb +163 -0
  47. data/lib/couchbase/protostellar/collection.rb +152 -0
  48. data/lib/couchbase/protostellar/connect_options.rb +63 -0
  49. data/lib/couchbase/protostellar/error_handling.rb +203 -0
  50. data/lib/couchbase/protostellar/generated/admin/bucket/v1/bucket_pb.rb +61 -0
  51. data/lib/couchbase/protostellar/generated/admin/bucket/v1/bucket_services_pb.rb +35 -0
  52. data/lib/couchbase/protostellar/generated/admin/collection/v1/collection_pb.rb +57 -0
  53. data/lib/couchbase/protostellar/generated/admin/collection/v1/collection_services_pb.rb +36 -0
  54. data/lib/couchbase/protostellar/generated/admin/query/v1/query_pb.rb +61 -0
  55. data/lib/couchbase/protostellar/generated/admin/query/v1/query_services_pb.rb +37 -0
  56. data/lib/couchbase/protostellar/generated/admin/search/v1/search_pb.rb +72 -0
  57. data/lib/couchbase/protostellar/generated/admin/search/v1/search_services_pb.rb +44 -0
  58. data/lib/couchbase/protostellar/generated/analytics/v1/analytics_pb.rb +52 -0
  59. data/lib/couchbase/protostellar/generated/analytics/v1/analytics_services_pb.rb +30 -0
  60. data/lib/couchbase/protostellar/generated/internal/hooks/v1/hooks_pb.rb +70 -0
  61. data/lib/couchbase/protostellar/generated/internal/hooks/v1/hooks_services_pb.rb +36 -0
  62. data/lib/couchbase/protostellar/generated/kv/v1/kv_pb.rb +97 -0
  63. data/lib/couchbase/protostellar/generated/kv/v1/kv_services_pb.rb +46 -0
  64. data/lib/couchbase/protostellar/generated/query/v1/query_pb.rb +57 -0
  65. data/lib/couchbase/protostellar/generated/query/v1/query_services_pb.rb +30 -0
  66. data/lib/couchbase/protostellar/generated/routing/v1/routing_pb.rb +52 -0
  67. data/lib/couchbase/protostellar/generated/routing/v1/routing_services_pb.rb +30 -0
  68. data/lib/couchbase/protostellar/generated/search/v1/search_pb.rb +99 -0
  69. data/lib/couchbase/protostellar/generated/search/v1/search_services_pb.rb +30 -0
  70. data/lib/couchbase/protostellar/generated/transactions/v1/transactions_pb.rb +57 -0
  71. data/lib/couchbase/protostellar/generated/transactions/v1/transactions_services_pb.rb +36 -0
  72. data/lib/couchbase/protostellar/generated/view/v1/view_pb.rb +51 -0
  73. data/lib/couchbase/protostellar/generated/view/v1/view_services_pb.rb +30 -0
  74. data/lib/couchbase/protostellar/generated.rb +9 -0
  75. data/lib/couchbase/protostellar/management/bucket_manager.rb +67 -0
  76. data/lib/couchbase/protostellar/management/collection_manager.rb +94 -0
  77. data/lib/couchbase/protostellar/management/collection_query_index_manager.rb +124 -0
  78. data/lib/couchbase/protostellar/management/query_index_manager.rb +112 -0
  79. data/lib/couchbase/protostellar/management.rb +24 -0
  80. data/lib/couchbase/protostellar/request.rb +78 -0
  81. data/lib/couchbase/protostellar/request_behaviour.rb +42 -0
  82. data/lib/couchbase/protostellar/request_generator/admin/bucket.rb +124 -0
  83. data/lib/couchbase/protostellar/request_generator/admin/collection.rb +94 -0
  84. data/lib/couchbase/protostellar/request_generator/admin/query.rb +130 -0
  85. data/lib/couchbase/protostellar/request_generator/admin.rb +24 -0
  86. data/lib/couchbase/protostellar/request_generator/kv.rb +474 -0
  87. data/lib/couchbase/protostellar/request_generator/query.rb +133 -0
  88. data/lib/couchbase/protostellar/request_generator/search.rb +387 -0
  89. data/lib/couchbase/protostellar/request_generator.rb +26 -0
  90. data/lib/couchbase/protostellar/response_converter/admin/bucket.rb +55 -0
  91. data/lib/couchbase/protostellar/response_converter/admin/collection.rb +42 -0
  92. data/lib/couchbase/protostellar/response_converter/admin/query.rb +59 -0
  93. data/lib/couchbase/protostellar/response_converter/admin.rb +24 -0
  94. data/lib/couchbase/protostellar/response_converter/kv.rb +151 -0
  95. data/lib/couchbase/protostellar/response_converter/query.rb +84 -0
  96. data/lib/couchbase/protostellar/response_converter/search.rb +136 -0
  97. data/lib/couchbase/protostellar/response_converter.rb +26 -0
  98. data/lib/couchbase/protostellar/retry/action.rb +38 -0
  99. data/lib/couchbase/protostellar/retry/orchestrator.rb +60 -0
  100. data/lib/couchbase/protostellar/retry/reason.rb +67 -0
  101. data/lib/couchbase/protostellar/retry/strategies/best_effort.rb +49 -0
  102. data/lib/couchbase/protostellar/retry/strategies.rb +26 -0
  103. data/lib/couchbase/protostellar/retry.rb +28 -0
  104. data/lib/couchbase/protostellar/scope.rb +57 -0
  105. data/lib/couchbase/protostellar/timeout_defaults.rb +30 -0
  106. data/lib/couchbase/protostellar/timeouts.rb +83 -0
  107. data/lib/couchbase/protostellar.rb +29 -0
  108. data/lib/couchbase/query_options.rb +120 -0
  109. data/lib/couchbase/railtie.rb +45 -0
  110. data/lib/couchbase/raw_binary_transcoder.rb +37 -0
  111. data/lib/couchbase/raw_json_transcoder.rb +38 -0
  112. data/lib/couchbase/raw_string_transcoder.rb +40 -0
  113. data/lib/couchbase/scope.rb +256 -0
  114. data/lib/couchbase/search_options.rb +1622 -0
  115. data/lib/couchbase/subdoc.rb +290 -0
  116. data/lib/couchbase/transcoder_flags.rb +62 -0
  117. data/lib/couchbase/utils/generic_logger_adapter.rb +38 -0
  118. data/lib/couchbase/utils/stdlib_logger_adapter.rb +65 -0
  119. data/lib/couchbase/utils/time.rb +69 -0
  120. data/lib/couchbase/utils.rb +21 -0
  121. data/lib/couchbase/version.rb +23 -0
  122. data/lib/couchbase/view_options.rb +65 -0
  123. data/lib/couchbase.rb +28 -0
  124. data/lib/rails/generators/couchbase/config/config_generator.rb +27 -0
  125. metadata +190 -0
@@ -0,0 +1,130 @@
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/protostellar/generated/admin/query/v1/query_pb"
18
+ require "couchbase/protostellar/request"
19
+
20
+ module Couchbase
21
+ module Protostellar
22
+ module RequestGenerator
23
+ module Admin
24
+ class Query
25
+ def initialize(bucket_name: nil, scope_name: nil, collection_name: nil)
26
+ @bucket_name = bucket_name
27
+ @scope_name = scope_name
28
+ @collection_name = collection_name
29
+ end
30
+
31
+ def get_all_indexes_request(options, bucket_name = nil)
32
+ proto_req = Generated::Admin::Query::V1::GetAllIndexesRequest.new(
33
+ **location(
34
+ bucket_name: bucket_name, scope_name: options.scope_name, collection_name: options.collection_name
35
+ )
36
+ )
37
+
38
+ create_request(proto_req, :get_all_indexes, options, idempotent: true)
39
+ end
40
+
41
+ def create_primary_index_request(options, bucket_name = nil)
42
+ proto_opts = {
43
+ deferred: options.deferred,
44
+ }
45
+ proto_opts[:name] = options.index_name unless options.index_name.nil?
46
+ proto_opts[:num_replicas] = options.num_replicas unless options.num_replicas.nil?
47
+
48
+ proto_req = Generated::Admin::Query::V1::CreatePrimaryIndexRequest.new(
49
+ **location(
50
+ bucket_name: bucket_name, scope_name: options.scope_name, collection_name: options.collection_name
51
+ ),
52
+ **proto_opts
53
+ )
54
+
55
+ create_request(proto_req, :create_primary_index, options)
56
+ end
57
+
58
+ def create_index_request(index_name, fields, options, bucket_name = nil)
59
+ proto_opts = {
60
+ deferred: options.deferred,
61
+ }
62
+ proto_opts[:num_replicas] = options.num_replicas unless options.num_replicas.nil?
63
+
64
+ proto_req = Generated::Admin::Query::V1::CreateIndexRequest.new(
65
+ **location(
66
+ bucket_name: bucket_name, scope_name: options.scope_name, collection_name: options.collection_name
67
+ ),
68
+ name: index_name,
69
+ fields: fields,
70
+ **proto_opts
71
+ )
72
+
73
+ create_request(proto_req, :create_index, options)
74
+ end
75
+
76
+ def drop_primary_index_request(options, bucket_name = nil)
77
+ proto_req = Generated::Admin::Query::V1::DropPrimaryIndexRequest.new(
78
+ **location(
79
+ bucket_name: bucket_name, scope_name: options.scope_name, collection_name: options.collection_name
80
+ )
81
+ )
82
+
83
+ create_request(proto_req, :drop_primary_index, options)
84
+ end
85
+
86
+ def drop_index_request(index_name, options, bucket_name = nil)
87
+ proto_req = Generated::Admin::Query::V1::DropIndexRequest.new(
88
+ **location(
89
+ bucket_name: bucket_name, scope_name: options.scope_name, collection_name: options.collection_name
90
+ ),
91
+ name: index_name
92
+ )
93
+
94
+ create_request(proto_req, :drop_index, options)
95
+ end
96
+
97
+ def build_deferred_indexes_request(options, bucket_name = nil)
98
+ proto_req = Generated::Admin::Query::V1::BuildDeferredIndexesRequest.new(
99
+ **location(
100
+ bucket_name: bucket_name, scope_name: options.scope_name, collection_name: options.collection_name
101
+ )
102
+ )
103
+
104
+ create_request(proto_req, :build_deferred_indexes, options)
105
+ end
106
+
107
+ private
108
+
109
+ def location(bucket_name: nil, scope_name: nil, collection_name: nil)
110
+ {
111
+ bucket_name: @bucket_name || bucket_name,
112
+ scope_name: @scope_name || scope_name,
113
+ collection_name: @collection_name || collection_name,
114
+ }.compact
115
+ end
116
+
117
+ def create_request(proto_request, rpc, options, idempotent: false)
118
+ Request.new(
119
+ service: :query_admin,
120
+ rpc: rpc,
121
+ proto_request: proto_request,
122
+ idempotent: idempotent,
123
+ timeout: options.timeout
124
+ )
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
130
+ 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 RequestGenerator
20
+ module Admin
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,474 @@
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/json_transcoder"
18
+ require "couchbase/utils/time"
19
+ require "couchbase/errors"
20
+
21
+ require "couchbase/protostellar/generated/kv/v1/kv_pb"
22
+ require "couchbase/protostellar/request"
23
+
24
+ require "google/protobuf/well_known_types"
25
+
26
+ module Couchbase
27
+ module Protostellar
28
+ module RequestGenerator
29
+ class KV
30
+ DURABILITY_LEVEL_MAP = {
31
+ :majority => :DURABILITY_LEVEL_MAJORITY,
32
+ :majority_and_persist_to_active => :DURABILITY_LEVEL_MAJORITY_AND_PERSIST_TO_ACTIVE,
33
+ :persist_to_majority => :DURABILITY_LEVEL_PERSIST_TO_MAJORITY,
34
+ }.freeze
35
+
36
+ LOOKUP_IN_OPERATION_TYPE_MAP = {
37
+ :get => :OPERATION_GET,
38
+ :get_doc => :OPERATION_GET,
39
+ :exists => :OPERATION_EXISTS,
40
+ :count => :OPERATION_COUNT,
41
+ }.freeze
42
+
43
+ MUTATE_IN_OPERATION_TYPE_MAP = {
44
+ :set_doc => :OPERATION_REPLACE,
45
+ :replace => :OPERATION_REPLACE,
46
+ :dict_add => :OPERATION_INSERT,
47
+ :remove_doc => :OPERATION_REMOVE,
48
+ :remove => :OPERATION_REMOVE,
49
+ :dict_upsert => :OPERATION_UPSERT,
50
+ :array_push_last => :OPERATION_ARRAY_APPEND,
51
+ :array_push_first => :OPERATION_ARRAY_PREPEND,
52
+ :array_insert => :OPERATION_ARRAY_INSERT,
53
+ :array_add_unique => :OPERATION_ARRAY_ADD_UNIQUE,
54
+ :counter => :OPERATION_COUNTER,
55
+ }.freeze
56
+
57
+ MUTATE_IN_STORE_SEMANTIC_MAP = {
58
+ :replace => :STORE_SEMANTIC_REPLACE,
59
+ :upsert => :STORE_SEMANTIC_UPSERT,
60
+ :insert => :STORE_SEMANTIC_INSERT,
61
+ }.freeze
62
+
63
+ attr_reader :bucket_name
64
+ attr_reader :scope_name
65
+ attr_reader :collection_name
66
+
67
+ def initialize(bucket_name, scope_name, collection_name)
68
+ @bucket_name = bucket_name
69
+ @scope_name = scope_name
70
+ @collection_name = collection_name
71
+ end
72
+
73
+ def location
74
+ {
75
+ bucket_name: @bucket_name,
76
+ scope_name: @scope_name,
77
+ collection_name: @collection_name,
78
+ }
79
+ end
80
+
81
+ def get_request(id, options)
82
+ proto_opts = {
83
+ project: options.projections,
84
+ }
85
+
86
+ proto_req = Generated::KV::V1::GetRequest.new(
87
+ key: id,
88
+ **location,
89
+ **proto_opts
90
+ )
91
+
92
+ create_kv_request(proto_req, :get, options, idempotent: true)
93
+ end
94
+
95
+ def get_and_touch_request(id, expiry, options)
96
+ expiry_type, expiry_value = get_expiry(expiry)
97
+
98
+ raise ArgumentError, "Expiry cannot be nil" if expiry_value.nil?
99
+
100
+ proto_req = Generated::KV::V1::GetAndTouchRequest.new(
101
+ **{expiry_type => expiry_value},
102
+ **location,
103
+ key: id
104
+ )
105
+
106
+ create_kv_request(proto_req, :get_and_touch, options)
107
+ end
108
+
109
+ def get_and_lock_request(id, lock_time, options)
110
+ proto_req = Generated::KV::V1::GetAndLockRequest.new(
111
+ **location,
112
+ key: id,
113
+ lock_time: lock_time.respond_to?(:in_seconds) ? lock_time.public_send(:in_seconds) : lock_time
114
+ )
115
+
116
+ create_kv_request(proto_req, :get_and_lock, options)
117
+ end
118
+
119
+ def unlock_request(id, cas, options)
120
+ proto_req = Generated::KV::V1::UnlockRequest.new(
121
+ **location,
122
+ key: id,
123
+ cas: cas
124
+ )
125
+
126
+ create_kv_request(proto_req, :unlock, options)
127
+ end
128
+
129
+ def touch_request(id, expiry, options)
130
+ expiry_type, expiry_value = get_expiry(expiry)
131
+
132
+ raise ArgumentError, "Expiry cannot be nil" if expiry_value.nil?
133
+
134
+ proto_req = Generated::KV::V1::TouchRequest.new(
135
+ **{expiry_type => expiry_value},
136
+ **location,
137
+ key: id
138
+ )
139
+
140
+ create_kv_request(proto_req, :touch, options)
141
+ end
142
+
143
+ def upsert_request(id, content, options)
144
+ encoded, flag = get_encoded(content, options)
145
+
146
+ proto_opts = {
147
+ content_flags: flag,
148
+ preserve_expiry_on_existing: options.preserve_expiry,
149
+ }
150
+ proto_opts[:durability_level] = get_durability_level(options) unless options.durability_level == :none
151
+
152
+ expiry_type, expiry_value = get_expiry(options)
153
+ proto_opts[expiry_type] = expiry_value
154
+
155
+ proto_req = Generated::KV::V1::UpsertRequest.new(
156
+ key: id,
157
+ content_uncompressed: encoded,
158
+ **location,
159
+ **proto_opts
160
+ )
161
+
162
+ create_kv_request(proto_req, :upsert, options)
163
+ end
164
+
165
+ def insert_request(id, content, options)
166
+ encoded, flag = get_encoded(content, options)
167
+
168
+ proto_opts = {
169
+ content_flags: flag,
170
+ }
171
+
172
+ proto_opts[:durability_level] = get_durability_level(options) unless options.durability_level == :none
173
+ expiry_type, expiry_value = get_expiry(options)
174
+ proto_opts[expiry_type] = expiry_value unless expiry_value.nil?
175
+
176
+ proto_req = Generated::KV::V1::InsertRequest.new(
177
+ key: id,
178
+ content_uncompressed: encoded,
179
+ **location,
180
+ **proto_opts
181
+ )
182
+
183
+ create_kv_request(proto_req, :insert, options)
184
+ end
185
+
186
+ def replace_request(id, content, options)
187
+ encoded, flag = get_encoded(content, options)
188
+
189
+ proto_opts = {
190
+ content_flags: flag,
191
+ }
192
+
193
+ proto_opts[:cas] = options.cas unless options.cas.nil?
194
+ proto_opts[:durability_level] = get_durability_level(options) unless options.durability_level == :none
195
+
196
+ unless options.preserve_expiry
197
+ expiry_type, expiry_value = get_expiry(options)
198
+ proto_opts[expiry_type] = expiry_value
199
+ end
200
+
201
+ proto_req = Generated::KV::V1::ReplaceRequest.new(
202
+ key: id,
203
+ content_uncompressed: encoded,
204
+ **location,
205
+ **proto_opts
206
+ )
207
+
208
+ create_kv_request(proto_req, :replace, options)
209
+ end
210
+
211
+ def remove_request(id, options)
212
+ proto_opts = {}
213
+
214
+ proto_opts[:cas] = options.cas unless options.cas.nil?
215
+ proto_opts[:durability_level] = get_durability_level(options) unless options.durability_level == :none
216
+
217
+ proto_req = Generated::KV::V1::RemoveRequest.new(
218
+ key: id,
219
+ **location,
220
+ **proto_opts
221
+ )
222
+
223
+ create_kv_request(proto_req, :remove, options)
224
+ end
225
+
226
+ def exists_request(id, options)
227
+ proto_opts = {}
228
+
229
+ proto_req = Generated::KV::V1::ExistsRequest.new(
230
+ key: id,
231
+ **proto_opts,
232
+ **location
233
+ )
234
+
235
+ create_kv_request(proto_req, :exists, options)
236
+ end
237
+
238
+ def mutate_in_request(id, specs, options)
239
+ if options.create_as_deleted
240
+ raise Error::FeatureNotAvailable, "The #{Couchbase::Protostellar::NAME} protocol does not support create_as_deleted"
241
+ end
242
+
243
+ proto_opts = {
244
+ flags: get_mutate_in_flags(options),
245
+ store_semantic: get_mutate_in_store_semantic(options),
246
+ durability_level: get_durability_level(options),
247
+ }
248
+ proto_opts[:cas] = options.cas unless options.cas.nil?
249
+
250
+ unless options.preserve_expiry
251
+ expiry_type, expiry_value = get_expiry(options)
252
+ proto_opts[expiry_type] = expiry_value
253
+ end
254
+
255
+ proto_req = Generated::KV::V1::MutateInRequest.new(
256
+ key: id,
257
+ **location,
258
+ specs: specs.map { |s| get_mutate_in_spec(s) },
259
+ **proto_opts
260
+ )
261
+
262
+ create_kv_request(proto_req, :mutate_in, options)
263
+ end
264
+
265
+ def lookup_in_request(id, specs, options)
266
+ proto_opts = {
267
+ flags: get_lookup_in_flags(options),
268
+ }
269
+
270
+ proto_req = Generated::KV::V1::LookupInRequest.new(
271
+ key: id,
272
+ **location,
273
+ specs: specs.map { |s| get_lookup_in_spec(s) },
274
+ **proto_opts
275
+ )
276
+
277
+ create_kv_request(proto_req, :lookup_in, options, idempotent: true)
278
+ end
279
+
280
+ def increment_request(id, options)
281
+ proto_opts = {
282
+ delta: options.delta,
283
+ }
284
+ expiry_type, expiry_value = get_expiry(options)
285
+ proto_opts[expiry_type] = expiry_value unless expiry_value.nil?
286
+ proto_opts[:initial] = options.initial unless options.initial.nil?
287
+
288
+ proto_req = Generated::KV::V1::IncrementRequest.new(
289
+ key: id,
290
+ **location,
291
+ **proto_opts
292
+ )
293
+
294
+ create_kv_request(proto_req, :increment, options)
295
+ end
296
+
297
+ def decrement_request(id, options)
298
+ proto_opts = {
299
+ delta: options.delta,
300
+ }
301
+ expiry_type, expiry_value = get_expiry(options)
302
+ proto_opts[expiry_type] = expiry_value unless expiry_value.nil?
303
+ proto_opts[:initial] = options.initial unless options.initial.nil?
304
+
305
+ proto_req = Generated::KV::V1::DecrementRequest.new(
306
+ key: id,
307
+ **location,
308
+ **proto_opts
309
+ )
310
+
311
+ create_kv_request(proto_req, :decrement, options)
312
+ end
313
+
314
+ def append_request(id, content, options)
315
+ proto_opts = {}
316
+ proto_opts[:cas] = options.cas unless options.cas.nil?
317
+ proto_opts[:durability_level] = get_durability_level(options) unless options.durability_level == :none
318
+
319
+ proto_req = Generated::KV::V1::AppendRequest.new(
320
+ key: id,
321
+ content: content,
322
+ **location,
323
+ **proto_opts
324
+ )
325
+
326
+ create_kv_request(proto_req, :append, options)
327
+ end
328
+
329
+ def prepend_request(id, content, options)
330
+ proto_opts = {}
331
+ proto_opts[:cas] = options.cas unless options.cas.nil?
332
+ proto_opts[:durability_level] = get_durability_level(options) unless options.durability_level == :none
333
+
334
+ proto_req = Generated::KV::V1::PrependRequest.new(
335
+ key: id,
336
+ content: content,
337
+ **location,
338
+ **proto_opts
339
+ )
340
+
341
+ create_kv_request(proto_req, :prepend, options)
342
+ end
343
+
344
+ def get_all_replicas_request(id, options)
345
+ proto_req = Generated::KV::V1::GetAllReplicasRequest.new(
346
+ key: id,
347
+ **location
348
+ )
349
+
350
+ create_kv_request(proto_req, :get_all_replicas, options, idempotent: true)
351
+ end
352
+
353
+ def get_any_replica_request(id, options)
354
+ # Uses the GetAllReplicas request and returns the first item from the result
355
+ get_all_replicas_request(id, options)
356
+ end
357
+
358
+ private
359
+
360
+ def create_kv_request(proto_request, rpc, options, idempotent: false)
361
+ Request.new(
362
+ service: :kv,
363
+ rpc: rpc,
364
+ proto_request: proto_request,
365
+ timeout: options.timeout,
366
+ idempotent: idempotent
367
+ )
368
+ end
369
+
370
+ def get_expiry(options_or_expiry)
371
+ if options_or_expiry.respond_to?(:expiry)
372
+ type, time_or_duration = Couchbase::Utils::Time.extract_expiry_time(options_or_expiry.expiry)
373
+ else
374
+ type, time_or_duration = Couchbase::Utils::Time.extract_expiry_time(options_or_expiry)
375
+ end
376
+
377
+ if time_or_duration.nil?
378
+ return [:expiry_secs, 0] if options_or_expiry.respond_to?(:expiry) # Expiry in KV options - expiry should be removed
379
+
380
+ return [nil, nil]
381
+ end
382
+
383
+ case type
384
+ when :duration
385
+ [:expiry_secs, time_or_duration]
386
+ when :time_point
387
+ timestamp = Google::Protobuf::Timestamp.new(
388
+ seconds: time_or_duration
389
+ )
390
+ [:expiry_time, timestamp]
391
+ else
392
+ raise Couchbase::Error::CouchbaseError, "Unexpected expiry type"
393
+ end
394
+ end
395
+
396
+ def get_durability_level(options)
397
+ if options.durability_level == :none
398
+ nil
399
+ else
400
+ DURABILITY_LEVEL_MAP[options.durability_level]
401
+ end
402
+ end
403
+
404
+ def get_lookup_in_spec(lookup_in_spec)
405
+ Generated::KV::V1::LookupInRequest::Spec.new(
406
+ operation: get_lookup_in_operation(lookup_in_spec),
407
+ path: lookup_in_spec.path,
408
+ flags: get_lookup_in_spec_flags(lookup_in_spec)
409
+ )
410
+ end
411
+
412
+ def get_lookup_in_operation(lookup_in_spec)
413
+ LOOKUP_IN_OPERATION_TYPE_MAP[lookup_in_spec.type]
414
+ end
415
+
416
+ def get_lookup_in_spec_flags(lookup_in_spec)
417
+ Generated::KV::V1::LookupInRequest::Spec::Flags.new(
418
+ xattr: lookup_in_spec.xattr?
419
+ )
420
+ end
421
+
422
+ def get_lookup_in_flags(options)
423
+ Generated::KV::V1::LookupInRequest::Flags.new(
424
+ access_deleted: options.access_deleted
425
+ )
426
+ end
427
+
428
+ def get_mutate_in_spec(mutate_in_spec)
429
+ if mutate_in_spec.expand_macros?
430
+ raise Couchbase::Error::FeatureNotAvailable, "The #{Protostellar::NAME} protocol does not support expanding macros"
431
+ end
432
+
433
+ Generated::KV::V1::MutateInRequest::Spec.new(
434
+ operation: get_mutate_in_operation(mutate_in_spec),
435
+ path: mutate_in_spec.path,
436
+ content: mutate_in_spec.param.to_s,
437
+ flags: get_mutate_in_spec_flags(mutate_in_spec)
438
+ )
439
+ end
440
+
441
+ def get_mutate_in_operation(mutate_in_spec)
442
+ MUTATE_IN_OPERATION_TYPE_MAP[mutate_in_spec.type]
443
+ end
444
+
445
+ def get_mutate_in_spec_flags(mutate_in_spec)
446
+ Generated::KV::V1::MutateInRequest::Spec::Flags.new(
447
+ create_path: mutate_in_spec.create_path?,
448
+ xattr: mutate_in_spec.xattr?
449
+ )
450
+ end
451
+
452
+ def get_mutate_in_flags(options)
453
+ Generated::KV::V1::MutateInRequest::Flags.new(
454
+ access_deleted: options.access_deleted
455
+ )
456
+ end
457
+
458
+ def get_mutate_in_store_semantic(options)
459
+ MUTATE_IN_STORE_SEMANTIC_MAP[options.store_semantics]
460
+ end
461
+
462
+ def get_encoded(content, options)
463
+ if options.transcoder.nil?
464
+ encoded = content.to_s
465
+ flag = 0
466
+ else
467
+ encoded, flag = options.transcoder.encode(content)
468
+ end
469
+ [encoded, flag]
470
+ end
471
+ end
472
+ end
473
+ end
474
+ end