google-cloud-spanner 2.3.0 → 2.8.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 (35) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +64 -0
  3. data/CONTRIBUTING.md +1 -1
  4. data/LOGGING.md +1 -1
  5. data/OVERVIEW.md +1 -1
  6. data/lib/google-cloud-spanner.rb +2 -0
  7. data/lib/google/cloud/spanner/backup.rb +75 -4
  8. data/lib/google/cloud/spanner/backup/job.rb +8 -8
  9. data/lib/google/cloud/spanner/backup/job/list.rb +2 -2
  10. data/lib/google/cloud/spanner/backup/list.rb +2 -2
  11. data/lib/google/cloud/spanner/batch_snapshot.rb +11 -4
  12. data/lib/google/cloud/spanner/batch_update.rb +3 -1
  13. data/lib/google/cloud/spanner/client.rb +315 -83
  14. data/lib/google/cloud/spanner/commit.rb +4 -0
  15. data/lib/google/cloud/spanner/data.rb +4 -5
  16. data/lib/google/cloud/spanner/database.rb +111 -3
  17. data/lib/google/cloud/spanner/database/backup_info.rb +12 -3
  18. data/lib/google/cloud/spanner/database/job/list.rb +2 -2
  19. data/lib/google/cloud/spanner/database/list.rb +4 -4
  20. data/lib/google/cloud/spanner/fields.rb +5 -3
  21. data/lib/google/cloud/spanner/instance.rb +91 -3
  22. data/lib/google/cloud/spanner/instance/config/list.rb +4 -4
  23. data/lib/google/cloud/spanner/instance/list.rb +4 -4
  24. data/lib/google/cloud/spanner/partition.rb +4 -2
  25. data/lib/google/cloud/spanner/policy.rb +3 -2
  26. data/lib/google/cloud/spanner/pool.rb +10 -10
  27. data/lib/google/cloud/spanner/project.rb +65 -5
  28. data/lib/google/cloud/spanner/results.rb +13 -9
  29. data/lib/google/cloud/spanner/service.rb +44 -24
  30. data/lib/google/cloud/spanner/session.rb +38 -15
  31. data/lib/google/cloud/spanner/snapshot.rb +10 -2
  32. data/lib/google/cloud/spanner/status.rb +4 -1
  33. data/lib/google/cloud/spanner/transaction.rb +61 -6
  34. data/lib/google/cloud/spanner/version.rb +1 -1
  35. metadata +10 -10
@@ -71,7 +71,7 @@ module Google
71
71
  return nil unless next?
72
72
  ensure_service!
73
73
  options = { token: token, max: @max }
74
- grpc = @service.list_instances options
74
+ grpc = @service.list_instances(**options)
75
75
  self.class.from_grpc grpc, @service, @max
76
76
  end
77
77
 
@@ -120,17 +120,17 @@ module Google
120
120
  # puts instance.instance_id
121
121
  # end
122
122
  #
123
- def all request_limit: nil
123
+ def all request_limit: nil, &block
124
124
  request_limit = request_limit.to_i if request_limit
125
125
  unless block_given?
126
126
  return enum_for :all, request_limit: request_limit
127
127
  end
128
128
  results = self
129
129
  loop do
130
- results.each { |r| yield r }
130
+ results.each(&block)
131
131
  if request_limit
132
132
  request_limit -= 1
133
- break if request_limit < 0
133
+ break if request_limit.negative?
134
134
  end
135
135
  break unless results.next?
136
136
  results = results.next
@@ -45,11 +45,13 @@ module Google
45
45
  #
46
46
  class Partition
47
47
  # @ private
48
- attr_reader :execute, :read
48
+ attr_reader :execute
49
+ attr_reader :read
49
50
 
50
51
  ##
51
52
  # @private Creates a Partition object.
52
- def initialize; end
53
+ def initialize
54
+ end
53
55
 
54
56
  ##
55
57
  # Whether the partition was created for an execute_query/query
@@ -70,7 +70,8 @@ module Google
70
70
  # end
71
71
  #
72
72
  class Policy
73
- attr_reader :etag, :roles
73
+ attr_reader :etag
74
+ attr_reader :roles
74
75
 
75
76
  ##
76
77
  # @private Creates a Policy object.
@@ -169,7 +170,7 @@ module Google
169
170
  role: role_name,
170
171
  members: roles[role_name]
171
172
  )
172
- end
173
+ end.compact
173
174
  )
174
175
  end
175
176
 
