google-cloud-bigtable 2.2.1 → 2.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +43 -0
  3. data/CONTRIBUTING.md +3 -4
  4. data/LOGGING.md +1 -1
  5. data/OVERVIEW.md +1 -1
  6. data/lib/google/cloud/bigtable/app_profile/list.rb +2 -2
  7. data/lib/google/cloud/bigtable/backup.rb +55 -4
  8. data/lib/google/cloud/bigtable/backup/list.rb +2 -2
  9. data/lib/google/cloud/bigtable/chunk_processor.rb +4 -3
  10. data/lib/google/cloud/bigtable/cluster.rb +22 -2
  11. data/lib/google/cloud/bigtable/cluster/list.rb +2 -2
  12. data/lib/google/cloud/bigtable/column_family.rb +4 -0
  13. data/lib/google/cloud/bigtable/column_family_map.rb +2 -0
  14. data/lib/google/cloud/bigtable/convert.rb +12 -0
  15. data/lib/google/cloud/bigtable/encryption_info.rb +118 -0
  16. data/lib/google/cloud/bigtable/gc_rule.rb +2 -0
  17. data/lib/google/cloud/bigtable/instance.rb +1 -0
  18. data/lib/google/cloud/bigtable/instance/cluster_map.rb +61 -21
  19. data/lib/google/cloud/bigtable/instance/list.rb +2 -2
  20. data/lib/google/cloud/bigtable/mutation_entry.rb +6 -3
  21. data/lib/google/cloud/bigtable/mutation_operations.rb +2 -1
  22. data/lib/google/cloud/bigtable/policy.rb +2 -1
  23. data/lib/google/cloud/bigtable/project.rb +4 -3
  24. data/lib/google/cloud/bigtable/routing_policy.rb +3 -1
  25. data/lib/google/cloud/bigtable/row.rb +5 -1
  26. data/lib/google/cloud/bigtable/row_filter/simple_filter.rb +6 -1
  27. data/lib/google/cloud/bigtable/rows_reader.rb +6 -6
  28. data/lib/google/cloud/bigtable/service.rb +6 -3
  29. data/lib/google/cloud/bigtable/status.rb +4 -1
  30. data/lib/google/cloud/bigtable/table.rb +62 -19
  31. data/lib/google/cloud/bigtable/table/cluster_state.rb +43 -9
  32. data/lib/google/cloud/bigtable/table/list.rb +2 -2
  33. data/lib/google/cloud/bigtable/table/restore_job.rb +1 -1
  34. data/lib/google/cloud/bigtable/value_range.rb +24 -6
  35. data/lib/google/cloud/bigtable/version.rb +1 -1
  36. metadata +7 -6
@@ -28,6 +28,8 @@ module Google
28
28
  # so it is possible for reads to return a cell even if it matches the
29
29
  # active GC expression for its column family.
30
30
  #
31
+ # @see https://cloud.google.com/bigtable/docs/garbage-collection Garbage collection
32
+ #
31
33
  # GC Rule types:
32
34
  # * `max_num_versions` - A garbage-collection rule that explicitly
33
35
  # states the maximum number of cells to keep for all columns in a
@@ -520,6 +520,7 @@ module Google
520
520
  def table table_id, view: nil, perform_lookup: nil, app_profile_id: nil
521
521
  ensure_service!
522
522
 
523
+ view ||= :SCHEMA_VIEW
523
524
  table = if perform_lookup
524
525
  grpc = service.get_table instance_id, table_id, view: view
525
526
  Table.from_grpc grpc, service, view: view
@@ -15,28 +15,31 @@
15
15
  # limitations under the License.
16
16
 
17
17
 
18
+ require "google/cloud/bigtable/admin/v2"
19
+
18
20
  module Google
19
21
  module Cloud
20
22
  module Bigtable
21
23
  class Instance
22
24
  ##
23
- # Instance::ClusterMap is a hash with cluster ID keys and cluster configuration values.
24
- # It is used to create a cluster.
25
+ # Instance::ClusterMap is a hash with cluster ID keys and cluster configuration values. It is used to create a
26
+ # cluster.
25
27
  #
26
28
  # @example
29
+ # require "google/cloud/bigtable"
27
30
  #
28
- # clusters = Google::Cloud::Bigtable::Instance::ClusterMap.new
31
+ # bigtable = Google::Cloud::Bigtable.new
29
32
  #
