google-cloud-spanner 2.27.0 → 2.28.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -0
- data/lib/google/cloud/spanner/backup/job/list.rb +8 -6
- data/lib/google/cloud/spanner/backup/job.rb +11 -6
- data/lib/google/cloud/spanner/batch_client.rb +18 -5
- data/lib/google/cloud/spanner/client.rb +55 -14
- data/lib/google/cloud/spanner/instance.rb +14 -5
- data/lib/google/cloud/spanner/interval.rb +1 -1
- data/lib/google/cloud/spanner/partition.rb +7 -1
- data/lib/google/cloud/spanner/pool.rb +15 -0
- data/lib/google/cloud/spanner/project.rb +17 -5
- data/lib/google/cloud/spanner/results.rb +102 -30
- data/lib/google/cloud/spanner/service.rb +142 -10
- data/lib/google/cloud/spanner/session.rb +67 -33
- data/lib/google/cloud/spanner/transaction.rb +77 -31
- data/lib/google/cloud/spanner/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 850ac8a54d873ff6d92cc7d7b835abd1d0fd980d22529296b036b67d5c4ecbfe
|
|
4
|
+
data.tar.gz: 585441baf49b27942fddc9876044221965fe9edd475bdf8f6c53f463a3a75cf0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: dca36d5f2479c792b0c7e10051cf52915314c76de12581d09ff8284ae8e591430d2d67f779c71b2956580e4f970054ddcac3d3f8429ed8ced759b8cd0be0339a
|
|
7
|
+
data.tar.gz: 887212c39b640de69edf12df3bca506494a7bb65c6f0b102eb80cefb3c41e8c3511b027f18334669ab58a9d1ba7114ab1d5bdc83d4982c39521ff4d542b94344
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Release History
|
|
2
2
|
|
|
3
|
+
### 2.28.0 (2025-10-22)
|
|
4
|
+
|
|
5
|
+
#### Features
|
|
6
|
+
|
|
7
|
+
* Add support for order_by and lock_hint options ([#182](https://github.com/googleapis/ruby-spanner/issues/182))
|
|
8
|
+
|
|
9
|
+
#### Bug Fixes
|
|
10
|
+
|
|
11
|
+
* use create Transaction when retrying when enumerating rows in `Spanner::Results` ([#191](https://github.com/googleapis/ruby-spanner/issues/191))
|
|
12
|
+
* run explicit BeginTransaction in Client#transaction for mutation-only payloads ([#191](https://github.com/googleapis/ruby-spanner/issues/191))
|
|
13
|
+
* Transaction#initialize is no longer incorrectly marked as public in documentation ([#191](https://github.com/googleapis/ruby-spanner/issues/191))
|
|
14
|
+
* several field accessors in Partition are no longer incorrectly marked as public in documentation ([#191](https://github.com/googleapis/ruby-spanner/issues/191))
|
|
15
|
+
* session keepalive uses Process.clock_gettime instead of Time.now ([#185](https://github.com/googleapis/ruby-spanner/pull/185))
|
|
16
|
+
|
|
3
17
|
### 2.27.0 (2025-05-28)
|
|
4
18
|
|
|
5
19
|
#### Features
|
|
@@ -33,8 +33,9 @@ module Google
|
|
|
33
33
|
# {Google::Cloud::Spanner::Admin::Database.database_admin}.list_backup_operations instead.
|
|
34
34
|
#
|
|
35
35
|
class List < DelegateClass(::Array)
|
|
36
|
+
# The `Spanner::Service` reference.
|
|
36
37
|
# @private
|
|
37
|
-
#
|
|
38
|
+
# @return [::Google::Cloud::Spanner::Service]
|
|
38
39
|
attr_accessor :service
|
|
39
40
|
|
|
40
41
|
# @private
|
|
@@ -148,13 +149,14 @@ module Google
|
|
|
148
149
|
end
|
|
149
150
|
end
|
|
150
151
|
|
|
151
|
-
|
|
152
|
-
# @private
|
|
153
|
-
#
|
|
154
|
-
# New Backup::Job::List from a
|
|
152
|
+
# Creates a new `Spanner::Backup::Job::List` of `Gapic::Operation` operations from a
|
|
155
153
|
# `Gapic::PagedEnumerable<Google::Longrunning::Operation>`
|
|
156
154
|
# object. Operation object is a backup operation.
|
|
157
|
-
#
|
|
155
|
+
# @param grpc [::Gapic::PagedEnumerable<::Google::Longrunning::Operation>]
|
|
156
|
+
# Wrapped `Gapic::PagedEnumberable` reference.
|
|
157
|
+
# @param service [::Google::Cloud::Spanner::Service] A `Spanner::Service` reference.
|
|
158
|
+
# @private
|
|
159
|
+
# @return [::Google::Cloud::Spanner::Backup::Job::List]
|
|
158
160
|
def self.from_grpc grpc, service
|
|
159
161
|
operations_client =
|
|
160
162
|
service.databases.instance_variable_get "@operations_client"
|
|
@@ -58,12 +58,14 @@ module Google
|
|
|
58
58
|
# end
|
|
59
59
|
#
|
|
60
60
|
class Job
|
|
61
|
-
|
|
62
|
-
# @private
|
|
61
|
+
# The wrapped `Gapic::Operation` object.
|
|
62
|
+
# @private
|
|
63
|
+
# @return [::Gapic::Operation]
|
|
63
64
|
attr_accessor :grpc
|
|
64
65
|
|
|
65
|
-
|
|
66
|
-
# @private
|
|
66
|
+
# The `Spanner::Service` reference.
|
|
67
|
+
# @private
|
|
68
|
+
# @return [::Google::Cloud::Spanner::Service]
|
|
67
69
|
attr_accessor :service
|
|
68
70
|
|
|
69
71
|
##
|
|
@@ -265,8 +267,11 @@ module Google
|
|
|
265
267
|
Convert.timestamp_to_time @grpc.metadata.cancel_time
|
|
266
268
|
end
|
|
267
269
|
|
|
268
|
-
|
|
269
|
-
# @
|
|
270
|
+
# Create a new Backup::Job from a `Gapic::Operation` object.
|
|
271
|
+
# @param grpc [::Gapic::Operation`] The wrapped `Gapic::Operation` object.
|
|
272
|
+
# @param service [::Google::Cloud::Spanner::Service] A `Spanner::Service` reference.
|
|
273
|
+
# @private
|
|
274
|
+
# @return [::Google::Cloud::Spanner::Backup::Job]
|
|
270
275
|
def self.from_grpc grpc, service
|
|
271
276
|
new.tap do |job|
|
|
272
277
|
job.instance_variable_set :@grpc, grpc
|
|
@@ -63,8 +63,18 @@ module Google
|
|
|
63
63
|
# new_partition
|
|
64
64
|
#
|
|
65
65
|
class BatchClient
|
|
66
|
-
|
|
67
|
-
# @
|
|
66
|
+
# Creates a new Spanner BatchClient instance.
|
|
67
|
+
# @param project [::Google::Cloud::Spanner::Project] A `Spanner::Project` ref.
|
|
68
|
+
# @param instance_id [::String] Instance id, e.g. `"my-instance"`.
|
|
69
|
+
# @param database_id [::String] Database id, e.g. `"my-database"`.
|
|
70
|
+
# @param session_labels [::Hash, nil] Optional. The labels to be applied to all sessions
|
|
71
|
+
# created by the client. Example: `"team" => "billing-service"`.
|
|
72
|
+
# @param query_options [::Hash, nil] Optional. A hash of values to specify the custom
|
|
73
|
+
# query options for executing SQL query. Example parameter `:optimizer_version`.
|
|
74
|
+
# @param directed_read_options [::Hash, nil] Optional. Client options used to set
|
|
75
|
+
# the `directed_read_options` for all ReadRequests and ExecuteSqlRequests.
|
|
76
|
+
# Converts to `V1::DirectedReadOptions`. Example option: `:exclude_replicas`.
|
|
77
|
+
# @private
|
|
68
78
|
def initialize project, instance_id, database_id, session_labels: nil,
|
|
69
79
|
query_options: nil, directed_read_options: nil
|
|
70
80
|
@project = project
|
|
@@ -404,15 +414,18 @@ module Google
|
|
|
404
414
|
|
|
405
415
|
protected
|
|
406
416
|
|
|
407
|
-
|
|
408
|
-
# @private Raise an error unless an active connection to the service is
|
|
417
|
+
# Raise an error unless an active connection to the service is
|
|
409
418
|
# available.
|
|
419
|
+
# @private
|
|
420
|
+
# @raise [StandardError]
|
|
421
|
+
# @return [nil]
|
|
410
422
|
def ensure_service!
|
|
411
423
|
raise "Must have active connection to service" unless @project.service
|
|
412
424
|
end
|
|
413
425
|
|
|
414
|
-
##
|
|
415
426
|
# New session for each use.
|
|
427
|
+
# @private
|
|
428
|
+
# @return [::Google::Cloud::Spanner::Session]
|
|
416
429
|
def session
|
|
417
430
|
ensure_service!
|
|
418
431
|
grpc = @project.service.create_session \
|
|
@@ -51,12 +51,26 @@ module Google
|
|
|
51
51
|
# end
|
|
52
52
|
#
|
|
53
53
|
class Client
|
|
54
|
-
|
|
54
|
+
# A semi-arbitrary constant for thread-wide global parameter name
|
|
55
55
|
# @private
|
|
56
56
|
IS_TRANSACTION_RUNNING_KEY = "ruby_spanner_is_transaction_running".freeze
|
|
57
57
|
|
|
58
|
-
|
|
59
|
-
# @
|
|
58
|
+
# Creates a new Spanner Client instance.
|
|
59
|
+
# @param project [::Google::Cloud::Spanner::Project] A `Spanner::Project` ref.
|
|
60
|
+
# @param instance_id [::String] Instance id, e.g. `"my-instance"`.
|
|
61
|
+
# @param database_id [::String] Database id, e.g. `"my-database"`.
|
|
62
|
+
# @param session_labels [::Hash, nil] Optional. The labels to be applied to all sessions
|
|
63
|
+
# created by the client. Example: `"team" => "billing-service"`.
|
|
64
|
+
# @param pool_opts [::Hash] Optional. `Spanner::Pool` creation options.
|
|
65
|
+
# Example parameter: `:keepalive`.
|
|
66
|
+
# @param query_options [::Hash, nil] Optional. A hash of values to specify the custom
|
|
67
|
+
# query options for executing SQL query. Example parameter `:optimizer_version`.
|
|
68
|
+
# @param database_role [::String, nil] Optional. The Spanner session creator role.
|
|
69
|
+
# Example: `analyst`
|
|
70
|
+
# @param directed_read_options [::Hash, nil] Optional. Client options used to set
|
|
71
|
+
# the `directed_read_options` for all ReadRequests and ExecuteSqlRequests.
|
|
72
|
+
# Converts to `V1::DirectedReadOptions`. Example option: `:exclude_replicas`.
|
|
73
|
+
# @private
|
|
60
74
|
def initialize project, instance_id, database_id, session_labels: nil,
|
|
61
75
|
pool_opts: {}, query_options: nil, database_role: nil,
|
|
62
76
|
directed_read_options: nil
|
|
@@ -89,7 +103,7 @@ module Google
|
|
|
89
103
|
end
|
|
90
104
|
|
|
91
105
|
# The Spanner project connected to.
|
|
92
|
-
# @return [Project]
|
|
106
|
+
# @return [::Google::Cloud::Spanner::Project]
|
|
93
107
|
def project
|
|
94
108
|
@project
|
|
95
109
|
end
|
|
@@ -878,6 +892,14 @@ module Google
|
|
|
878
892
|
# and all replicas are exhausted without finding a healthy replica,
|
|
879
893
|
# Spanner will wait for a replica in the list to become available,
|
|
880
894
|
# requests may fail due to DEADLINE_EXCEEDED errors.
|
|
895
|
+
# @param [::Google::Cloud::Spanner::V1::ReadRequest::OrderBy] order_by An option to control the order in which
|
|
896
|
+
# rows are returned from a read.
|
|
897
|
+
# To see the available options refer to
|
|
898
|
+
# [Google::Cloud::Spanner::V1::ReadRequest::OrderBy](https://cloud.google.com/ruby/docs/reference/google-cloud-spanner-v1/latest/Google-Cloud-Spanner-V1-ReadRequest-OrderBy)
|
|
899
|
+
# @param [::Google::Cloud::Spanner::V1::ReadRequest::LockHint] lock_hint A lock hint mechanism for reads done
|
|
900
|
+
# within a transaction.
|
|
901
|
+
# To see the available options refer to
|
|
902
|
+
# [Google::Cloud::Spanner::V1::ReadRequest::LockHint](https://cloud.google.com/ruby/docs/reference/google-cloud-spanner-v1/latest/Google-Cloud-Spanner-V1-ReadRequest-LockHint)
|
|
881
903
|
#
|
|
882
904
|
# @return [Google::Cloud::Spanner::Results] The results of the read.
|
|
883
905
|
#
|
|
@@ -962,7 +984,7 @@ module Google
|
|
|
962
984
|
#
|
|
963
985
|
def read table, columns, keys: nil, index: nil, limit: nil,
|
|
964
986
|
single_use: nil, request_options: nil, call_options: nil,
|
|
965
|
-
directed_read_options: nil
|
|
987
|
+
directed_read_options: nil, order_by: nil, lock_hint: nil
|
|
966
988
|
validate_single_use_args! single_use
|
|
967
989
|
ensure_service!
|
|
968
990
|
|
|
@@ -981,7 +1003,9 @@ module Google
|
|
|
981
1003
|
request_options: request_options,
|
|
982
1004
|
call_options: call_options,
|
|
983
1005
|
directed_read_options: directed_read_options || @directed_read_options,
|
|
984
|
-
route_to_leader: route_to_leader
|
|
1006
|
+
route_to_leader: route_to_leader,
|
|
1007
|
+
order_by: order_by,
|
|
1008
|
+
lock_hint: lock_hint
|
|
985
1009
|
end
|
|
986
1010
|
results
|
|
987
1011
|
end
|
|
@@ -2102,15 +2126,28 @@ module Google
|
|
|
2102
2126
|
begin
|
|
2103
2127
|
Thread.current[IS_TRANSACTION_RUNNING_KEY] = true
|
|
2104
2128
|
yield tx
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2129
|
+
|
|
2130
|
+
unless tx.existing_transaction?
|
|
2131
|
+
# This can happen if the yielded `tx` object was only used to add mutations.
|
|
2132
|
+
# Then it never called any RPCs and didn't create a server-side Transaction object.
|
|
2133
|
+
# In which case we should make an explicit BeginTransaction call here.
|
|
2134
|
+
tx.safe_begin_transaction!(
|
|
2135
|
+
exclude_from_change_streams: exclude_txn_from_change_streams,
|
|
2136
|
+
request_options: request_options,
|
|
2137
|
+
call_options: call_options
|
|
2138
|
+
)
|
|
2139
|
+
end
|
|
2140
|
+
|
|
2141
|
+
transaction_id = tx.transaction_id
|
|
2142
|
+
commit_resp = @project.service.commit(
|
|
2143
|
+
tx.session.path,
|
|
2144
|
+
tx.mutations,
|
|
2109
2145
|
transaction_id: transaction_id,
|
|
2110
2146
|
exclude_txn_from_change_streams: exclude_txn_from_change_streams,
|
|
2111
2147
|
commit_options: commit_options,
|
|
2112
2148
|
request_options: request_options,
|
|
2113
2149
|
call_options: call_options
|
|
2150
|
+
)
|
|
2114
2151
|
resp = CommitResponse.from_grpc commit_resp
|
|
2115
2152
|
commit_options ? resp : resp.timestamp
|
|
2116
2153
|
rescue GRPC::Aborted,
|
|
@@ -2409,17 +2446,21 @@ module Google
|
|
|
2409
2446
|
@pool.reset
|
|
2410
2447
|
end
|
|
2411
2448
|
|
|
2412
|
-
|
|
2449
|
+
# Creates a new Session objece.
|
|
2450
|
+
# @param multiplexed [::Boolean] Optional. Default to `false`.
|
|
2451
|
+
# If `true`, specifies a multiplexed session.
|
|
2413
2452
|
# @private
|
|
2414
|
-
#
|
|
2415
|
-
def create_new_session
|
|
2453
|
+
# @return [::Google::Cloud::Spanner::Session]
|
|
2454
|
+
def create_new_session multiplexed: false
|
|
2416
2455
|
ensure_service!
|
|
2417
2456
|
grpc = @project.service.create_session \
|
|
2418
2457
|
Admin::Database::V1::DatabaseAdmin::Paths.database_path(
|
|
2419
2458
|
project: project_id, instance: instance_id, database: database_id
|
|
2420
2459
|
),
|
|
2421
2460
|
labels: @session_labels,
|
|
2422
|
-
database_role: @database_role
|
|
2461
|
+
database_role: @database_role,
|
|
2462
|
+
multiplexed: multiplexed
|
|
2463
|
+
|
|
2423
2464
|
Session.from_grpc grpc, @project.service, query_options: @query_options
|
|
2424
2465
|
end
|
|
2425
2466
|
|
|
@@ -74,11 +74,16 @@ module Google
|
|
|
74
74
|
# end
|
|
75
75
|
#
|
|
76
76
|
class Instance
|
|
77
|
-
|
|
78
|
-
# @private
|
|
77
|
+
# The `Spanner::Service` reference.
|
|
78
|
+
# @private
|
|
79
|
+
# @return [::Google::Cloud::Spanner::Service]
|
|
79
80
|
attr_accessor :service
|
|
80
81
|
|
|
81
|
-
#
|
|
82
|
+
# Creates a new `Spanner::Instance` instance.
|
|
83
|
+
# @param grpc [::Google::Cloud::Spanner::Admin::Instance::V1::Instance]
|
|
84
|
+
# The protobuf `V1::Instance` underlying object.
|
|
85
|
+
# @param service [::Google::Cloud::Spanner::Service] A `Spanner::Service` reference.
|
|
86
|
+
# @private
|
|
82
87
|
def initialize grpc, service
|
|
83
88
|
@grpc = grpc
|
|
84
89
|
@service = service
|
|
@@ -957,9 +962,13 @@ module Google
|
|
|
957
962
|
grpc.permissions
|
|
958
963
|
end
|
|
959
964
|
|
|
960
|
-
|
|
961
|
-
# @private Creates a new Instance instance from a
|
|
965
|
+
# Creates a new Instance instance from a
|
|
962
966
|
# `Google::Cloud::Spanner::Admin::Instance::V1::Instance`.
|
|
967
|
+
# @param grpc [::Google::Cloud::Spanner::Admin::Instance::V1::Instance]
|
|
968
|
+
# The protobuf `V1::Instance` underlying object.
|
|
969
|
+
# @param service [::Google::Cloud::Spanner::Service] A `Spanner::Service` reference.
|
|
970
|
+
# @private
|
|
971
|
+
# @return [::Google::Cloud::Spanner::Instance]
|
|
963
972
|
def self.from_grpc grpc, service
|
|
964
973
|
new grpc, service
|
|
965
974
|
end
|
|
@@ -44,8 +44,14 @@ module Google
|
|
|
44
44
|
# results = batch_snapshot.execute_partition partition
|
|
45
45
|
#
|
|
46
46
|
class Partition
|
|
47
|
-
#
|
|
47
|
+
# A `V1::ExecuteSqlRequest` that is related to this partition.
|
|
48
|
+
# @private
|
|
49
|
+
# @return [::Google::Cloud::Spanner::V1::ExecuteSqlRequest]
|
|
48
50
|
attr_reader :execute
|
|
51
|
+
|
|
52
|
+
# A `V1::ReadRequest` that is related to this partition.
|
|
53
|
+
# @private
|
|
54
|
+
# @return [::Google::Cloud::Spanner::V1::ReadRequest]
|
|
49
55
|
attr_reader :read
|
|
50
56
|
|
|
51
57
|
##
|
|
@@ -36,6 +36,16 @@ module Google
|
|
|
36
36
|
# and `Session` objects as values.
|
|
37
37
|
attr_accessor :sessions_in_use
|
|
38
38
|
|
|
39
|
+
# Creates a new Session pool that manages non-multiplexed sessions.
|
|
40
|
+
# @param client [::Google::Cloud::Spanner::Client] A `Spanner::Client` reference
|
|
41
|
+
# @param min [::Integer] Min number of sessions to keep
|
|
42
|
+
# @param max [::Integer] Max number of sessions to keep
|
|
43
|
+
# @param keepalive [::Numeric] How long after their last usage the sessions can be reclaimed
|
|
44
|
+
# @param fail [::Boolean] If `true` the pool will raise `SessionLimitError` if number of new sessions
|
|
45
|
+
# needed is more that can be created due to the `max` parameter. If `false` it will wait instead.
|
|
46
|
+
# @param threads [::Integer, nil] Number of threads in the thread pool that is used for keepalive and
|
|
47
|
+
# release session actions. If `nil` the Pool will choose a reasonable default.
|
|
48
|
+
# @private
|
|
39
49
|
def initialize client, min: 10, max: 100, keepalive: 1800,
|
|
40
50
|
fail: true, threads: nil
|
|
41
51
|
@client = client
|
|
@@ -52,6 +62,11 @@ module Google
|
|
|
52
62
|
init
|
|
53
63
|
end
|
|
54
64
|
|
|
65
|
+
# Provides a session for running an operation
|
|
66
|
+
# @yield session Session a client can use to run an operation
|
|
67
|
+
# @yieldparam [::Google::Cloud::Spanner::Session] `Spanner::Session` to run an operation
|
|
68
|
+
# @private
|
|
69
|
+
# @return [nil]
|
|
55
70
|
def with_session
|
|
56
71
|
session = checkout_session
|
|
57
72
|
begin
|
|
@@ -66,12 +66,22 @@ module Google
|
|
|
66
66
|
# end
|
|
67
67
|
#
|
|
68
68
|
class Project
|
|
69
|
-
|
|
70
|
-
# @private
|
|
71
|
-
|
|
69
|
+
# The `Spanner::Service` reference.
|
|
70
|
+
# @private
|
|
71
|
+
# @return [::Google::Cloud::Spanner::Service]
|
|
72
|
+
attr_accessor :service
|
|
72
73
|
|
|
73
|
-
|
|
74
|
-
#
|
|
74
|
+
# A hash of values to specify the custom query options for executing SQL query.
|
|
75
|
+
# Example option: `:optimizer_version`.
|
|
76
|
+
# @private
|
|
77
|
+
# @return [::Hash, nil]
|
|
78
|
+
attr_accessor :query_options
|
|
79
|
+
|
|
80
|
+
# Creates a new Spanner Project instance.
|
|
81
|
+
# @param service [::Google::Cloud::Spanner::Service] The `Spanner::Service` ref.
|
|
82
|
+
# @param query_options [::Hash, nil] Optional. A hash of values to specify the custom
|
|
83
|
+
# query options for executing SQL query. Example option: `:optimizer_version`.
|
|
84
|
+
# @private
|
|
75
85
|
def initialize service, query_options: nil
|
|
76
86
|
@service = service
|
|
77
87
|
@query_options = query_options
|
|
@@ -80,6 +90,8 @@ module Google
|
|
|
80
90
|
##
|
|
81
91
|
# The identifier for the Cloud Spanner project.
|
|
82
92
|
#
|
|
93
|
+
# @return [::String]
|
|
94
|
+
#
|
|
83
95
|
# @example
|
|
84
96
|
# require "google/cloud"
|
|
85
97
|
#
|
|
@@ -40,19 +40,44 @@ module Google
|
|
|
40
40
|
# puts "Column #{name} is type #{type}"
|
|
41
41
|
# end
|
|
42
42
|
#
|
|
43
|
+
# results.rows.each do |row|
|
|
44
|
+
# puts "User #{row[:id]} is #{row[:name]}"
|
|
45
|
+
# end
|
|
46
|
+
#
|
|
43
47
|
class Results
|
|
44
|
-
|
|
45
|
-
#
|
|
46
|
-
#
|
|
48
|
+
# The `V1::ResultSetMetadata` protobuf object from the first
|
|
49
|
+
# PartialResultSet.
|
|
50
|
+
# @private
|
|
51
|
+
# @return [::Google::Cloud::Spanner::V1::ResultSetMetadata]
|
|
47
52
|
attr_reader :metadata
|
|
48
53
|
|
|
54
|
+
# Creates a new Results instance.
|
|
55
|
+
# @param service [::Google::Cloud::Spanner::Service] The `Spanner::Service` reference.
|
|
56
|
+
# @param partial_result_sets [::Enumerable<::Google::Cloud::Spanner::V1::PartialResultSet>]
|
|
57
|
+
# Raw enumerable from grpc `StreamingRead` call.
|
|
58
|
+
# @param session_name [::String] Required.
|
|
59
|
+
# The session in which the transaction to be committed is running.
|
|
60
|
+
# Values are of the form:
|
|
61
|
+
# `projects/<project_id>/instances/<instance_id>/databases/<database_id>/sessions/<session_id>`.
|
|
62
|
+
# @param metadata [::Google::Cloud::Spanner::V1::ResultSetMetadata] ParialResultSet metadata object
|
|
63
|
+
# @param stats [::Google::Cloud::Spanner::V1::ResultSetStats] Query plan and execution statistics
|
|
64
|
+
# for the statement that produced this streaming result set.
|
|
65
|
+
# @private
|
|
66
|
+
def initialize service, partial_result_sets, session_name, metadata, stats
|
|
67
|
+
@service = service
|
|
68
|
+
@partial_result_sets = partial_result_sets
|
|
69
|
+
@session_name = session_name
|
|
70
|
+
@metadata = metadata
|
|
71
|
+
@stats = stats
|
|
72
|
+
end
|
|
73
|
+
|
|
49
74
|
##
|
|
50
75
|
# The read timestamp chosen for single-use snapshots (read-only
|
|
51
76
|
# transactions).
|
|
52
77
|
# @return [Time] The chosen timestamp.
|
|
53
78
|
def timestamp
|
|
54
|
-
return nil if
|
|
55
|
-
Convert.timestamp_to_time
|
|
79
|
+
return nil if transaction.nil?
|
|
80
|
+
Convert.timestamp_to_time transaction.read_timestamp
|
|
56
81
|
end
|
|
57
82
|
|
|
58
83
|
##
|
|
@@ -78,9 +103,9 @@ module Google
|
|
|
78
103
|
@fields ||= Fields.from_grpc @metadata.row_type.fields
|
|
79
104
|
end
|
|
80
105
|
|
|
81
|
-
|
|
106
|
+
# Returns a transaction from the first ResultSet's metadata if available
|
|
82
107
|
# @private
|
|
83
|
-
#
|
|
108
|
+
# @return [::Google::Cloud::Spanner::V1::Transaction, nil]
|
|
84
109
|
def transaction
|
|
85
110
|
@metadata&.transaction
|
|
86
111
|
end
|
|
@@ -128,16 +153,18 @@ module Google
|
|
|
128
153
|
loop do
|
|
129
154
|
begin
|
|
130
155
|
if should_resume_request
|
|
131
|
-
@
|
|
156
|
+
@partial_result_sets = resume_request(resume_token)
|
|
132
157
|
buffered_responses = []
|
|
133
158
|
should_resume_request = false
|
|
134
159
|
elsif should_retry_request
|
|
135
|
-
@
|
|
160
|
+
@partial_result_sets = retry_request()
|
|
136
161
|
buffered_responses = []
|
|
137
162
|
should_retry_request = false
|
|
138
163
|
end
|
|
139
164
|
|
|
140
|
-
|
|
165
|
+
# @type [::Google::Cloud::Spanner::V1::PartialResultsSet]
|
|
166
|
+
grpc = @partial_result_sets.next
|
|
167
|
+
|
|
141
168
|
# metadata should be set before the first iteration...
|
|
142
169
|
@metadata ||= grpc.metadata
|
|
143
170
|
@stats ||= grpc.stats
|
|
@@ -243,13 +270,13 @@ module Google
|
|
|
243
270
|
def resume_request resume_token
|
|
244
271
|
if @execute_query_options
|
|
245
272
|
@service.execute_streaming_sql(
|
|
246
|
-
@
|
|
273
|
+
@session_name,
|
|
247
274
|
@sql,
|
|
248
275
|
**@execute_query_options.merge(resume_token: resume_token)
|
|
249
276
|
)
|
|
250
277
|
else
|
|
251
278
|
@service.streaming_read_table(
|
|
252
|
-
@
|
|
279
|
+
@session_name,
|
|
253
280
|
@table,
|
|
254
281
|
@columns,
|
|
255
282
|
**@read_options.merge(resume_token: resume_token)
|
|
@@ -262,9 +289,9 @@ module Google
|
|
|
262
289
|
# Retries a request, by re-executing it from scratch.
|
|
263
290
|
def retry_request
|
|
264
291
|
if @execute_query_options
|
|
265
|
-
@service.execute_streaming_sql @
|
|
292
|
+
@service.execute_streaming_sql @session_name, @sql, **@execute_query_options
|
|
266
293
|
else
|
|
267
|
-
@service.streaming_read_table @
|
|
294
|
+
@service.streaming_read_table @session_name, @table, @columns, **@read_options
|
|
268
295
|
end
|
|
269
296
|
end
|
|
270
297
|
|
|
@@ -295,35 +322,80 @@ module Google
|
|
|
295
322
|
@stats.row_count == :row_count_exact
|
|
296
323
|
end
|
|
297
324
|
|
|
325
|
+
# Creates a `Spanner::Results` for a given `PartialResultSet` grpc stream.
|
|
326
|
+
# @param partial_result_sets [::Enumerable<::Google::Cloud::Spanner::V1::PartialResultSet>]
|
|
327
|
+
# Raw enumerable from underlying grpc call.
|
|
328
|
+
# @param service [::Google::Cloud::Spanner::Service] The `Spanner::Service` reference.
|
|
329
|
+
# @param session_name [::String] Required.
|
|
330
|
+
# The session in which the transaction to be committed is running.
|
|
331
|
+
# Values are of the form:
|
|
332
|
+
# `projects/<project_id>/instances/<instance_id>/databases/<database_id>/sessions/<session_id>`.
|
|
298
333
|
# @private
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
end
|
|
334
|
+
# @return [::Google::Cloud::Spanner::Results]
|
|
335
|
+
def self.from_partial_result_sets partial_result_sets, service, session_name
|
|
336
|
+
# @type [::Google::Cloud::Spanner::V1::PartialResultSet]
|
|
337
|
+
partial_result_set = partial_result_sets.peek
|
|
338
|
+
metadata = partial_result_set.metadata
|
|
339
|
+
stats = partial_result_set.stats
|
|
340
|
+
new service, partial_result_sets, session_name, metadata, stats
|
|
307
341
|
rescue GRPC::BadStatus => e
|
|
308
342
|
raise Google::Cloud::Error.from_error(e)
|
|
309
343
|
end
|
|
310
344
|
|
|
345
|
+
# Creates a `Spanner::Results` wrapper from ExecuteStreamingSql call results and params.
|
|
346
|
+
# @param response [::Enumerable<::Google::Cloud::Spanner::V1::PartialResultSet>]
|
|
347
|
+
# Raw enumerable from grpc `ExecuteStreamingSql` call.
|
|
348
|
+
# @param service [::Google::Cloud::Spanner::Service] The `Spanner::Service` reference.
|
|
349
|
+
# @param session_name [::String] Required.
|
|
350
|
+
# The session in which the transaction to be committed is running.
|
|
351
|
+
# Values are of the form:
|
|
352
|
+
# `projects/<project_id>/instances/<instance_id>/databases/<database_id>/sessions/<session_id>`.
|
|
353
|
+
# @param sql [::String] The SQL query string that was executed.
|
|
354
|
+
# @param execute_query_options [::Hash] Full request options
|
|
355
|
+
# that were sent to the `service.execute_streaming_sql`. This hash joins params needed to
|
|
356
|
+
# construct `::Gapic::CallOptions`, e.g. `call_options` and header-related `route_to_leader`
|
|
357
|
+
# with params specific to `execute_streaming_sql`, such as `seqno`.
|
|
311
358
|
# @private
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
359
|
+
# @return [::Google::Cloud::Spanner::Results]
|
|
360
|
+
def self.from_execute_query_response response, service, session_name, sql, execute_query_options
|
|
361
|
+
from_partial_result_sets(response, service, session_name).tap do |results|
|
|
362
|
+
execute_query_options_copy = execute_query_options.dup
|
|
363
|
+
unless results.metadata.transaction.nil?
|
|
364
|
+
execute_query_options_copy[:transaction] = V1::TransactionSelector.new id: results.metadata.transaction.id
|
|
365
|
+
end
|
|
366
|
+
|
|
315
367
|
results.instance_variable_set :@sql, sql
|
|
316
|
-
results.instance_variable_set :@execute_query_options,
|
|
368
|
+
results.instance_variable_set :@execute_query_options, execute_query_options_copy
|
|
317
369
|
end
|
|
318
370
|
end
|
|
319
371
|
|
|
372
|
+
# Creates a `Spanner::Results` wrapper from StreamingRead call results and params.
|
|
373
|
+
# @param response [::Enumerable<::Google::Cloud::Spanner::V1::PartialResultSet>]
|
|
374
|
+
# Raw enumerable from grpc `StreamingRead` call.
|
|
375
|
+
# @param service [::Google::Cloud::Spanner::Service] The `Spanner::Service` reference.
|
|
376
|
+
# @param session_name [::String] Required.
|
|
377
|
+
# The session in which the transaction to be committed is running.
|
|
378
|
+
# Values are of the form:
|
|
379
|
+
# `projects/<project_id>/instances/<instance_id>/databases/<database_id>/sessions/<session_id>`.
|
|
380
|
+
# @param table [::String] The name of the table in the database that was read by `StreamingRead` request.
|
|
381
|
+
# @param columns [::Array<String, Symbol>] The columns of table that were returned
|
|
382
|
+
# by the `StreamingRead` request.
|
|
383
|
+
# @param read_options [::Hash] Full request options
|
|
384
|
+
# that were sent to the `service.streaming_read_table`. This hash joins params needed to
|
|
385
|
+
# construct `::Gapic::CallOptions`, e.g. `call_options` and header-related `route_to_leader`
|
|
386
|
+
# with params specific to `streaming_read_table`, such as `keys`.
|
|
320
387
|
# @private
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
388
|
+
# @return [::Google::Cloud::Spanner::Results]
|
|
389
|
+
def self.from_read_response response, service, session_name, table, columns, read_options
|
|
390
|
+
from_partial_result_sets(response, service, session_name).tap do |results|
|
|
391
|
+
read_options_copy = read_options.dup
|
|
392
|
+
unless results.metadata.transaction.nil?
|
|
393
|
+
read_options_copy[:transaction] = V1::TransactionSelector.new id: results.metadata.transaction.id
|
|
394
|
+
end
|
|
395
|
+
|
|
324
396
|
results.instance_variable_set :@table, table
|
|
325
397
|
results.instance_variable_set :@columns, columns
|
|
326
|
-
results.instance_variable_set :@read_options,
|
|
398
|
+
results.instance_variable_set :@read_options, read_options_copy
|
|
327
399
|
end
|
|
328
400
|
end
|
|
329
401
|
|
|
@@ -43,8 +43,18 @@ module Google
|
|
|
43
43
|
RST_STREAM_INTERNAL_ERROR = "Received RST_STREAM".freeze
|
|
44
44
|
EOS_INTERNAL_ERROR = "Received unexpected EOS on DATA frame from server".freeze
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
#
|
|
46
|
+
# Creates a new `Spanner::Service` instance.
|
|
47
|
+
# @param project [::String] The project id to use
|
|
48
|
+
# @param credentials [::Symbol, ::Google::Auth::Credentials] Credentials
|
|
49
|
+
# @param quota_project [::String, nil] Optional. The quota project id to use
|
|
50
|
+
# @param host [::String, nil] Optional. The endpoint override.
|
|
51
|
+
# @param timeout [::Numeric, nil] Optional. Timeout for Gapic client.
|
|
52
|
+
# @param lib_name [::String, nil] Optional. Library name for headers.
|
|
53
|
+
# @param lib_version [::String, nil] Optional. Library version for headers.
|
|
54
|
+
# @param enable_leader_aware_routing [::Boolean, nil] Optional. Whether Leader
|
|
55
|
+
# Aware Routing should be enabled.
|
|
56
|
+
# @param universe_domain [::String, nil] Optional. The domain of the universe to connect to.
|
|
57
|
+
# @private
|
|
48
58
|
def initialize project, credentials, quota_project: nil,
|
|
49
59
|
host: nil, timeout: nil, lib_name: nil, lib_version: nil,
|
|
50
60
|
enable_leader_aware_routing: nil, universe_domain: nil
|
|
@@ -82,6 +92,8 @@ module Google
|
|
|
82
92
|
GRPC::Core::CallCredentials.new credentials.client.updater_proc
|
|
83
93
|
end
|
|
84
94
|
|
|
95
|
+
# `V1::Spanner::Client` or a mock.
|
|
96
|
+
# @return [::Google::Cloud::Spanner::V1::Spanner::Client]
|
|
85
97
|
def service
|
|
86
98
|
return mocked_service if mocked_service
|
|
87
99
|
@service ||=
|
|
@@ -145,6 +157,11 @@ module Google
|
|
|
145
157
|
paged_enum.response
|
|
146
158
|
end
|
|
147
159
|
|
|
160
|
+
# Gets information about a particular instance
|
|
161
|
+
# @param name [::String] The name of the Spanner instance, e.g. 'myinstance'
|
|
162
|
+
# or path to the Spanner instance, e.g. `projects/myproject/instances/myinstance`.
|
|
163
|
+
# @private
|
|
164
|
+
# @return [::Google::Cloud::Spanner::Admin::Instance::V1::Instance]
|
|
148
165
|
def get_instance name, call_options: nil
|
|
149
166
|
opts = default_options call_options: call_options
|
|
150
167
|
request = { name: instance_path(name) }
|
|
@@ -329,13 +346,41 @@ module Google
|
|
|
329
346
|
service.get_session({ name: session_name }, opts)
|
|
330
347
|
end
|
|
331
348
|
|
|
349
|
+
# Creates a new Spanner session.
|
|
350
|
+
# This creates a `V1::Session` protobuf object not wrapped in `Spanner::Session`.
|
|
351
|
+
#
|
|
352
|
+
# @param database_name [::String] The full name of the database.
|
|
353
|
+
# @param labels [::Hash, nil] Optional. The labels to be applied to all sessions
|
|
354
|
+
# created by the client. Example: `"team" => "billing-service"`.
|
|
355
|
+
# @param call_options [::Hash, nil] Optional. A hash of values to specify the custom
|
|
356
|
+
# call options. Example option `:timeout`.
|
|
357
|
+
# @param database_role [::String, nil] Optional. The Spanner session creator role.
|
|
358
|
+
# Example: `analyst`.
|
|
359
|
+
# @param multiplexed [::Boolean] Optional. Default to `false`.
|
|
360
|
+
# If `true`, specifies a multiplexed session.
|
|
361
|
+
# @return [::Google::Cloud::Spanner::V1::Session]
|
|
362
|
+
# @private
|
|
332
363
|
def create_session database_name, labels: nil,
|
|
333
|
-
call_options: nil, database_role: nil
|
|
364
|
+
call_options: nil, database_role: nil,
|
|
365
|
+
multiplexed: false
|
|
334
366
|
route_to_leader = LARHeaders.create_session
|
|
335
|
-
opts = default_options
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
367
|
+
opts = default_options(
|
|
368
|
+
session_name: database_name,
|
|
369
|
+
call_options: call_options,
|
|
370
|
+
route_to_leader: route_to_leader
|
|
371
|
+
)
|
|
372
|
+
|
|
373
|
+
# check if we need a session object in request or server defaults would work.
|
|
374
|
+
params_diff_from_default = !(labels.nil? && database_role.nil? && !multiplexed)
|
|
375
|
+
|
|
376
|
+
if params_diff_from_default
|
|
377
|
+
session = V1::Session.new(
|
|
378
|
+
labels: labels,
|
|
379
|
+
creator_role: database_role,
|
|
380
|
+
multiplexed: multiplexed
|
|
381
|
+
)
|
|
382
|
+
end
|
|
383
|
+
|
|
339
384
|
service.create_session(
|
|
340
385
|
{ database: database_name, session: session }, opts
|
|
341
386
|
)
|
|
@@ -414,7 +459,7 @@ module Google
|
|
|
414
459
|
resume_token: nil, partition_token: nil,
|
|
415
460
|
request_options: nil, call_options: nil,
|
|
416
461
|
data_boost_enabled: nil, directed_read_options: nil,
|
|
417
|
-
route_to_leader: nil
|
|
462
|
+
route_to_leader: nil, order_by: nil, lock_hint: nil
|
|
418
463
|
opts = default_options session_name: session_name,
|
|
419
464
|
call_options: call_options,
|
|
420
465
|
route_to_leader: route_to_leader
|
|
@@ -422,7 +467,8 @@ module Google
|
|
|
422
467
|
session: session_name, table: table_name, columns: columns,
|
|
423
468
|
key_set: keys, transaction: transaction, index: index,
|
|
424
469
|
limit: limit, resume_token: resume_token,
|
|
425
|
-
partition_token: partition_token, request_options: request_options
|
|
470
|
+
partition_token: partition_token, request_options: request_options,
|
|
471
|
+
order_by: order_by, lock_hint: lock_hint
|
|
426
472
|
}
|
|
427
473
|
request[:data_boost_enabled] = data_boost_enabled unless data_boost_enabled.nil?
|
|
428
474
|
request[:directed_read_options] = directed_read_options unless directed_read_options.nil?
|
|
@@ -463,6 +509,29 @@ module Google
|
|
|
463
509
|
service.partition_query request, opts
|
|
464
510
|
end
|
|
465
511
|
|
|
512
|
+
# Commits a transaction. Can be a predefined (`transaction_id`) transaction
|
|
513
|
+
# or a single-use created for this request. The request includes the mutations to be
|
|
514
|
+
# applied to rows in the database.
|
|
515
|
+
#
|
|
516
|
+
# @param session_name [::String]
|
|
517
|
+
# Required. The session in which the transaction to be committed is running.
|
|
518
|
+
# @param mutations [::Array<::Google::Cloud::Spanner::V1::Mutation>] Optional.
|
|
519
|
+
# The mutations to be executed when this transaction commits. All
|
|
520
|
+
# mutations are applied atomically, in the order they appear in
|
|
521
|
+
# this list. Defaults to an empty array.
|
|
522
|
+
# @param transaction_id [::String, nil] Optional.
|
|
523
|
+
# Commit a previously-started transaction. If nil, a new single-use transation will be used.
|
|
524
|
+
# @param exclude_txn_from_change_streams [::Boolean] Optional. Defaults to `false`.
|
|
525
|
+
# When `exclude_txn_from_change_streams` is set to `true`, it prevents read
|
|
526
|
+
# or write transactions from being tracked in change streams.
|
|
527
|
+
# @param commit_options [::Hash, nil] Optional. A hash of commit options.
|
|
528
|
+
# Example option: `:return_commit_stats`.
|
|
529
|
+
# @param request_options [::Hash, nil] Optional. Common request options.
|
|
530
|
+
# Example option: `:priority`.
|
|
531
|
+
# @param call_options [::Hash, nil] Optional. A hash of values to specify the custom
|
|
532
|
+
# call options. Example option `:timeout`.
|
|
533
|
+
# @private
|
|
534
|
+
# @return [::Google::Cloud::Spanner::V1::CommitResponse]
|
|
466
535
|
def commit session_name, mutations = [],
|
|
467
536
|
transaction_id: nil, exclude_txn_from_change_streams: false,
|
|
468
537
|
commit_options: nil, request_options: nil, call_options: nil
|
|
@@ -484,10 +553,16 @@ module Google
|
|
|
484
553
|
}
|
|
485
554
|
|
|
486
555
|
request = add_commit_options request, commit_options
|
|
487
|
-
|
|
556
|
+
# request is a hash equivalent of `::Google::Cloud::Spanner::V1::CommitRequest`
|
|
488
557
|
service.commit request, opts
|
|
489
558
|
end
|
|
490
559
|
|
|
560
|
+
# Merges commit options hash to a hash representing a `V1::CommitRequest`.
|
|
561
|
+
# @param request [::Hash] A `::Google::Cloud::Spanner::V1::CommitRequest` in a hash form.
|
|
562
|
+
# @param commit_options [::Hash, nil] Optional. A hash of commit options.
|
|
563
|
+
# Example option: `:return_commit_stats`.
|
|
564
|
+
# @return [::Hash] An enriched `::Google::Cloud::Spanner::V1::CommitRequest` in a hash form.
|
|
565
|
+
# @private
|
|
491
566
|
def add_commit_options request, commit_options
|
|
492
567
|
if commit_options
|
|
493
568
|
if commit_options.key? :return_commit_stats
|
|
@@ -512,6 +587,38 @@ module Google
|
|
|
512
587
|
service.rollback request, opts
|
|
513
588
|
end
|
|
514
589
|
|
|
590
|
+
# Explicitly begins a new transaction, making a `BeginTransaction` rpc call,
|
|
591
|
+
# and creating and returning a `V1::Transaction` object.
|
|
592
|
+
#
|
|
593
|
+
# Explicit transaction creation can often be skipped:
|
|
594
|
+
# {::Google::Cloud::Spanner::V1::Spanner::Client#read Read},
|
|
595
|
+
# {::Google::Cloud::Spanner::V1::Spanner::Client#execute_sql ExecuteSql} and
|
|
596
|
+
# {::Google::Cloud::Spanner::V1::Spanner::Client#execute_batch_dml ExecuteBatchDml}
|
|
597
|
+
# can begin a new transaction as part of the request (so-called inline-begin).
|
|
598
|
+
# The inline-begin functionality is used in methods on `Spanner::Transaction` class,
|
|
599
|
+
# e.g. `Spanner::Transaction#read`, accessible to the end-users via the `Spanner::Client#transaction` method.
|
|
600
|
+
#
|
|
601
|
+
# All the above methods, and {::Google::Cloud::Spanner::V1::Spanner::Client#commit Commit}
|
|
602
|
+
# can utilize single-use transactions that do not require an explicit BeginTransaction call.
|
|
603
|
+
# Single-use transactions are used by the methods on `Spanner::Client` class,
|
|
604
|
+
# e.g. `Spanner::Client#read`, with the exception of `Spanner::Client#transaction`.
|
|
605
|
+
#
|
|
606
|
+
# @param session_name [::String]
|
|
607
|
+
# Required. The session in which the transaction is to be created.
|
|
608
|
+
# Values are of the form:
|
|
609
|
+
# `projects/<project_id>/instances/<instance_id>/databases/<database_id>/sessions/<session_id>`.
|
|
610
|
+
# @param exclude_txn_from_change_streams [::Boolean] Optional. Defaults to `false`.
|
|
611
|
+
# When `exclude_txn_from_change_streams` is set to `true`, it prevents read
|
|
612
|
+
# or write transactions from being tracked in change streams.
|
|
613
|
+
# @param request_options [::Hash, nil] Optional. Common request options.
|
|
614
|
+
# Example option: `:priority`.
|
|
615
|
+
# @param call_options [::Hash, nil] Optional. A hash of values to specify the custom
|
|
616
|
+
# call options. Example option `:timeout`.
|
|
617
|
+
# @param route_to_leader [::String, nil] Optional. The value to be sent
|
|
618
|
+
# as `x-goog-spanner-route-to-leader` header for leader aware routing.
|
|
619
|
+
# Expected values: `"true"` or `"false"`.
|
|
620
|
+
# @private
|
|
621
|
+
# @return [::Google::Cloud::Spanner::V1::Transaction]
|
|
515
622
|
def begin_transaction session_name,
|
|
516
623
|
exclude_txn_from_change_streams: false,
|
|
517
624
|
request_options: nil,
|
|
@@ -647,6 +754,25 @@ module Google
|
|
|
647
754
|
databases.list_database_operations request, opts
|
|
648
755
|
end
|
|
649
756
|
|
|
757
|
+
# Lists the backup `::Google::Longrunning::Operation` long-running operations in
|
|
758
|
+
# the given instance. A backup operation has a name of the form
|
|
759
|
+
# projects/<project>/instances/<instance>/backups/<backup>/operations/<operation>.
|
|
760
|
+
# @param instance_id [::String] The name of the Spanner instance, e.g. 'myinstance'
|
|
761
|
+
# or path to the Spanner instance, e.g. `projects/myproject/instances/myinstance`.
|
|
762
|
+
# @param filter [::String, nil] Optional.
|
|
763
|
+
# An expression that filters the list of returned backup operations.
|
|
764
|
+
# Example filter: `done:true`.
|
|
765
|
+
# @param page_size [::Integer, nil] Optional.
|
|
766
|
+
# Number of operations to be returned in the response. If 0 or
|
|
767
|
+
# less, defaults to the server's maximum allowed page size.
|
|
768
|
+
# @param page_token [::String, nil] Optional.
|
|
769
|
+
# If set, `page_token` should contain a value received as a `next_page_token`
|
|
770
|
+
# from a previous `ListBackupOperationsResponse` to the same `parent`
|
|
771
|
+
# and with the same `filter`.
|
|
772
|
+
# @param call_options [::Hash, nil] Optional. A hash of values to specify the custom
|
|
773
|
+
# call options. Example option `:timeout`.
|
|
774
|
+
# @private
|
|
775
|
+
# @return [::Gapic::PagedEnumerable<::Gapic::Operation>]
|
|
650
776
|
def list_backup_operations instance_id,
|
|
651
777
|
filter: nil, page_size: nil,
|
|
652
778
|
page_token: nil,
|
|
@@ -736,6 +862,12 @@ module Google
|
|
|
736
862
|
project: project
|
|
737
863
|
end
|
|
738
864
|
|
|
865
|
+
# Converts an instance name to instance path.
|
|
866
|
+
# If an instance path is given, returns it unchanged
|
|
867
|
+
# @param name [::String] name of the Spanner instance, e.g. 'myinstance'
|
|
868
|
+
# or path to the Spanner instance, e.g. `projects/myproject/instances/myinstance`.
|
|
869
|
+
# @private
|
|
870
|
+
# @return [::String]
|
|
739
871
|
def instance_path name
|
|
740
872
|
return name if name.to_s.include? "/"
|
|
741
873
|
|
|
@@ -43,19 +43,28 @@ module Google
|
|
|
43
43
|
# no operations are sent for more than an hour.
|
|
44
44
|
#
|
|
45
45
|
class Session
|
|
46
|
-
|
|
47
|
-
# @
|
|
46
|
+
# The wrapped `V1::Session` protobuf session object.
|
|
47
|
+
# @return [::Google::Cloud::Spanner::V1::Session]
|
|
48
|
+
# @private
|
|
48
49
|
attr_accessor :grpc
|
|
49
50
|
|
|
50
|
-
|
|
51
|
-
# @private
|
|
51
|
+
# The `Spanner::Service` object.
|
|
52
|
+
# @private
|
|
53
|
+
# @return [::Google::Cloud::Spanner::Service]
|
|
52
54
|
attr_accessor :service
|
|
53
55
|
|
|
54
|
-
|
|
55
|
-
#
|
|
56
|
+
# A hash of values to specify the custom query options for executing SQL query.
|
|
57
|
+
# Example option: `:optimizer_version`.
|
|
58
|
+
# @private
|
|
59
|
+
# @return [::Hash, nil]
|
|
56
60
|
attr_accessor :query_options
|
|
57
61
|
|
|
58
|
-
#
|
|
62
|
+
# Creates a new Session instance.
|
|
63
|
+
# @param grpc [::Google::Cloud::Spanner::V1::Session] Underlying `V1::Session` object.
|
|
64
|
+
# @param service [::Google::Cloud::Spanner::Service] A `Spanner::Service` object.
|
|
65
|
+
# @param query_options [::Hash, nil] Optional. A hash of values to specify the custom
|
|
66
|
+
# query options for executing SQL query. Example option: `:optimizer_version`.
|
|
67
|
+
# @private
|
|
59
68
|
def initialize grpc, service, query_options: nil
|
|
60
69
|
@grpc = grpc
|
|
61
70
|
@service = service
|
|
@@ -63,33 +72,38 @@ module Google
|
|
|
63
72
|
end
|
|
64
73
|
|
|
65
74
|
# The unique identifier for the project.
|
|
66
|
-
# @
|
|
75
|
+
# @private
|
|
76
|
+
# @return [::String]
|
|
67
77
|
def project_id
|
|
68
78
|
@grpc.name.split("/")[1]
|
|
69
79
|
end
|
|
70
80
|
|
|
71
81
|
# The unique identifier for the instance.
|
|
72
|
-
# @
|
|
82
|
+
# @private
|
|
83
|
+
# @return [::String]
|
|
73
84
|
def instance_id
|
|
74
85
|
@grpc.name.split("/")[3]
|
|
75
86
|
end
|
|
76
87
|
|
|
77
88
|
# The unique identifier for the database.
|
|
78
|
-
# @
|
|
89
|
+
# @private
|
|
90
|
+
# @return [::String]
|
|
79
91
|
def database_id
|
|
80
92
|
@grpc.name.split("/")[5]
|
|
81
93
|
end
|
|
82
94
|
|
|
83
95
|
# The unique identifier for the session.
|
|
84
|
-
# @
|
|
96
|
+
# @private
|
|
97
|
+
# @return [::String]
|
|
85
98
|
def session_id
|
|
86
99
|
@grpc.name.split("/")[7]
|
|
87
100
|
end
|
|
88
101
|
|
|
89
|
-
|
|
90
|
-
#
|
|
102
|
+
# Full session name.
|
|
103
|
+
# Values are of the form:
|
|
91
104
|
# `projects/<project_id>/instances/<instance_id>/databases/<database_id>/sessions/<session_id>`.
|
|
92
|
-
# @
|
|
105
|
+
# @private
|
|
106
|
+
# @return [::String]
|
|
93
107
|
def path
|
|
94
108
|
@grpc.name
|
|
95
109
|
end
|
|
@@ -360,7 +374,7 @@ module Google
|
|
|
360
374
|
response = service.execute_streaming_sql path, sql, **execute_query_options
|
|
361
375
|
|
|
362
376
|
results = Results.from_execute_query_response response, service, path, sql, execute_query_options
|
|
363
|
-
@last_updated_at =
|
|
377
|
+
@last_updated_at = Process.clock_gettime Process::CLOCK_MONOTONIC
|
|
364
378
|
results
|
|
365
379
|
end
|
|
366
380
|
|
|
@@ -430,7 +444,7 @@ module Google
|
|
|
430
444
|
batch.statements, seqno,
|
|
431
445
|
request_options: request_options,
|
|
432
446
|
call_options: call_options
|
|
433
|
-
@last_updated_at =
|
|
447
|
+
@last_updated_at = Process.clock_gettime Process::CLOCK_MONOTONIC
|
|
434
448
|
results
|
|
435
449
|
end
|
|
436
450
|
|
|
@@ -483,6 +497,14 @@ module Google
|
|
|
483
497
|
# * `:multiplier` (`Numeric`) - The incremental backoff multiplier.
|
|
484
498
|
# * `:retry_codes` (`Array<String>`) - The error codes that should
|
|
485
499
|
# trigger a retry.
|
|
500
|
+
# @param [::Google::Cloud::Spanner::V1::ReadRequest::OrderBy] order_by An option to control the order in which
|
|
501
|
+
# rows are returned from a read.
|
|
502
|
+
# To see the available options refer to
|
|
503
|
+
# ['Google::Cloud::Spanner::V1::ReadRequest::OrderBy'](https://cloud.google.com/ruby/docs/reference/google-cloud-spanner-v1/latest/Google-Cloud-Spanner-V1-ReadRequest-OrderBy)
|
|
504
|
+
# @param [::Google::Cloud::Spanner::V1::ReadRequest::LockHint] lock_hint A lock hint mechanism for reads done
|
|
505
|
+
# within a transaction.
|
|
506
|
+
# To see the available options refer to
|
|
507
|
+
# ['Google::Cloud::Spanner::V1::ReadRequest::LockHint'](https://cloud.google.com/ruby/docs/reference/google-cloud-spanner-v1/latest/Google-Cloud-Spanner-V1-ReadRequest-LockHint)
|
|
486
508
|
#
|
|
487
509
|
# @return [Google::Cloud::Spanner::Results] The results of the read
|
|
488
510
|
# operation.
|
|
@@ -503,7 +525,7 @@ module Google
|
|
|
503
525
|
def read table, columns, keys: nil, index: nil, limit: nil,
|
|
504
526
|
transaction: nil, partition_token: nil, request_options: nil,
|
|
505
527
|
call_options: nil, data_boost_enabled: nil, directed_read_options: nil,
|
|
506
|
-
route_to_leader: nil
|
|
528
|
+
route_to_leader: nil, order_by: nil, lock_hint: nil
|
|
507
529
|
ensure_service!
|
|
508
530
|
|
|
509
531
|
read_options = {
|
|
@@ -512,7 +534,9 @@ module Google
|
|
|
512
534
|
partition_token: partition_token,
|
|
513
535
|
request_options: request_options,
|
|
514
536
|
call_options: call_options,
|
|
515
|
-
route_to_leader: route_to_leader
|
|
537
|
+
route_to_leader: route_to_leader,
|
|
538
|
+
order_by: order_by,
|
|
539
|
+
lock_hint: lock_hint
|
|
516
540
|
}
|
|
517
541
|
read_options[:data_boost_enabled] = data_boost_enabled unless data_boost_enabled.nil?
|
|
518
542
|
read_options[:directed_read_options] = directed_read_options unless directed_read_options.nil?
|
|
@@ -522,7 +546,7 @@ module Google
|
|
|
522
546
|
|
|
523
547
|
results = Results.from_read_response response, service, path, table, columns, read_options
|
|
524
548
|
|
|
525
|
-
@last_updated_at =
|
|
549
|
+
@last_updated_at = Process.clock_gettime Process::CLOCK_MONOTONIC
|
|
526
550
|
|
|
527
551
|
results
|
|
528
552
|
end
|
|
@@ -538,7 +562,7 @@ module Google
|
|
|
538
562
|
max_partitions: max_partitions,
|
|
539
563
|
call_options: call_options
|
|
540
564
|
|
|
541
|
-
@last_updated_at =
|
|
565
|
+
@last_updated_at = Process.clock_gettime Process::CLOCK_MONOTONIC
|
|
542
566
|
|
|
543
567
|
results
|
|
544
568
|
end
|
|
@@ -555,7 +579,7 @@ module Google
|
|
|
555
579
|
max_partitions: max_partitions,
|
|
556
580
|
call_options: call_options
|
|
557
581
|
|
|
558
|
-
@last_updated_at =
|
|
582
|
+
@last_updated_at = Process.clock_gettime Process::CLOCK_MONOTONIC
|
|
559
583
|
|
|
560
584
|
results
|
|
561
585
|
end
|
|
@@ -657,7 +681,7 @@ module Google
|
|
|
657
681
|
commit_options: commit_options,
|
|
658
682
|
request_options: request_options,
|
|
659
683
|
call_options: call_options
|
|
660
|
-
@last_updated_at =
|
|
684
|
+
@last_updated_at = Process.clock_gettime Process::CLOCK_MONOTONIC
|
|
661
685
|
resp = CommitResponse.from_grpc commit_resp
|
|
662
686
|
commit_options ? resp : resp.timestamp
|
|
663
687
|
end
|
|
@@ -755,7 +779,7 @@ module Google
|
|
|
755
779
|
request_options: request_options,
|
|
756
780
|
call_options: call_options
|
|
757
781
|
results = BatchWriteResults.new response
|
|
758
|
-
@last_updated_at =
|
|
782
|
+
@last_updated_at = Process.clock_gettime Process::CLOCK_MONOTONIC
|
|
759
783
|
results
|
|
760
784
|
end
|
|
761
785
|
|
|
@@ -1341,7 +1365,7 @@ module Google
|
|
|
1341
1365
|
# Rolls back the transaction, releasing any locks it holds.
|
|
1342
1366
|
def rollback transaction_id
|
|
1343
1367
|
service.rollback path, transaction_id
|
|
1344
|
-
@last_updated_at =
|
|
1368
|
+
@last_updated_at = Process.clock_gettime Process::CLOCK_MONOTONIC
|
|
1345
1369
|
true
|
|
1346
1370
|
end
|
|
1347
1371
|
|
|
@@ -1370,7 +1394,7 @@ module Google
|
|
|
1370
1394
|
def reload!
|
|
1371
1395
|
ensure_service!
|
|
1372
1396
|
@grpc = service.get_session path
|
|
1373
|
-
@last_updated_at =
|
|
1397
|
+
@last_updated_at = Process.clock_gettime Process::CLOCK_MONOTONIC
|
|
1374
1398
|
self
|
|
1375
1399
|
rescue Google::Cloud::NotFoundError
|
|
1376
1400
|
labels = @grpc.labels.to_h unless @grpc.labels.to_h.empty?
|
|
@@ -1379,7 +1403,7 @@ module Google
|
|
|
1379
1403
|
project: project_id, instance: instance_id, database: database_id
|
|
1380
1404
|
),
|
|
1381
1405
|
labels: labels
|
|
1382
|
-
@last_updated_at =
|
|
1406
|
+
@last_updated_at = Process.clock_gettime Process::CLOCK_MONOTONIC
|
|
1383
1407
|
self
|
|
1384
1408
|
end
|
|
1385
1409
|
|
|
@@ -1408,18 +1432,23 @@ module Google
|
|
|
1408
1432
|
service.delete_session path
|
|
1409
1433
|
end
|
|
1410
1434
|
|
|
1411
|
-
##
|
|
1412
|
-
# @private
|
|
1413
1435
|
# Determines if the session has been idle longer than the given
|
|
1414
1436
|
# duration.
|
|
1415
|
-
|
|
1437
|
+
# @param duration_sec [::Numeric] interval in seconds
|
|
1438
|
+
# @private
|
|
1439
|
+
# @return [::Boolean]
|
|
1440
|
+
def idle_since? duration_sec
|
|
1416
1441
|
return true if @last_updated_at.nil?
|
|
1417
|
-
|
|
1442
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC) > @last_updated_at + duration_sec
|
|
1418
1443
|
end
|
|
1419
1444
|
|
|
1420
|
-
|
|
1421
|
-
# @
|
|
1422
|
-
#
|
|
1445
|
+
# Creates a new Session instance from a `V1::Session`.
|
|
1446
|
+
# @param grpc [::Google::Cloud::Spanner::V1::Session] Underlying `V1::Session` object.
|
|
1447
|
+
# @param service [::Google::Cloud::Spanner::Service] A `Spanner::Service` ref.
|
|
1448
|
+
# @param query_options [::Hash, nil] Optional. A hash of values to specify the custom
|
|
1449
|
+
# query options for executing SQL query. Example option: `:optimizer_version`.
|
|
1450
|
+
# @private
|
|
1451
|
+
# @return [::Google::Cloud::Spanner::Session]
|
|
1423
1452
|
def self.from_grpc grpc, service, query_options: nil
|
|
1424
1453
|
new grpc, service, query_options: query_options
|
|
1425
1454
|
end
|
|
@@ -1439,6 +1468,11 @@ module Google
|
|
|
1439
1468
|
raise "Must have active connection to service" unless service
|
|
1440
1469
|
end
|
|
1441
1470
|
|
|
1471
|
+
# Merge two hashes
|
|
1472
|
+
# @param hash [::Hash, nil]
|
|
1473
|
+
# @param hash_to_merge [::Hash, nil]
|
|
1474
|
+
# @private
|
|
1475
|
+
# @return [::Hash, nil]
|
|
1442
1476
|
def merge_if_present hash, hash_to_merge
|
|
1443
1477
|
if hash.nil?
|
|
1444
1478
|
hash_to_merge
|
|
@@ -76,19 +76,40 @@ module Google
|
|
|
76
76
|
# end
|
|
77
77
|
#
|
|
78
78
|
class Transaction
|
|
79
|
-
#
|
|
79
|
+
# The underlying `V1::Transaction` protobuf object.
|
|
80
|
+
# @private
|
|
81
|
+
# @return [::Google::Cloud::Spanner::V1::Transaction]
|
|
80
82
|
attr_reader :grpc
|
|
81
83
|
|
|
82
|
-
#
|
|
84
|
+
# The `Spanner::Session` session for this transaction.
|
|
85
|
+
# @private
|
|
86
|
+
# @return [::Google::Cloud::Spanner::Session]
|
|
83
87
|
attr_accessor :session
|
|
84
88
|
|
|
85
|
-
#
|
|
89
|
+
# Transaction tag for statistics collection.
|
|
90
|
+
# Example: `"update_user_profile"`.
|
|
91
|
+
# @private
|
|
92
|
+
# @return [::String, nil]
|
|
86
93
|
attr_accessor :transaction_tag
|
|
87
94
|
|
|
88
|
-
#
|
|
95
|
+
# Whether to exclude this transaction from change streams.
|
|
96
|
+
# @private
|
|
97
|
+
# @return [::Boolean]
|
|
89
98
|
attr_accessor :exclude_txn_from_change_streams
|
|
90
99
|
|
|
91
|
-
|
|
100
|
+
# Creates a new `Spanner::Transaction` instance from a `V1::Transaction` object.
|
|
101
|
+
# @param grpc [::Google::Cloud::Spanner::V1::Transaction] Underlying `V1::Transaction` object.
|
|
102
|
+
# @param session [::Google::Cloud::Spanner::Session] The session this transaction is running in.
|
|
103
|
+
# @param exclude_txn_from_change_streams [::Boolean]
|
|
104
|
+
# When `exclude_txn_from_change_streams` is set to `true`, it prevents read
|
|
105
|
+
# or write transactions from being tracked in change streams.
|
|
106
|
+
# @private
|
|
107
|
+
# @return [::Google::Cloud::Spanner::Transaction]
|
|
108
|
+
def initialize grpc, session, exclude_txn_from_change_streams
|
|
109
|
+
@grpc = grpc
|
|
110
|
+
@session = session
|
|
111
|
+
@exclude_txn_from_change_streams = exclude_txn_from_change_streams
|
|
112
|
+
|
|
92
113
|
@commit = Commit.new
|
|
93
114
|
@seqno = 0
|
|
94
115
|
@exclude_txn_from_change_streams = false
|
|
@@ -116,7 +137,7 @@ module Google
|
|
|
116
137
|
# @return [String] The transaction id.
|
|
117
138
|
def transaction_id
|
|
118
139
|
return @grpc.id if existing_transaction?
|
|
119
|
-
safe_begin_transaction
|
|
140
|
+
safe_begin_transaction!
|
|
120
141
|
@grpc.id
|
|
121
142
|
end
|
|
122
143
|
|
|
@@ -1153,15 +1174,16 @@ module Google
|
|
|
1153
1174
|
@commit.mutations
|
|
1154
1175
|
end
|
|
1155
1176
|
|
|
1156
|
-
|
|
1157
|
-
# @
|
|
1158
|
-
#
|
|
1177
|
+
# Creates a new `Spanner::Transaction` instance from a `V1::Transaction` object.
|
|
1178
|
+
# @param grpc [::Google::Cloud::Spanner::V1::Transaction] Underlying `V1::Transaction` object.
|
|
1179
|
+
# @param session [::Google::Cloud::Spanner::Session] The session this transaction is running in.
|
|
1180
|
+
# @param exclude_txn_from_change_streams [::Boolean] Optional. Defaults to `false`.
|
|
1181
|
+
# When `exclude_txn_from_change_streams` is set to `true`, it prevents read
|
|
1182
|
+
# or write transactions from being tracked in change streams.
|
|
1183
|
+
# @private
|
|
1184
|
+
# @return [::Google::Cloud::Spanner::Transaction]
|
|
1159
1185
|
def self.from_grpc grpc, session, exclude_txn_from_change_streams: false
|
|
1160
|
-
new
|
|
1161
|
-
s.instance_variable_set :@grpc, grpc
|
|
1162
|
-
s.instance_variable_set :@session, session
|
|
1163
|
-
s.exclude_txn_from_change_streams = exclude_txn_from_change_streams
|
|
1164
|
-
end
|
|
1186
|
+
new grpc, session, exclude_txn_from_change_streams
|
|
1165
1187
|
end
|
|
1166
1188
|
|
|
1167
1189
|
##
|
|
@@ -1176,6 +1198,33 @@ module Google
|
|
|
1176
1198
|
@grpc.nil?
|
|
1177
1199
|
end
|
|
1178
1200
|
|
|
1201
|
+
# Begins a new transaction in a thread-safe manner if one does not already exist.
|
|
1202
|
+
#
|
|
1203
|
+
# @param exclude_from_change_streams [::Boolean] Optional. Defaults to `false`.
|
|
1204
|
+
# When `exclude_from_change_streams` is set to `true`, it prevents read
|
|
1205
|
+
# or write transactions from being tracked in change streams.
|
|
1206
|
+
# @param request_options [::Hash, nil] Optional. Common request options.
|
|
1207
|
+
# Example option: `:priority`.
|
|
1208
|
+
# @param call_options [::Hash, nil] Optional. A hash of values to specify the custom
|
|
1209
|
+
# call options. Example option `:timeout`.
|
|
1210
|
+
# @private
|
|
1211
|
+
# @return [::Google::Cloud::Spanner::V1::Transaction, nil] The new transaction
|
|
1212
|
+
# object, or `nil` if a transaction already exists.
|
|
1213
|
+
def safe_begin_transaction! exclude_from_change_streams: false, request_options: nil, call_options: nil
|
|
1214
|
+
@mutex.synchronize do
|
|
1215
|
+
return if existing_transaction?
|
|
1216
|
+
ensure_session!
|
|
1217
|
+
route_to_leader = LARHeaders.begin_transaction true
|
|
1218
|
+
@grpc = service.begin_transaction(
|
|
1219
|
+
session.path,
|
|
1220
|
+
exclude_txn_from_change_streams: exclude_from_change_streams,
|
|
1221
|
+
request_options: request_options,
|
|
1222
|
+
call_options: call_options,
|
|
1223
|
+
route_to_leader: route_to_leader
|
|
1224
|
+
)
|
|
1225
|
+
end
|
|
1226
|
+
end
|
|
1227
|
+
|
|
1179
1228
|
protected
|
|
1180
1229
|
|
|
1181
1230
|
##
|
|
@@ -1203,24 +1252,18 @@ module Google
|
|
|
1203
1252
|
end
|
|
1204
1253
|
end
|
|
1205
1254
|
|
|
1206
|
-
|
|
1207
|
-
#
|
|
1208
|
-
|
|
1209
|
-
@mutex.synchronize do
|
|
1210
|
-
return if existing_transaction?
|
|
1211
|
-
ensure_session!
|
|
1212
|
-
route_to_leader = LARHeaders.begin_transaction true
|
|
1213
|
-
@grpc = service.begin_transaction session.path, route_to_leader: route_to_leader
|
|
1214
|
-
end
|
|
1215
|
-
end
|
|
1216
|
-
|
|
1217
|
-
##
|
|
1218
|
-
# @private The TransactionSelector to be used for queries. This method must
|
|
1219
|
-
# be called from within a synchronized block, since the value returned
|
|
1220
|
-
# depends on the state of @grpc field.
|
|
1255
|
+
# The TransactionSelector to be used for queries. This method must
|
|
1256
|
+
# be called from within a synchronized block, since the value returned
|
|
1257
|
+
# depends on the state of @grpc field.
|
|
1221
1258
|
#
|
|
1222
|
-
#
|
|
1223
|
-
#
|
|
1259
|
+
# This method is expected to be called from within `safe_execute()` method's block,
|
|
1260
|
+
# since it provides synchronization and gurantees thread safety.
|
|
1261
|
+
#
|
|
1262
|
+
# @param exclude_txn_from_change_streams [::Boolean] Optional. Defaults to `false`.
|
|
1263
|
+
# When `exclude_txn_from_change_streams` is set to `true`, it prevents read
|
|
1264
|
+
# or write transactions from being tracked in change streams.
|
|
1265
|
+
# @private
|
|
1266
|
+
# @return [::Google::Cloud::Spanner::V1::TransactionSelector]
|
|
1224
1267
|
def tx_selector exclude_txn_from_change_streams: false
|
|
1225
1268
|
return V1::TransactionSelector.new id: transaction_id if existing_transaction?
|
|
1226
1269
|
V1::TransactionSelector.new(
|
|
@@ -1261,6 +1304,9 @@ module Google
|
|
|
1261
1304
|
raise "Must have active connection to service" unless session
|
|
1262
1305
|
end
|
|
1263
1306
|
|
|
1307
|
+
# The `Spanner::Service` object used by this transaction.
|
|
1308
|
+
# @private
|
|
1309
|
+
# @return [::Google::Cloud::Spanner::Service]
|
|
1264
1310
|
def service
|
|
1265
1311
|
session.service
|
|
1266
1312
|
end
|