google-cloud-bigtable 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +10 -0
  3. data/LICENSE +201 -0
  4. data/README.md +65 -0
  5. data/lib/google/bigtable/admin/v2/bigtable_instance_admin_pb.rb +139 -0
  6. data/lib/google/bigtable/admin/v2/bigtable_instance_admin_services_pb.rb +85 -0
  7. data/lib/google/bigtable/admin/v2/bigtable_table_admin_pb.rb +137 -0
  8. data/lib/google/bigtable/admin/v2/bigtable_table_admin_services_pb.rb +117 -0
  9. data/lib/google/bigtable/admin/v2/common_pb.rb +24 -0
  10. data/lib/google/bigtable/admin/v2/instance_pb.rb +72 -0
  11. data/lib/google/bigtable/admin/v2/table_pb.rb +88 -0
  12. data/lib/google/bigtable/v2/bigtable_pb.rb +109 -0
  13. data/lib/google/bigtable/v2/bigtable_services_pb.rb +67 -0
  14. data/lib/google/bigtable/v2/data_pb.rb +155 -0
  15. data/lib/google/cloud/bigtable/admin/credentials.rb +26 -0
  16. data/lib/google/cloud/bigtable/admin/v2/bigtable_instance_admin_client.rb +1417 -0
  17. data/lib/google/cloud/bigtable/admin/v2/bigtable_instance_admin_client_config.json +123 -0
  18. data/lib/google/cloud/bigtable/admin/v2/bigtable_table_admin_client.rb +1079 -0
  19. data/lib/google/cloud/bigtable/admin/v2/bigtable_table_admin_client_config.json +109 -0
  20. data/lib/google/cloud/bigtable/admin/v2/credentials.rb +50 -0
  21. data/lib/google/cloud/bigtable/admin/v2/doc/google/bigtable/admin/v2/bigtable_instance_admin.rb +279 -0
  22. data/lib/google/cloud/bigtable/admin/v2/doc/google/bigtable/admin/v2/bigtable_table_admin.rb +353 -0
  23. data/lib/google/cloud/bigtable/admin/v2/doc/google/bigtable/admin/v2/instance.rb +194 -0
  24. data/lib/google/cloud/bigtable/admin/v2/doc/google/bigtable/admin/v2/table.rb +209 -0
  25. data/lib/google/cloud/bigtable/admin/v2/doc/google/iam/v1/iam_policy.rb +62 -0
  26. data/lib/google/cloud/bigtable/admin/v2/doc/google/iam/v1/policy.rb +127 -0
  27. data/lib/google/cloud/bigtable/admin/v2/doc/google/longrunning/operations.rb +92 -0
  28. data/lib/google/cloud/bigtable/admin/v2/doc/google/protobuf/any.rb +124 -0
  29. data/lib/google/cloud/bigtable/admin/v2/doc/google/protobuf/duration.rb +90 -0
  30. data/lib/google/cloud/bigtable/admin/v2/doc/google/protobuf/empty.rb +28 -0
  31. data/lib/google/cloud/bigtable/admin/v2/doc/google/protobuf/field_mask.rb +223 -0
  32. data/lib/google/cloud/bigtable/admin/v2/doc/google/protobuf/timestamp.rb +106 -0
  33. data/lib/google/cloud/bigtable/admin/v2/doc/google/rpc/status.rb +83 -0
  34. data/lib/google/cloud/bigtable/admin/v2.rb +200 -0
  35. data/lib/google/cloud/bigtable/admin.rb +196 -0
  36. data/lib/google/cloud/bigtable/app_profile/job.rb +102 -0
  37. data/lib/google/cloud/bigtable/app_profile/list.rb +159 -0
  38. data/lib/google/cloud/bigtable/app_profile.rb +373 -0
  39. data/lib/google/cloud/bigtable/chunk_processor.rb +253 -0
  40. data/lib/google/cloud/bigtable/cluster/job.rb +92 -0
  41. data/lib/google/cloud/bigtable/cluster/list.rb +169 -0
  42. data/lib/google/cloud/bigtable/cluster.rb +264 -0
  43. data/lib/google/cloud/bigtable/column_family.rb +280 -0
  44. data/lib/google/cloud/bigtable/column_range.rb +186 -0
  45. data/lib/google/cloud/bigtable/convert.rb +75 -0
  46. data/lib/google/cloud/bigtable/credentials.rb +24 -0
  47. data/lib/google/cloud/bigtable/errors.rb +35 -0
  48. data/lib/google/cloud/bigtable/gc_rule.rb +215 -0
  49. data/lib/google/cloud/bigtable/instance/cluster_map.rb +70 -0
  50. data/lib/google/cloud/bigtable/instance/job.rb +97 -0
  51. data/lib/google/cloud/bigtable/instance/list.rb +159 -0
  52. data/lib/google/cloud/bigtable/instance.rb +921 -0
  53. data/lib/google/cloud/bigtable/longrunning_job.rb +105 -0
  54. data/lib/google/cloud/bigtable/mutation_entry.rb +244 -0
  55. data/lib/google/cloud/bigtable/mutation_operations.rb +338 -0
  56. data/lib/google/cloud/bigtable/policy.rb +163 -0
  57. data/lib/google/cloud/bigtable/project.rb +580 -0
  58. data/lib/google/cloud/bigtable/read_modify_write_rule.rb +129 -0
  59. data/lib/google/cloud/bigtable/read_operations.rb +345 -0
  60. data/lib/google/cloud/bigtable/row.rb +125 -0
  61. data/lib/google/cloud/bigtable/row_filter/chain_filter.rb +539 -0
  62. data/lib/google/cloud/bigtable/row_filter/condition_filter.rb +108 -0
  63. data/lib/google/cloud/bigtable/row_filter/interleave_filter.rb +570 -0
  64. data/lib/google/cloud/bigtable/row_filter/simple_filter.rb +273 -0
  65. data/lib/google/cloud/bigtable/row_filter.rb +593 -0
  66. data/lib/google/cloud/bigtable/row_range.rb +174 -0
  67. data/lib/google/cloud/bigtable/rows_mutator.rb +120 -0
  68. data/lib/google/cloud/bigtable/rows_reader.rb +196 -0
  69. data/lib/google/cloud/bigtable/sample_row_key.rb +82 -0
  70. data/lib/google/cloud/bigtable/service.rb +817 -0
  71. data/lib/google/cloud/bigtable/table/cluster_state.rb +93 -0
  72. data/lib/google/cloud/bigtable/table/column_family_map.rb +68 -0
  73. data/lib/google/cloud/bigtable/table/list.rb +147 -0
  74. data/lib/google/cloud/bigtable/table.rb +676 -0
  75. data/lib/google/cloud/bigtable/v2/bigtable_client.rb +579 -0
  76. data/lib/google/cloud/bigtable/v2/bigtable_client_config.json +65 -0
  77. data/lib/google/cloud/bigtable/v2/credentials.rb +45 -0
  78. data/lib/google/cloud/bigtable/v2/doc/google/bigtable/v2/bigtable.rb +286 -0
  79. data/lib/google/cloud/bigtable/v2/doc/google/bigtable/v2/data.rb +492 -0
  80. data/lib/google/cloud/bigtable/v2/doc/google/protobuf/any.rb +124 -0
  81. data/lib/google/cloud/bigtable/v2/doc/google/protobuf/wrappers.rb +89 -0
  82. data/lib/google/cloud/bigtable/v2/doc/google/rpc/status.rb +83 -0
  83. data/lib/google/cloud/bigtable/v2.rb +132 -0
  84. data/lib/google/cloud/bigtable/value_range.rb +175 -0
  85. data/lib/google/cloud/bigtable/version.rb +22 -0
  86. data/lib/google/cloud/bigtable.rb +223 -0
  87. data/lib/google-cloud-bigtable.rb +167 -0
  88. metadata +283 -0