30
- # clusters.add("cluster-1", "us-east1-b", nodes: 3, storage_type: :SSD)
33
+ # job = bigtable.create_instance("my-instance") do |clusters|
34
+ # clusters.add("test-cluster", "us-east1-b", nodes: 3, storage_type: :SSD)
35
+ # end
31
36
  #
32
- # # Or
33
- # clusters.add("cluster-2", "us-east1-b")
37
+ # job.wait_until_done!
34
38
  #
35
39
  class ClusterMap < DelegateClass(::Hash)
36
40
  # @private
37
41
  #
38
- # Creates a new Instance::ClusterMap with an hash of Cluster name and
39
- # cluster grpc instances.
42
+ # Creates a new Instance::ClusterMap with an hash of Cluster name and cluster grpc instances.
40
43
  def initialize value = {}
41
44
  super value
42
45
  end
@@ -45,24 +48,61 @@ module Google
45
48
  # Adds a cluster to the cluster map.
46
49
  #
47
50
  # @param name [String] The unique identifier for the cluster.
48
- # @param location [String]
49
- # The location where this cluster's nodes and storage reside. For best
50
- # performance, clients should be located as close as possible to this
51
- # cluster. Currently only zones are supported.
52
- # @param nodes [Integer] Number of nodes for the cluster. When creating
53
- # an instance of type `:DEVELOPMENT`, `nodes` must not be set.
54
- # @param storage_type [Symbol]
55
- # Valid values are:
56
- # * `:SSD`(Flash (SSD) storage should be used),
57
- # *`:HDD`(Magnetic drive (HDD) storage should be used)
51
+ # @param location [String] The location where this cluster's nodes and storage reside. For best performance,
52
+ # clients should be located as close as possible to this cluster. Currently only zones are supported.
53
+ # @param nodes [Integer] Number of nodes for the cluster. When creating an instance of type `:DEVELOPMENT`,
54
+ # `nodes` must not be set.
55
+ # @param storage_type [Symbol] The type of storage used by this cluster to serve its parent instance's tables,
56
+ # unless explicitly overridden. Valid values are:
57
+ #
58
+ # * `:SSD` - Flash (SSD) storage should be used.
59
+ # * `:HDD` - Magnetic drive (HDD) storage should be used.
60
+ #
61
+ # If not set then default will set to `:STORAGE_TYPE_UNSPECIFIED`.
62
+ # @param kms_key [String] The full name of a Cloud KMS encryption key for a CMEK-protected cluster, in the
63
+ # format `projects/{key_project_id}/locations/{location}/keyRings/{ring_name}/cryptoKeys/{key_name}`.
64
+ #
65
+ # The requirements for this key are:
66
+ #
67
+ # 1. The Cloud Bigtable service account associated with the project that contains this cluster must be
68
+ # granted the `cloudkms.cryptoKeyEncrypterDecrypter` role on the CMEK key.
69
+ # 2. Only regional keys can be used and the region of the CMEK key must match the region of the cluster.
70
+ # 3. All clusters within an instance must use the same CMEK key.
71
+ #
72
+ # @example
73
+ # require "google/cloud/bigtable"
74
+ #
75
+ # bigtable = Google::Cloud::Bigtable.new
76
+ #
77
+ # job = bigtable.create_instance("my-instance") do |clusters|
78
+ # clusters.add("test-cluster", "us-east1-b", nodes: 3, storage_type: :SSD)
79
+ # end
80
+ #
81
+ # job.wait_until_done!
82
+ #
83
+ # @example With a Cloud KMS encryption key name for a CMEK-protected cluster:
84
+ # require "google/cloud/bigtable"
85
+ #
86
+ # bigtable = Google::Cloud::Bigtable.new
87
+ #
88
+ # kms_key_name = "projects/a/locations/b/keyRings/c/cryptoKeys/d"
89
+ # job = bigtable.create_instance("my-instance") do |clusters|
90
+ # clusters.add("test-cluster", "us-east1-b", kms_key: kms_key_name)
91
+ # end
58
92
  #
59
- # If not set then default will set to `:STORAGE_TYPE_UNSPECIFIED`
93
+ # job.wait_until_done!
60
94
  #