@@ -29,7 +29,9 @@ module Google
29
29
  # {Google::Cloud::Spanner::Session} instances.
30
30
  #
31
31
  class Pool
32
- attr_accessor :all_sessions, :session_queue, :transaction_queue
32
+ attr_accessor :all_sessions
33
+ attr_accessor :session_queue
34
+ attr_accessor :transaction_queue
33
35
 
34
36
  def initialize client, min: 10, max: 100, keepalive: 1800,
35
37
  write_ratio: 0.3, fail: true, threads: nil
@@ -38,7 +40,7 @@ module Google
38
40
  @max = max
39
41
  @keepalive = keepalive
40
42
  @write_ratio = write_ratio
41
- @write_ratio = 0 if write_ratio < 0
43
+ @write_ratio = 0 if write_ratio.negative?
42
44
  @write_ratio = 1 if write_ratio > 1
43
45
  @fail = fail
44
46
  @threads = threads || [2, Concurrent.processor_count * 2].max
@@ -143,13 +145,13 @@ module Google
143
145
  return new_transaction! if action == :new
144
146
  end
145
147
 
146
- def checkin_transaction tx
148
+ def checkin_transaction txn
147
149
  @mutex.synchronize do
148
- unless all_sessions.include? tx.session
150
+ unless all_sessions.include? txn.session
149
151
  raise ArgumentError, "Cannot checkin session"
150
152
  end
151
153
 
152
- transaction_queue.push tx
154
+ transaction_queue.push txn
153
155
 
154
156
  @resource.signal
155
157
  end
@@ -182,7 +184,7 @@ module Google
182
184
  @mutex.synchronize do
183
185
  available_count = session_queue.count + transaction_queue.count
184
186
  release_count = @min - available_count
185
- release_count = 0 if release_count < 0
187
+ release_count = 0 if release_count.negative?
186
188
 
187
189
  to_keepalive += (session_queue + transaction_queue).select do |x|
188
190
  x.idle_since? @keepalive
@@ -282,10 +284,8 @@ module Google
282
284
  @keepalive_task.execute
283
285
  end
284
286
 
285
- def future
286
- Concurrent::Future.new executor: @thread_pool do
287
- yield
288
- end.execute
287
+ def future &block
288
+ Concurrent::Future.new(executor: @thread_pool, &block).execute
289
289
  end
290
290
  end
291
291
  end
@@ -177,7 +177,10 @@ module Google
177
177
  # configuration. Values can be the `instance_config_id`, the full
178
178
  # path, or an {Instance::Config} object. Required.
179
179
  # @param [Integer] nodes The number of nodes allocated to this instance.
180
- # Required.
180
+ # Optional. Specify either `nodes` or `processing_units`
181
+ # @param [Integer] processing_units The number of processing units
182
+ # allocated to this instance. Optional. Specify either `nodes`
183
+ # or `processing_units`
181
184
  # @param [Hash] labels Cloud Labels are a flexible and lightweight
182
185
  # mechanism for organizing cloud resources into groups that reflect a
183
186
  # customer's organizational needs and deployment strategies. Cloud
@@ -195,6 +198,7 @@ module Google
195
198
  #
196
199
  # @return [Instance::Job] The job representing the long-running,
197
200
  # asynchronous processing of an instance create operation.
201
+ # @raise [ArgumentError] if both processing_units or nodes are specified.
198
202
  #
199
203
  # @example
200
204
  # require "google/cloud/spanner"
@@ -217,14 +221,36 @@ module Google
217
221
  # instance = job.instance
218
222
  # end
219
223
  #
224
+ # @example Create instance using processsing units
225
+ # require "google/cloud/spanner"
226
+ #
227
+ # spanner = Google::Cloud::Spanner.new
228
+ #
229
+ # job = spanner.create_instance "my-new-instance",
230
+ # name: "My New Instance",
231
+ # config: "regional-us-central1",
232
+ # processing_units: 500,
233
+ # labels: { production: :env }
234
+ #
235
+ # job.done? #=> false
236
+ # job.reload! # API call
237
+ # job.done? #=> true
238
+ #
239
+ # if job.error?
240
+ # status = job.error
241
+ # else
242
+ # instance = job.instance
243
+ # end
244
+ #
220
245
  def create_instance instance_id, name: nil, config: nil, nodes: nil,
221
- labels: nil
246
+ processing_units: nil, labels: nil
222
247
  config = config.path if config.respond_to? :path
248
+
223
249
  # Convert from possible Google::Protobuf::Map