@@ -0,0 +1,373 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2018 Google LLC
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
+ # https://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
+ require "google/cloud/bigtable/app_profile/list"
19
+ require "google/cloud/bigtable/app_profile/job"
20
+
21
+ module Google
22
+ module Cloud
23
+ module Bigtable
24
+ # # AppProfile
25
+ #
26
+ # A configuration object describing how Cloud Bigtable should treat traffic
27
+ # from a particular end user application.
28
+ #
29
+ # @example
30
+ # require "google/cloud/bigtable"
31
+ #
32
+ # bigtable = Google::Cloud::Bigtable.new
33
+ #
34
+ # instance = bigtable.instance("my-instance")
35
+ #
36
+ # app_profile = bigtable.app_profile("my-instance", "my-app-profile")
37
+ #
38
+ # # Update
39
+ # app_profile.description = "User data instance app profile"
40
+ # app_profile.routing_policy = Google::Cloud::Bigtable::AppProfile.multi_cluster_routing
41
+ # job = app_profile.save
42
+ # job.wait_until_done!
43
+ #
44
+ # # Delete
45
+ # app_profile.delete
46
+ #
47
+ class AppProfile
48
+ # @private
49
+ # The gRPC Service object.
50
+ attr_accessor :service
51
+
52
+ # @private
53
+ #
54
+ # Creates a new AppProfile instance.
55
+ def initialize grpc, service
56
+ @grpc = grpc
57
+ @service = service
58
+ @changed_fields = {}
59
+ end
60
+
61
+ # The unique identifier for the project.
62
+ #
63
+ # @return [String]
64
+ def project_id
65
+ @grpc.name.split("/")[1]
66
+ end
67
+
68
+ # The unique identifier for the instance.
69
+ #
70
+ # @return [String]
71
+ def instance_id
72
+ @grpc.name.split("/")[3]
73
+ end
74
+
75
+ # The unique identifier for the app profile.
76
+ #
77
+ # @return [String]
78
+ def name
79
+ @grpc.name.split("/")[5]
80
+ end
81
+
82
+ # The full path for the instance resource. Values are of the form
83
+ # `projects/<project_id>/instances/<instance_id>`.
84
+ #
85
+ # @return [String]
86
+ def path
87
+ @grpc.name
88
+ end
89
+
90
+ # Etag for optimistic concurrency control.
91
+ #
92
+ # @return [String]
93
+ def etag
94
+ @grpc.etag
95
+ end
96
+
97
+ # Description of the AppProfile.
98
+ #
99
+ # @return [String]
100
+ def description
101
+ @grpc.description
102
+ end
103
+
104
+ # Set description of the AppProfile.
105
+ #
106
+ # @param text [String] Description text
107
+ def description= text
108
+ @grpc.description = text
109
+ @changed_fields["description"] = "description"
110
+ end
111
+
112
+ # Get value of multi-cluster routing policy.
113
+ #
114
+ # @return [Google::Bigtable::Admin::V2::AppProfile::MultiClusterRoutingUseAny]
115
+ def multi_cluster_routing
116
+ @grpc.multi_cluster_routing_use_any
117
+ end
118
+
119
+ # Get value of single cluster routing policy
120
+ #
121
+ # @return [Google::Bigtable::Admin::V2::AppProfile::SingleClusterRouting]
122
+ def single_cluster_routing
123
+ @grpc.single_cluster_routing
124
+ end
125
+
126
+ # Set routing policy
127
+ #
128
+ # @param policy [Google::Bigtable::Admin::V2::AppProfile::SingleClusterRouting | Google::Bigtable::Admin::V2::AppProfile::MultiClusterRoutingUseAny]
129
+ # The routing policy for all read/write requests which use this app profile.
130
+ # A value must be explicitly set.
131
+ #
132
+ # Routing Policies:
133
+ # * `multi_cluster_routing` - Read/write requests may be routed to any
134
+ # cluster in the instance, and will fail over to another cluster in the event
135
+ # of transient errors or delays. Choosing this option sacrifices
136
+ # read-your-writes consistency to improve availability.
137
+ # * `single_cluster_routing` - Unconditionally routes all read/write requests
138
+ # to a specific cluster. This option preserves read-your-writes consistency,
139
+ # but does not improve availability.
140
+ # Value contain `cluster_id` and optional field `allow_transactional_writes`.
141
+ #
142
+ # @example Set multi cluster routing policy
143
+ # require "google/cloud/bigtable"
144
+ #
145
+ # bigtable = Google::Cloud::Bigtable.new
146
+ # instance = bigtable.instance("my-instance")
147
+ # app_profile = instance.app_profile("my-app-profile")
148
+ #
149
+ # routing_policy = Google::Cloud::Bigtable::AppProfile.multi_cluster_routing
150
+ # app_profile.routing_policy = routing_policy
151
+ #
152
+ # @example Set single cluster routing policy
153
+ # require "google/cloud/bigtable"
154
+ #
155
+ # bigtable = Google::Cloud::Bigtable.new
156
+ # instance = bigtable.instance("my-instance")
157
+ # app_profile = instance.app_profile("my-app-profile")
158
+ #
159
+ # routing_policy = Google::Cloud::Bigtable::AppProfile.single_cluster_routing(
160
+ # "my-instance-cluster-1"
161
+ # allow_transactional_writes: true
162
+ # )
163
+ # app_profile.routing_policy = routing_policy
164
+ #
165
+ def routing_policy= policy
166
+ if policy.is_a?(Google::Bigtable::Admin::V2::AppProfile:: \
167
+ SingleClusterRouting)
168
+ @grpc.single_cluster_routing = policy
169
+ @changed_fields["routing_policy"] = "single_cluster_routing"
170
+ else
171
+ @grpc.multi_cluster_routing_use_any = policy
172
+ @changed_fields["routing_policy"] = "multi_cluster_routing_use_any"
173
+ end
174
+ end
175
+
176
+ # Get routing policy
177
+ #
178
+ # @return [Google::Bigtable::Admin::V2::AppProfile::SingleClusterRouting, Google::Bigtable::Admin::V2::AppProfile::MultiClusterRoutingUseAny]
179
+ #
180
+ def routing_policy
181
+ @grpc.single_cluster_routing || @grpc.multi_cluster_routing_use_any
182
+ end
183
+
184
+ # Delete app profile.
185
+ #
186
+ # @param ignore_warnings [Boolean]
187
+ # Default value is false. If true, ignore safety checks when deleting
188
+ # the app profile.
189
+ # @return [Boolean] Returns `true` if the app profile was deleted.
190
+ #
191
+ # @example
192
+ # require "google/cloud/bigtable"
193
+ #
194
+ # bigtable = Google::Cloud::Bigtable.new
195
+ #
196
+ # instance = bigtable.instance("my-instance")
197
+ # app_profile = bigtable.instance("my-app-profile")
198
+ #
199
+ # app_profile.delete(ignore_warnings: true) # Ignore warnings.
200
+ #
201
+ # # OR : Not ignoring warnings
202
+ # app_profile.delete
203
+ #
204
+ def delete ignore_warnings: false
205
+ ensure_service!
206
+ service.delete_app_profile(
207
+ instance_id,
208
+ name,
209
+ ignore_warnings: ignore_warnings
210
+ )
211
+ true
212
+ end
213
+
214
+ # Update app profile.
215
+ #
216
+ # @param ignore_warnings [Boolean]
217
+ # Default value is false. If true, ignore safety checks when updating
218
+ # the app profile.
219
+ # @return [Google::Cloud::Bigtable::AppProfile::Job]
220
+ #
221
+ # @example Update
222
+ # require "google/cloud/bigtable"
223
+ #
224
+ # bigtable = Google::Cloud::Bigtable.new
225
+ #
226
+ # app_profile = bigtable.app_profile("my-app-profile")
227
+ #
228
+ # app_profile.description = "User data instance app profile"
229
+ # app_profile.routing_policy = \
230
+ # Google::Cloud::Bigtable::AppProfile.multi_cluster_routing
231
+ #
232
+ # job = app_profile.save
233
+ # job.wait_until_done!
234
+ # if job.error?
235
+ # puts job.error
236
+ # else
237
+ # puts "App profile successfully update."
238
+ # app_profile = job.app_profile
239
+ # end
240
+ #
241
+ # # OR - Update with ignoring warnings.
242
+ # job = app_profile.save(ignore_warnings: true)
243
+ # job.wait_until_done!
244
+ #
245
+ # @example Update with single cluster routing
246
+ # require "google/cloud/bigtable"
247
+ #
248
+ # bigtable = Google::Cloud::Bigtable.new
249
+ #
250
+ # instance = bigtable.instance("my-instance")
251
+ # app_profile = bigtable.instance("my-app-profile")
252
+ #
253
+ # app_profile.description = "User data instance app profile"
254
+ # routing_policy = Google::Cloud::Bigtable::AppProfile.single_cluster_routing(
255
+ # "my-cluster",
256
+ # allow_transactional_writes: true
257
+ # )
258
+ # app_profile.routing_policy = routing_policy
259
+ #
260
+ # job = app_profile.save
261
+ #
262
+ # job.done? #=> false
263
+ # job.reload!
264
+ # job.done? #=> false
265
+ #
266
+ # # Reload job until completion.
267
+ # job.wait_until_done!
268
+ # job.done? #=> true
269
+ #
270
+ # if job.error?
271
+ # puts job.error
272
+ # else
273
+ # app_profile = job.app_profile
274
+ # puts app_profile.name
275
+ # end
276
+
277
+ def save ignore_warnings: false
278
+ ensure_service!
279
+ update_mask = Google::Protobuf::FieldMask.new(
280
+ paths: @changed_fields.values
281
+ )
282
+ grpc = service.update_app_profile(
283
+ @grpc,
284
+ update_mask,
285
+ ignore_warnings: ignore_warnings
286
+ )
287
+ @changed_fields.clear
288
+ AppProfile::Job.from_grpc(grpc, service)
289
+ end
290
+ alias update save
291
+
292
+ # Reload app profile information.
293
+ #
294
+ # @return [Google::Cloud::Bigtable::AppProfile]
295
+
296
+ def reload!
297
+ @grpc = service.get_app_profile(instance_id, name)
298
+ self
299
+ end
300
+
301
+ # Create instance of multi cluster routing policy.
302
+ #
303
+ # Read/write requests may be routed to any cluster in the instance, and will
304
+ # Fail over to another cluster in the event of transient errors or delays.
305
+ # Choosing this option sacrifices read-your-writes consistency to improve
306
+ # availability
307
+ # @return [Google::Bigtable::Admin::V2::AppProfile::MultiClusterRoutingUseAny]
308
+ #
309
+ # @example Create instance of multi cluster routing
310
+ #
311
+ # Google::Cloud::Bigtable::AppProfile.multi_cluster_routing
312
+ #
313
+ def self.multi_cluster_routing
314
+ Google::Bigtable::Admin::V2::AppProfile::MultiClusterRoutingUseAny.new
315
+ end
316
+
317
+ # Create instance of single cluster routing
318
+ #
319
+ # Unconditionally routes all read/write requests to a specific cluster.
320
+ # This option preserves read-your-writes consistency, but does not improve
321
+ # availability.
322
+ #
323
+ # @param cluster_id [String]
324
+ # The cluster to which read/write requests should be routed.
325
+ # @param allow_transactional_writes [Boolean]
326
+ # Whether or not `CheckAndMutateRow` and `ReadModifyWriteRow` requests are
327
+ # allowed by this app profile. It is unsafe to send these requests to
328
+ # the same table/row/column in multiple clusters.
329
+ # Default value is false.
330
+ # @return [Google::Bigtable::Admin::V2::AppProfile::SingleClusterRouting]
331
+ #
332
+ # @example Create instance of single cluster routing
333
+ #
334
+ # Google::Cloud::Bigtable::AppProfile.single_cluster_routing("my-cluster")
335
+ #
336
+ # # With allowed transactional writes
337
+ # Google::Cloud::Bigtable::AppProfile.single_cluster_routing(
338
+ # "my-cluster",
339
+ # allow_transactional_writes: true
340
+ # )
341
+
342
+ def self.single_cluster_routing \
343
+ cluster_id,
344
+ allow_transactional_writes: false
345
+ Google::Bigtable::Admin::V2::AppProfile::SingleClusterRouting.new(
346
+ cluster_id: cluster_id,
347
+ allow_transactional_writes: allow_transactional_writes
348
+ )
349
+ end
350
+
351
+ # @private
352
+ #
353
+ # Creates a new Instance instance from a
354
+ # Google::Bigtable::Admin::V2::Table.
355
+ # @param grpc [Google::Bigtable::Admin::V2::Table]
356
+ # @param service [Google::Cloud::Bigtable::Service]
357
+ # @return [Google::Cloud::Bigtable::Table]
358
+ def self.from_grpc grpc, service
359
+ new(grpc, service)
360
+ end
361
+
362
+ protected
363
+
364
+ # @private
365
+ # Raise an error unless an active connection to the service is
366
+ # available.
367
+ def ensure_service!
368
+ raise "Must have active connection to service" unless service
369
+ end
370
+ end
371
+ end
372
+ end
373
+ end
@@ -0,0 +1,253 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2018 Google LLC
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
+ # https://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
+ module Google
19
+ module Cloud
20
+ module Bigtable
21
+ # @private
22
+ # # RowsMutator
23
+ #
24
+ # Read chunk and merge based on states and build rows and cells
25
+ #
26
+ class ChunkProcessor
27
+ # Row states
28
+ NEW_ROW = 1
29
+ ROW_IN_PROGRESS = 2
30
+ CELL_IN_PROGRESS = 3
31
+
32
+ # Current state
33
+ attr_accessor :state, :last_key
34
+
35
+ # Current cached row data
36
+ attr_accessor :chunk, :row
37
+
38
+ # Current cell values
39
+ attr_accessor :cur_family, :cur_qaul, :cur_ts, :cur_val, :cur_labels
40
+
41
+ # @private
42
+ #
43
+ # Create chunk reader object and set row state to new
44
+ #
45
+ def initialize
46
+ reset_to_new_row
47
+ end
48
+
49
+ # Process chunk and build full row with cells
50
+ #
51
+ # @param chunk [Google::Bigtable::V2::ReadRowsResponse::CellChunk]
52
+ #
53
+ def process chunk
54
+ self.chunk = chunk
55
+
56
+ if chunk.commit_row
57
+ raise_if(
58
+ chunk.value_size > 0,
59
+ "A row cant not have value_size and commit_row"
60
+ )
61
+ end
62
+
63
+ if state == NEW_ROW
64
+ process_new_row
65
+ elsif state == CELL_IN_PROGRESS
66
+ process_cell_in_progress
67
+ elsif state == ROW_IN_PROGRESS
68
+ process_row_in_progress
69
+ end
70
+ end
71
+
72
+ # Validate row status commit or reset
73
+ #
74
+ # @raise [Google::Cloud::Bigtable::InvalidRowStateError]
75
+ # if chunk has data on reset row state
76
+ #
77
+ def validate_reset_row
78
+ return unless chunk.reset_row
79
+
80
+ value = (!chunk.row_key.empty? ||
81
+ chunk.family_name ||
82
+ chunk.qualifier ||
83
+ !chunk.value.empty? ||
84
+ chunk.timestamp_micros > 0)
85
+
86
+ raise_if value, "A reset should have no data"
87
+ end
88
+
89
+ # Validate chunk has new row state
90
+ #
91
+ # @raise [Google::Cloud::Bigtable::InvalidRowStateError]
92
+ # If row has already set key, chunk has emoty row key, chunk state is
93
+ # reset, new row key same as last read key, family name or column
94
+ # qualifier is empty
95
+ #
96
+ def validate_new_row
97
+ raise_if(row.key, "A new row cannot have existing state")
98
+ raise_if(chunk.row_key.empty?, "A row key must be set")
99
+ raise_if(chunk.reset_row, "A new row cannot be reset")
100
+ raise_if(
101
+ last_key == chunk.row_key,
102
+ "A commit happened but the same key followed"
103
+ )
104
+ raise_if(chunk.family_name.nil?, "A family must be set")
105
+ raise_if(chunk.qualifier.nil?, "A column qualifier must be set")
106
+ end
107
+
108
+ # Validate chunk merge is in progress to build new row
109
+ #
110
+ # @raise [Google::Cloud::Bigtable::InvalidRowStateError]
111
+ # If row and chunk row key are not same or chunk row key is empty.
112
+ #
113
+ def validate_row_in_progress
114
+ raise_if(
115
+ !chunk.row_key.empty? && chunk.row_key != row.key,
116
+ "A commit is required between row keys"
117
+ )
118
+
119
+ raise_if(
120
+ chunk.family_name && chunk.qualifier.nil?,
121
+ "A qualifier must be specified"
122
+ )
123
+
124
+ validate_reset_row
125
+ end
126
+
127
+ # Process new row by setting valus from current chunk.
128
+ #
129
+ # @return [Google::Cloud::Bigtable::Row]
130
+ #
131
+ def process_new_row
132
+ validate_new_row
133
+
134
+ return if chunk.family_name.nil? || chunk.qualifier.nil?
135
+
136
+ row.key = chunk.row_key
137
+ self.cur_family = chunk.family_name.value
138
+ self.cur_qaul = chunk.qualifier.value
139
+ self.cur_ts = chunk.timestamp_micros
140
+ self.cur_labels = chunk.labels
141
+
142
+ next_state!
143
+ end
144
+
145
+ # Process chunk if row state is in progress
146
+ #
147
+ # @return [Google::Cloud::Bigtable::Row]
148
+ #
149
+ def process_row_in_progress
150
+ validate_row_in_progress
151
+
152
+ return reset_to_new_row if chunk.reset_row
153
+
154
+ self.cur_family = chunk.family_name.value if chunk.family_name
155
+ self.cur_qaul = chunk.qualifier.value if chunk.qualifier
156
+ self.cur_ts = chunk.timestamp_micros
157
+ self.cur_labels = chunk.labels if chunk.labels
158
+ next_state!
159
+ end
160
+
161
+ # Process chunk if row cell state is in progress
162
+ #
163
+ # @return [Google::Cloud::Bigtable::Row]
164
+ #
165
+ def process_cell_in_progress
166
+ validate_reset_row
167
+
168
+ return reset_to_new_row if chunk.reset_row
169
+
170
+ next_state!
171
+ end
172
+
173
+ # Set next state of row.
174
+ #
175
+ # @return [Google::Cloud::Bigtable::Row]
176
+ #
177
+ def next_state!
178
+ if cur_val
179
+ self.cur_val += chunk.value
180
+ else
181
+ self.cur_val = chunk.value
182
+ end
183
+
184
+ if chunk.value_size.zero?
185
+ persist_cell
186
+ self.state = ROW_IN_PROGRESS
187
+ else
188
+ self.state = CELL_IN_PROGRESS
189
+ end
190
+
191
+ return unless chunk.commit_row
192
+
193
+ self.last_key = row.key
194
+ completed_row = row
195
+ reset_to_new_row
196
+ completed_row
197
+ end
198
+
199
+ # Build cell and append to row.
200
+ def persist_cell
201
+ cell = Row::Cell.new(
202
+ cur_family,
203
+ cur_qaul,
204
+ cur_ts,
205
+ cur_val,
206
+ cur_labels
207
+ )
208
+ row.cells[cur_family] << cell
209
+
210
+ # Clear cached cell values
211
+ self.cur_val = nil
212
+ self.cur_ts = nil
213
+ self.cur_labels = nil
214
+ end
215
+
216
+ # Reset read state and cached data
217
+ def reset_to_new_row
218
+ self.row = Row.new
219
+ self.state = NEW_ROW
220
+ self.cur_family = nil
221
+ self.cur_qaul = nil
222
+ self.cur_ts = nil
223
+ self.cur_val = nil
224
+ self.cur_labels = nil
225
+ end
226
+
227
+ # Validate last row is completed
228
+ #
229
+ # @raise [Google::Cloud::Bigtable::InvalidRowStateError]
230
+ # If read rows response end without last row completed
231
+ #
232
+ def validate_last_row_complete
233
+ return if row.key.nil?
234
+
235
+ raise_if(
236
+ !chunk.commit_row,
237
+ "Response ended with pending row without commit"
238
+ )
239
+ end
240
+
241
+ private
242
+
243
+ # Raise error on condition failure
244
+ #
245
+ # @raise [Google::Cloud::Bigtable::InvalidRowStateError]
246
+ #
247
+ def raise_if condition, message
248
+ raise InvalidRowStateError.new(message, chunk.to_hash) if condition
249
+ end
250
+ end
251
+ end
252
+ end
253
+ end