61
- def add name, location, nodes: nil, storage_type: nil
95
+ def add name, location, nodes: nil, storage_type: nil, kms_key: nil
96
+ if kms_key
97
+ encryption_config = Google::Cloud::Bigtable::Admin::V2::Cluster::EncryptionConfig.new(
98
+ kms_key_name: kms_key
99
+ )
100
+ end
62
101
  attrs = {
63
102
  serve_nodes: nodes,
64
103
  location: location,
65
- default_storage_type: storage_type
104
+ default_storage_type: storage_type,
105
+ encryption_config: encryption_config
66
106
  }.delete_if { |_, v| v.nil? }
67
107
 
68
108
  self[name] = Google::Cloud::Bigtable::Admin::V2::Cluster.new attrs
@@ -126,12 +126,12 @@ module Google
126
126
  # puts instance.instance_id
127
127
  # end
128
128
  #
129
- def all
129
+ def all &block
130
130
  return enum_for :all unless block_given?
131
131
 
132
132
  results = self
133
133
  loop do
134
- results.each { |r| yield r }
134
+ results.each(&block)
135
135
  break unless results.next?
136
136
  results = results.next
137
137
  end
@@ -15,6 +15,8 @@
15
15
  # limitations under the License.
16
16
 
17
17
 
18
+ require "google/cloud/bigtable/convert"
19
+
18
20
  module Google
19
21
  module Cloud
20
22
  module Bigtable
@@ -84,8 +86,9 @@ module Google
84
86
  # @param qualifier [String] Column qualifier name.
85
87
  # The qualifier of the column into which new data should be written.
86
88
  # Can be any byte string, including an empty string.
87
- # @param value [String, Integer] Cell value data.
88
- # The value to be written into the specified cell.
89
+ # @param value [String, Integer] Cell value data. The value to be written
90
+ # into the specified cell. If the argument is an Integer, it will be
91
+ # encoded as a 64-bit signed big-endian integer.
89
92
  # @param timestamp [Integer] Timestamp value in microseconds.
90
93
  # The timestamp of the cell into which new data should be written.
91
94
  # Use -1 for current Bigtable server time.
@@ -112,7 +115,7 @@ module Google
112
115
  #
113
116
  def set_cell family, qualifier, value, timestamp: nil
114
117
  # If value is integer, covert it to a 64-bit signed big-endian integer.