224
250
  labels = Hash[labels.map { |k, v| [String(k), String(v)] }] if labels
225
251
  grpc = service.create_instance \
226
252
  instance_id, name: name, config: config, nodes: nodes,
227
- labels: labels
253
+ processing_units: processing_units, labels: labels
228
254
  Instance::Job.from_grpc grpc, service
229
255
  end
230
256
 
@@ -380,6 +406,13 @@ module Google
380
406
  # These statements execute atomically with the creation of the
381
407
  # database: if there is an error in any statement, the database is not
382
408
  # created. Optional.
409
+ # @param [Hash] encryption_config An encryption configuration describing
410
+ # the encryption type and key resources in Cloud KMS. Optional. The
411
+ # following settings can be provided:
412
+ #
413
+ # * `:kms_key_name` (String) The name of KMS key to use which should
414
+ # be the full path, e.g., `projects/<project>/locations/<location>\
415
+ # /keyRings/<key_ring>/cryptoKeys/<kms_key_name>`
383
416
  #
384
417
  # @return [Database::Job] The job representing the long-running,
385
418
  # asynchronous processing of a database create operation.
@@ -402,9 +435,32 @@ module Google
402
435
  # database = job.database
403
436
  # end
404
437
  #
405
- def create_database instance_id, database_id, statements: []
438
+ # @example Create with encryption config
439
+ # require "google/cloud/spanner"
440
+ #
441
+ # spanner = Google::Cloud::Spanner.new
442
+ #
443
+ # kms_key_name = "projects/<project>/locations/<location>/keyRings/<key_ring>/cryptoKeys/<kms_key_name>"
444
+ # encryption_config = { kms_key_name: kms_key_name }
445
+ # job = spanner.create_database "my-instance",
446
+ # "my-new-database",
447
+ # encryption_config: encryption_config
448
+ #
449
+ # job.done? #=> false
450
+ # job.reload! # API call
451
+ # job.done? #=> true
452
+ #
453
+ # if job.error?
454
+ # status = job.error
455
+ # else
456
+ # database = job.database
457
+ # end
458
+ #
459
+ def create_database instance_id, database_id, statements: [],
460
+ encryption_config: nil
406
461
  grpc = service.create_database instance_id, database_id,
407
- statements: statements
462
+ statements: statements,
463
+ encryption_config: encryption_config
408
464
  Database::Job.from_grpc grpc, service
409
465
  end
410
466
 
@@ -460,6 +516,8 @@ module Google
460
516
  # * `:optimizer_version` (String) The version of optimizer to use.
461
517
  # Empty to use database default. "latest" to use the latest
462
518
  # available optimizer version.
519
+ # * `:optimizer_statistics_package` (String) Statistics package to
520
+ # use. Empty to use the database default.
463
521
  #
464
522
  # @return [Client] The newly created client.
465
523
  #
@@ -524,6 +582,8 @@ module Google
524
582
  # * `:optimizer_version` (String) The version of optimizer to use.
525
583
  # Empty to use database default. "latest" to use the latest
526
584
  # available optimizer version.
585
+ # * `:optimizer_statistics_package` (String) Statistics package to
586
+ # use. Empty to use the database default.
527
587
  #
528
588
  # @return [Client] The newly created client.
529
589
  #
@@ -251,14 +251,14 @@ module Google
251
251
  @service.execute_streaming_sql(
252
252
  @session_path,
253
253
  @sql,
254
- @execute_query_options.merge(resume_token: resume_token)
254
+ **@execute_query_options.merge(resume_token: resume_token)
255
255
  )
256
256
  else
257
257
  @service.streaming_read_table(
258
258
  @session_path,
259
259
  @table,
260
260
  @columns,
261
- @read_options.merge(resume_token: resume_token)
261
+ **@read_options.merge(resume_token: resume_token)
262
262
  )
263
263
  end
264
264
  end
@@ -268,9 +268,9 @@ module Google
268
268
  # Retries a request, by re-executing it from scratch.
269
269
  def retry_request
270
270
  if @execute_query_options
271
- @service.execute_streaming_sql @session_path, @sql, @execute_query_options
271
+ @service.execute_streaming_sql @session_path, @sql, **@execute_query_options
272
272
  else
273
- @service.streaming_read_table @session_path, @table, @columns, @read_options
273
+ @service.streaming_read_table @session_path, @table, @columns, **@read_options
274
274
  end
275
275
  end
276
276
 
@@ -319,14 +319,16 @@ module Google
319
319
  def self.execute_query service, session_path, sql, params: nil,
