google-cloud-bigtable 0.1.0

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 (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