115
- value = [value].pack "q>" if value.is_a? Integer
118
+ value = Convert.integer_to_signed_be_64 value
116
119
  options = {
117
120
  family_name: family,
118
121
  column_qualifier: qualifier,
@@ -335,7 +335,8 @@ module Google
335
335
  # end
336
336
  #
337
337
  class Response
338
- attr_reader :index, :status
338
+ attr_reader :index
339
+ attr_reader :status
339
340
 
340
341
  ##
341
342
  # @private Creates a MutationEntry::Response object.
@@ -54,7 +54,8 @@ module Google
54
54
  # policy.roles["roles/viewer"] = ["allUsers"]
55
55
  #
56
56
  class Policy
57
- attr_reader :etag, :roles
57
+ attr_reader :etag
58
+ attr_reader :roles
58
59
 
59
60
  # Creates a Policy instance.
60
61
  # @param etag [String]
@@ -316,18 +316,18 @@ module Google
316
316
  #
317
317
  # table = bigtable.table("my-instance", "my-table")
318
318
  #
319
- # @example Get a table with schema-only view.
319
+ # @example Retrieve a table with a schema-only view.
320
320
  # require "google/cloud/bigtable"
321
321
  #
322
322
  # bigtable = Google::Cloud::Bigtable.new
323
323
  #
324
- # table = bigtable.table("my-instance", "my-table", perform_lookup: true, view: :SCHEMA_VIEW)
324
+ # table = bigtable.table("my-instance", "my-table", perform_lookup: true)
325
325
  # if table
326
326
  # puts table.name
327
327
  # puts table.column_families
328
328
  # end
329
329
  #
330
- # @example Get a table with all fields, cluster states, and column families.
330
+ # @example Retrieve a table with all fields, cluster states, and column families.
331
331
  # require "google/cloud/bigtable"
332
332
  #
333
333
  # bigtable = Google::Cloud::Bigtable.new
@@ -342,6 +342,7 @@ module Google
342
342
  def table instance_id, table_id, view: nil, perform_lookup: nil, app_profile_id: nil
343
343
  ensure_service!
344
344
 
345
+ view ||= :SCHEMA_VIEW
345
346
  table = if perform_lookup
346
347
  grpc = service.get_table instance_id, table_id, view: view
347
348
  Table.from_grpc grpc, service, view: view
@@ -141,7 +141,8 @@ module Google
141
141
  # Default value is false.
142
142
  #
143
143
  class SingleClusterRouting < RoutingPolicy
144
- attr_reader :cluster_id, :allow_transactional_writes
144
+ attr_reader :cluster_id
145
+ attr_reader :allow_transactional_writes
145
146
 
146
147
  ##
147
148
  # Creates a new single-cluster routing policy.
@@ -155,6 +156,7 @@ module Google
155
156
  # Default value is false.
156
157
  #
157
158
  def initialize cluster_id, allow_transactional_writes
159
+ super()
158
160
  @cluster_id = cluster_id
159
161
  @allow_transactional_writes = allow_transactional_writes
160
162
  end
@@ -30,7 +30,11 @@ module Google
30
30
  # Row cell built from data chunks.
31
31
  #
32
32
  class Cell
33
- attr_reader :family, :qualifier, :value, :labels, :timestamp
33
+ attr_reader :family
34
+ attr_reader :qualifier
35
+ attr_reader :value
36
+ attr_reader :labels
37
+ attr_reader :timestamp
34
38
 
35
39
  ##
36
40
  # Creates a row cell instance.
@@ -15,6 +15,8 @@
15
15
  # limitations under the License.
16
16
 
17
17
 
18
+ require "google/cloud/bigtable/convert"
19
+
18
20
  module Google
19
21
  module Cloud
20
22
  module Bigtable
@@ -147,10 +149,13 @@ module Google
147
149
  # will not match the new line character `\n`, which may be present in a
148
150
  # binary value.
149
151
  #
150
- # @param regex [String] Regex to match cell value.
152
+ # @param regex [String, Integer] Regex to match cell value, or an Integer
153
+ # value to be encoded as a 64-bit signed big-endian integer.
151
154
  # @return [Google::Cloud::Bigtable::RowFilter::SimpleFilter]
152
155
  #
153
156
  def value regex
157
+ # If regex is integer, covert it to a 64-bit signed big-endian integer.
158
+ regex = Convert.integer_to_signed_be_64 regex
154
159
  @grpc.value_regex_filter = regex
155
160
  self
156
161
  end
@@ -170,10 +170,10 @@ module Google
170
170
  # @return [Boolean]
171
171
  #
172
172
  def start_key_read? range
173
- start_key = if !range.start_key_closed.empty?
174
- range.start_key_closed
175
- else
173
+ start_key = if range.start_key_closed.empty?
176
174
  range.start_key_open
175
+ else
176
+ range.start_key_closed
177
177
  end
178
178
 
179
179
  start_key.empty? || last_key >= start_key
@@ -186,10 +186,10 @@ module Google
186
186
  # @return [Boolean]
187
187
  #
188
188
  def end_key_read? range
189
- end_key = if !range.end_key_closed.empty?
190
- range.end_key_closed
191
- else
189
+ end_key = if range.end_key_closed.empty?
192
190
  range.end_key_open
191
+ else
192
+ range.end_key_closed
193
193
  end
194
194
 
195
195
  end_key && end_key <= last_key
@@ -752,17 +752,20 @@ module Google
752
752
  # Create a new table by restoring from a completed backup.
753
753
  #
754
754
  # @param table_id [String] The table ID for the new table. This table must not yet exist.
755
- # @param instance_id [String] The instance ID for the source backup. The table will be created in this instance.
755
+ # @param instance_id [String] The instance ID for the source backup. The table will be created in this instance
756
+ # if table_instance_id is not provided.
756
757
  # @param cluster_id [String] The cluster ID for the source backup.
757
758
  # @param backup_id [String] The backup ID for the source backup.
759
+ # @param table_instance_id [String] The instance ID for the table, if different from instance_id. Optional.
758
760
  #
759
761
  # @return [Gapic::Operation] The {Google::Longrunning::Operation#metadata metadata} field type is
760
762
  # {Google::Cloud::Bigtable::Admin::RestoreTableMetadata RestoreTableMetadata}. The
761
763
  # {Google::Longrunning::Operation#response response} type is
762
764
  # {Google::Cloud::Bigtable::Admin::V2::Table Table}, if successful.
763
765
  #
764
- def restore_table table_id, instance_id, cluster_id, backup_id
765
- tables.restore_table parent: instance_path(instance_id),
766
+ def restore_table table_id, instance_id, cluster_id, backup_id, table_instance_id: nil
767
+ table_instance_id ||= instance_id
768
+ tables.restore_table parent: instance_path(table_instance_id),
766
769
  table_id: table_id,
767
770
  backup: backup_path(instance_id, cluster_id, backup_id)
768
771
  end
@@ -47,7 +47,10 @@ module Google
47
47
  # end
48
48
  #
49
49
  class Status
50
- attr_reader :code, :description, :message, :details
50
+ attr_reader :code
51
+ attr_reader :description
52
+ attr_reader :message
53
+ attr_reader :details
51
54
 
52
55
  ##
53
56
  # @private Creates a Status object.
@@ -56,6 +56,14 @@ module Google
56
56
  # The gRPC Service object.
57
57
  attr_accessor :service
58
58
 
59
+ # @private
60
+ # The current gRPC resource, for testing only.
61
+ attr_accessor :grpc
62
+
63
+ # @private
64
+ # The current loaded_views, for testing only. See #check_view_and_load, below.
65
+ attr_reader :loaded_views
66
+
59
67
  ##
60
68
  # @return [String] App profile ID for request routing.
61
69
  #
@@ -64,10 +72,11 @@ module Google
64
72
  # @private
65
73
  #
66
74
  # Creates a new Table instance.
67
- def initialize grpc, service, view: nil
75
+ def initialize grpc, service, view:
68
76
  @grpc = grpc
69
77
  @service = service
70
- @view = view || :SCHEMA_VIEW
78
+ raise ArgumentError, "view must not be nil" if view.nil?
79
+ @loaded_views = Set[view]
71
80
  end
72
81
 
73
82
  ##
@@ -109,7 +118,8 @@ module Google
109
118
  end
110
119
 
111
120
  ##
112
- # Reloads table data.
121
+ # Reloads table data with the provided `view`, or with `SCHEMA_VIEW`
122
+ # if none is provided. Previously loaded data is not retained.
113
123
  #
114
124
  # @param view [Symbol] Table view type.
115
125
  # Default view type is `:SCHEMA_VIEW`.
@@ -123,22 +133,41 @@ module Google
123
133
  # @return [Google::Cloud::Bigtable::Table]
124
134
  #
125
135
  def reload! view: nil
126
- @view = view || :SCHEMA_VIEW
136
+ view ||= :SCHEMA_VIEW
127
137
  @grpc = service.get_table instance_id, name, view: view
138
+ @loaded_views = Set[view]
128
139
  self
129
140
  end
130
141
 
131
142
  ##
132
- # Map from cluster ID to per-cluster table state.
143
+ # Returns an array of {Table::ClusterState} objects that map cluster ID
144
+ # to per-cluster table state.
145
+ #
133
146
  # If it could not be determined whether or not the table has data in a
134
147
  # particular cluster (for example, if its zone is unavailable), then
135
- # there will be an entry for the cluster with UNKNOWN `replication_status`.
136
- # Views: `FULL`.
148
+ # the cluster state's `replication_state` will be `UNKNOWN`.
149
+ #
150
+ # Reloads the table with the `FULL` view type to retrieve the cluster states
151
+ # data, unless the table was previously loaded with view type `ENCRYPTION_VIEW`,
152
+ # `REPLICATION_VIEW` or `FULL`.
137
153
  #
138
154
  # @return [Array<Google::Cloud::Bigtable::Table::ClusterState>]
139
155
  #
156
+ # @example Retrieve a table with cluster states.
157
+ # require "google/cloud/bigtable"
158
+ #
159
+ # bigtable = Google::Cloud::Bigtable.new
160
+ #
161
+ # table = bigtable.table("my-instance", "my-table", view: :FULL, perform_lookup: true)
162
+ #
163
+ # table.cluster_states.each do |cs|
164
+ # puts cs.cluster_name
165
+ # puts cs.replication_state
166
+ # puts cs.encryption_infos.first.encryption_type
167
+ # end
168
+ #
140
169
  def cluster_states
141
- check_view_and_load :REPLICATION_VIEW
170
+ check_view_and_load :FULL, skip_if: [:ENCRYPTION_VIEW, :REPLICATION_VIEW]
142
171
  @grpc.cluster_states.map do |name, state_grpc|
143
172
  ClusterState.from_grpc state_grpc, name
144
173
  end
@@ -146,15 +175,19 @@ module Google
146
175
 
147
176
  ##
148
177
  # Returns a frozen object containing the column families configured for
149
- # the table, mapped by column family name. Reloads the table if
150
- # necessary to retrieve the column families data, since it is only
151
- # available in a table with view type `SCHEMA_VIEW` or `FULL`.
178
+ # the table, mapped by column family name.
179
+ #
180
+ # Reloads the table if necessary to retrieve the column families data,
181
+ # since it is only available in a table with view type `SCHEMA_VIEW`
182
+ # or `FULL`. Previously loaded data is retained.
152
183
  #
153
184
  # Also accepts a block for making modifications to the table's column
154
185
  # families. After the modifications are completed, the table will be
155
186
  # updated with the changes, and the updated column families will be
156
187
  # returned.
157
188
  #
189
+ # @see https://cloud.google.com/bigtable/docs/garbage-collection Garbage collection
190
+ #
158
191
  # @yield [column_families] A block for modifying the table's column
159
192
  # families. Applies multiple column modifications. Performs a series
160
193
  # of column family modifications on the specified table. Either all or
@@ -222,7 +255,10 @@ module Google
222
255
  # The granularity (e.g. `MILLIS`, `MICROS`) at which timestamps are stored in
223
256
  # this table. Timestamps not matching the granularity will be rejected.
224
257
  # If unspecified at creation time, the value will be set to `MILLIS`.
225
- # Views: `SCHEMA_VIEW`, `FULL`.
258
+ #
259
+ # Reloads the table if necessary to retrieve the column families data,
260
+ # since it is only available in a table with view type `SCHEMA_VIEW`
261
+ # or `FULL`. Previously loaded data is retained.
226
262
  #
227
263
  # @return [Symbol]
228
264
  #
@@ -437,7 +473,7 @@ module Google
437
473
  }.delete_if { |_, v| v.nil? })