320
320
  types: nil, transaction: nil,
321
321
  partition_token: nil, seqno: nil,
322
- query_options: nil, call_options: nil
322
+ query_options: nil, request_options: nil,
323
+ call_options: nil
323
324
  execute_query_options = {
324
325
  transaction: transaction, params: params, types: types,
325
326
  partition_token: partition_token, seqno: seqno,
326
- query_options: query_options, call_options: call_options
327
+ query_options: query_options, request_options: request_options,
328
+ call_options: call_options
327
329
  }
328
330
  enum = service.execute_streaming_sql session_path, sql,
329
- execute_query_options
331
+ **execute_query_options
330
332
  from_enum(enum, service).tap do |results|
331
333
  results.instance_variable_set :@session_path, session_path
332
334
  results.instance_variable_set :@sql, sql
@@ -338,15 +340,17 @@ module Google
338
340
  # @private
339
341
  def self.read service, session_path, table, columns, keys: nil,
340
342
  index: nil, limit: nil, transaction: nil,
341
- partition_token: nil, call_options: nil
343
+ partition_token: nil, request_options: nil,
344
+ call_options: nil
342
345
  read_options = {
343
346
  keys: keys, index: index, limit: limit,
344
347
  transaction: transaction,
345
348
  partition_token: partition_token,
349
+ request_options: request_options,
346
350
  call_options: call_options
347
351
  }
348
352
  enum = service.streaming_read_table \
349
- session_path, table, columns, read_options
353
+ session_path, table, columns, **read_options
350
354
  from_enum(enum, service).tap do |results|
351
355
  results.instance_variable_set :@session_path, session_path
352
356
  results.instance_variable_set :@table, table
@@ -28,8 +28,12 @@ module Google
28
28
  # @private Represents the gRPC Spanner service, including all the API
29
29
  # methods.
30
30
  class Service
31
- attr_accessor :project, :credentials, :timeout, :host, :lib_name,
32
- :lib_version
31
+ attr_accessor :project
32
+ attr_accessor :credentials
33
+ attr_accessor :timeout
34
+ attr_accessor :host
35
+ attr_accessor :lib_name
36
+ attr_accessor :lib_version
33
37
 
34
38
  ##
35
39
  # Creates a new Service instance.
@@ -123,13 +127,15 @@ module Google
123
127
  end
124
128
 
125
129
  def create_instance instance_id, name: nil, config: nil, nodes: nil,
126
- labels: nil, call_options: nil
130
+ processing_units: nil, labels: nil,
131
+ call_options: nil
127
132
  opts = default_options call_options: call_options
128
133
  labels = Hash[labels.map { |k, v| [String(k), String(v)] }] if labels
129
134
 
130
135
  create_obj = Admin::Instance::V1::Instance.new({
131
136
  display_name: name, config: instance_config_path(config),
132
- node_count: nodes, labels: labels
137
+ node_count: nodes, processing_units: processing_units,
138
+ labels: labels
133
139
  }.delete_if { |_, v| v.nil? })
134
140
 