438
474
 
439
475
  grpc = service.create_table instance_id, table_id, table, initial_splits: initial_splits
440
- from_grpc grpc, service
476
+ from_grpc grpc, service, view: :SCHEMA_VIEW
441
477
  end
442
478
 
443
479
  ##
@@ -623,7 +659,7 @@ module Google
623
659
  # @param view [Symbol] View type.
624
660
  # @return [Google::Cloud::Bigtable::Table]
625
661
  #
626
- def self.from_grpc grpc, service, view: nil
662
+ def self.from_grpc grpc, service, view:
627
663
  new grpc, service, view: view
628
664
  end
629
665
 
@@ -653,20 +689,24 @@ module Google
653
689
 
654
690
  FIELDS_BY_VIEW = {
655
691
  SCHEMA_VIEW: ["granularity", "column_families"],
692
+ ENCRYPTION_VIEW: ["cluster_states"],
656
693
  REPLICATION_VIEW: ["cluster_states"],
657
694
  FULL: ["granularity", "column_families", "cluster_states"]
658
695
  }.freeze
659
696
 
660
697
  # @private
661
698
  #
662
- # Checks and reloads table with expected view and sets fields.
663
- # @param view [Symbol] Expected view type.
699
+ # Checks and reloads table with expected view. Performs additive updates to fields specified by the given view.
700
+ # @param view [Symbol] The view type to load. If already loaded, no load is performed.
701
+ # @param skip_if [Symbol] Additional satisfying view types. If already loaded, no load is performed.
664
702
  #
665
- def check_view_and_load view
703
+ def check_view_and_load view, skip_if: nil
666
704
  ensure_service!
667
- @loaded_views ||= Set.new [@view]
668
705
 
669
- return if @loaded_views.include?(view) || @loaded_views.include?(:FULL)
706
+ skip = Set.new skip_if
707
+ skip << view
708
+ skip << :FULL
709
+ return if (@loaded_views & skip).any?
670
710
 
671
711
  grpc = service.get_table instance_id, table_id, view: view
672
712
  @loaded_views << view
@@ -674,6 +714,9 @@ module Google
674
714
  FIELDS_BY_VIEW[view].each do |field|
675
715
  case grpc[field]
676
716
  when Google::Protobuf::Map
717
+ # Special handling for column_families:
718
+ # Replace contents of existing Map since setting the new Map won't work.
719
+ # See https://github.com/protocolbuffers/protobuf/issues/4969
677
720
  @grpc[field].clear
678
721
  grpc[field].each { |k, v| @grpc[field][k] = v }
679
722
  else