135
141
  request = {
@@ -140,12 +146,17 @@ module Google
140
146
  instances.create_instance request, opts
141
147
  end
142
148
 
143
- def update_instance instance, call_options: nil
149
+ def update_instance instance, field_mask: nil, call_options: nil
144
150
  opts = default_options call_options: call_options
145
- mask = Google::Protobuf::FieldMask.new(
146
- paths: %w[display_name node_count labels]
147
- )
148
- request = { instance: instance, field_mask: mask }
151
+
152
+ if field_mask.nil? || field_mask.empty?
153
+ field_mask = %w[display_name node_count labels]
154
+ end
155
+
156
+ request = {
157
+ instance: instance,
158
+ field_mask: Google::Protobuf::FieldMask.new(paths: field_mask)
159
+ }
149
160
  instances.update_instance request, opts
150
161
  end
151
162
 
@@ -210,12 +221,13 @@ module Google
210
221
  end
211
222
 
212
223
  def create_database instance_id, database_id, statements: [],
213
- call_options: nil
224
+ call_options: nil, encryption_config: nil
214
225
  opts = default_options call_options: call_options
215
226
  request = {
216
227
  parent: instance_path(instance_id),
217
228
  create_statement: "CREATE DATABASE `#{database_id}`",
218
- extra_statements: Array(statements)
229
+ extra_statements: Array(statements),
230
+ encryption_config: encryption_config
219
231
  }
220
232
  databases.create_database request, opts
221
233
  end
@@ -308,7 +320,8 @@ module Google
308
320
  def execute_streaming_sql session_name, sql, transaction: nil,
309
321
  params: nil, types: nil, resume_token: nil,
310
322
  partition_token: nil, seqno: nil,
311
- query_options: nil, call_options: nil
323
+ query_options: nil, request_options: nil,
324
+ call_options: nil
312
325
  opts = default_options session_name: session_name,
313
326
  call_options: call_options
314
327
  request = {
@@ -320,13 +333,14 @@ module Google
320
333
  resume_token: resume_token,
321
334
  partition_token: partition_token,
322
335
  seqno: seqno,
323
- query_options: query_options
336
+ query_options: query_options,
337
+ request_options: request_options
324
338
  }
325
339
  service.execute_streaming_sql request, opts
326
340
  end
327
341
 
328
342
  def execute_batch_dml session_name, transaction, statements, seqno,
329
- call_options: nil
343
+ request_options: nil, call_options: nil
330
344
  opts = default_options session_name: session_name,
331
345
  call_options: call_options
332
346
  statements = statements.map(&:to_grpc)
@@ -334,7 +348,8 @@ module Google
334
348
  session: session_name,
335
349
  transaction: transaction,
336
350
  statements: statements,
337
- seqno: seqno
351
+ seqno: seqno,
352
+ request_options: request_options
338
353
  }
339
354
  results = service.execute_batch_dml request, opts
340
355
 
@@ -352,14 +367,14 @@ module Google
352
367
  def streaming_read_table session_name, table_name, columns, keys: nil,
353
368
  index: nil, transaction: nil, limit: nil,
354
369
  resume_token: nil, partition_token: nil,
355
- call_options: nil
370
+ request_options: nil, call_options: nil
356
371
  opts = default_options session_name: session_name,
357
372
  call_options: call_options
358
373
  request = {
359
374
  session: session_name, table: table_name, columns: columns,
360
375
  key_set: keys, transaction: transaction, index: index,
361
376
  limit: limit, resume_token: resume_token,
362
- partition_token: partition_token
377
+ partition_token: partition_token, request_options: request_options
363
378
  }
364
379
  service.streaming_read request, opts
365
380
  end
@@ -397,7 +412,7 @@ module Google
397
412
  end
398
413
 
399
414
  def commit session_name, mutations = [], transaction_id: nil,
400
- commit_options: nil, call_options: nil
415
+ commit_options: nil, request_options: nil, call_options: nil
401
416
  tx_opts = nil
402
417
  if transaction_id.nil?
403
418
  tx_opts = V1::TransactionOptions.new(
@@ -408,7 +423,8 @@ module Google
408
423
  call_options: call_options
409
424
  request = {
410
425
  session: session_name, transaction_id: transaction_id,
411
- single_use_transaction: tx_opts, mutations: mutations
426
+ single_use_transaction: tx_opts, mutations: mutations,
427
+ request_options: request_options
412
428
  }
413
429
 
414
430
  if commit_options
@@ -464,16 +480,19 @@ module Google
464
480
  end
465
481
 
466
482
  def create_backup instance_id, database_id, backup_id, expire_time,
467
- call_options: nil
483
+ version_time, call_options: nil,
484
+ encryption_config: nil
468
485
  opts = default_options call_options: call_options
469
486
  backup = {
470
487
  database: database_path(instance_id, database_id),
471
- expire_time: expire_time
488
+ expire_time: expire_time,
489
+ version_time: version_time
472
490
  }
473
491
  request = {
474
492
  parent: instance_path(instance_id),
475
493
  backup_id: backup_id,
476
- backup: backup
494
+ backup: backup,
495
+ encryption_config: encryption_config
477
496
  }
478
497
  databases.create_backup request, opts
479
498
  end
@@ -540,12 +559,13 @@ module Google
540
559
 
541
560
  def restore_database backup_instance_id, backup_id,
542
561
  database_instance_id, database_id,
543
- call_options: nil
562
+ call_options: nil, encryption_config: nil
544
563
  opts = default_options call_options: call_options
545
564
  request = {
546
565
  parent: instance_path(database_instance_id),
547
566
  database_id: database_id,
548
- backup: backup_path(backup_instance_id, backup_id)
567
+ backup: backup_path(backup_instance_id, backup_id),
568
+ encryption_config: encryption_config
549
569
  }
550
570
  databases.restore_database request, opts
551
571
  end