google-cloud-spanner 2.33.0 → 2.35.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 +12 -0
- data/lib/google/cloud/spanner/client.rb +6 -8
- data/lib/google/cloud/spanner/errors.rb +1 -0
- data/lib/google/cloud/spanner/request_id_interceptor.rb +207 -0
- data/lib/google/cloud/spanner/service.rb +8 -1
- data/lib/google/cloud/spanner/session.rb +14 -4
- data/lib/google/cloud/spanner/spanner_error.rb +35 -0
- data/lib/google/cloud/spanner/transaction.rb +11 -4
- data/lib/google/cloud/spanner/version.rb +1 -1
- data/lib/google/cloud/spanner.rb +6 -2
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7f2092db61c2ca6c7797176db72845ee4889255ed94d641d27ea8b5ac42f62b7
|
|
4
|
+
data.tar.gz: 3430361284c44739652f9ca1785a902cfccafc813e9b7833df854f0836df98c4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4edac28e59ec12727331f7810325de889c71154d28a3fb1dc155ec8d92f2f3b0a5a3e1168cc7a7949befd72bb13da25194107041021872778486ea8744a49c00
|
|
7
|
+
data.tar.gz: '018fba01b2d4dd8b16483a4a752c7768e8f512637973bdaf080cf7da8e14e20db8cae51ca0843de1b51dffdadfc4c0e5867bbbd94402d12cc8ecb9373416e1fa'
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Release History
|
|
2
2
|
|
|
3
|
+
### 2.35.0 (2026-02-23)
|
|
4
|
+
|
|
5
|
+
#### Features
|
|
6
|
+
|
|
7
|
+
* propagate transaction tag correctly in all scenarios ([#219](https://github.com/googleapis/ruby-spanner/issues/219))
|
|
8
|
+
|
|
9
|
+
### 2.34.0 (2026-01-30)
|
|
10
|
+
|
|
11
|
+
#### Features
|
|
12
|
+
|
|
13
|
+
* Support request id header feature ([#215](https://github.com/googleapis/ruby-spanner/issues/215))
|
|
14
|
+
|
|
3
15
|
### 2.33.0 (2025-12-12)
|
|
4
16
|
|
|
5
17
|
#### Features
|
|
@@ -2227,11 +2227,11 @@ module Google
|
|
|
2227
2227
|
request_options, tag_type: :transaction_tag
|
|
2228
2228
|
|
|
2229
2229
|
@pool.with_session do |session|
|
|
2230
|
+
transaction_tag = request_options[:transaction_tag] if request_options
|
|
2230
2231
|
tx = session.create_empty_transaction \
|
|
2231
|
-
exclude_txn_from_change_streams: exclude_txn_from_change_streams,
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
end
|
|
2232
|
+
exclude_txn_from_change_streams: exclude_txn_from_change_streams,
|
|
2233
|
+
read_lock_mode: read_lock_mode,
|
|
2234
|
+
transaction_tag: transaction_tag
|
|
2235
2235
|
|
|
2236
2236
|
begin
|
|
2237
2237
|
Thread.current[IS_TRANSACTION_RUNNING_KEY] = true
|
|
@@ -2289,11 +2289,9 @@ module Google
|
|
|
2289
2289
|
tx = session.create_empty_transaction(
|
|
2290
2290
|
exclude_txn_from_change_streams: exclude_txn_from_change_streams,
|
|
2291
2291
|
previous_transaction_id: previous_transaction_id,
|
|
2292
|
-
read_lock_mode: read_lock_mode
|
|
2292
|
+
read_lock_mode: read_lock_mode,
|
|
2293
|
+
transaction_tag: transaction_tag
|
|
2293
2294
|
)
|
|
2294
|
-
if request_options
|
|
2295
|
-
tx.transaction_tag = request_options[:transaction_tag]
|
|
2296
|
-
end
|
|
2297
2295
|
retry
|
|
2298
2296
|
rescue StandardError => e
|
|
2299
2297
|
# Rollback transaction when handling unexpected error
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# Copyright 2026 Google LLC
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
require "grpc"
|
|
17
|
+
require "securerandom"
|
|
18
|
+
require "mutex_m"
|
|
19
|
+
require "google/cloud/spanner/errors"
|
|
20
|
+
|
|
21
|
+
module Google
|
|
22
|
+
module Cloud
|
|
23
|
+
module Spanner
|
|
24
|
+
##
|
|
25
|
+
# RequestIdInterceptor is a GRPC interceptor class that captures all the rpc calls
|
|
26
|
+
# made by the GRPC layer inserting a new Header with a specific ID for debugging purposes.
|
|
27
|
+
#
|
|
28
|
+
class RequestIdInterceptor < GRPC::ClientInterceptor
|
|
29
|
+
@client_id_counter = 0
|
|
30
|
+
@client_mutex = Mutex.new
|
|
31
|
+
@channel_id_counter = 0
|
|
32
|
+
@channel_mutex = Mutex.new
|
|
33
|
+
@request_id_counter = 0
|
|
34
|
+
@request_id_mutex = Mutex.new
|
|
35
|
+
@process_id = nil
|
|
36
|
+
@process_id_mutex = Mutex.new
|
|
37
|
+
|
|
38
|
+
# @private
|
|
39
|
+
# Gets the next client ID and increments it.
|
|
40
|
+
#
|
|
41
|
+
# @return [Integer]
|
|
42
|
+
private_class_method def self.next_client_id
|
|
43
|
+
@client_mutex.synchronize do
|
|
44
|
+
@client_id_counter += 1
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# @private
|
|
49
|
+
# Gets the next channel ID and increments it.
|
|
50
|
+
#
|
|
51
|
+
# @return [Integer]
|
|
52
|
+
private_class_method def self.next_channel_id
|
|
53
|
+
@channel_mutex.synchronize do
|
|
54
|
+
@channel_id_counter += 1
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# @private
|
|
59
|
+
# Returns a process ID for the context of the request id header.
|
|
60
|
+
# A process ID is a Hex encoded 64 bit value
|
|
61
|
+
#
|
|
62
|
+
# @param [String, int] process_id A 64 bit value in Hex or Integer format
|
|
63
|
+
# @return [String]
|
|
64
|
+
private_class_method def self.get_process_id process_id = nil
|
|
65
|
+
@process_id_mutex.synchronize do
|
|
66
|
+
if process_id.nil? || !@process_id.nil?
|
|
67
|
+
return @process_id ||= (SecureRandom.hex 8)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
case process_id
|
|
71
|
+
when Integer
|
|
72
|
+
if process_id >= 0 && process_id.bit_length <= 64
|
|
73
|
+
return process_id.to_s(16).rjust(16, "0")
|
|
74
|
+
end
|
|
75
|
+
when String
|
|
76
|
+
if process_id =~ /\A[0-9a-fA-F]{16}\z/
|
|
77
|
+
return process_id
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
raise ArgumentError, "process_id must be a 64-bit integer or 16-character hex string"
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Initializes a request_id_interceptor instance.
|
|
86
|
+
#
|
|
87
|
+
# @param [String, int] process_id A 64 bit value in Hex or Integer format
|
|
88
|
+
# @return [Google::Cloud::Spanner::RequestIdInterceptor]
|
|
89
|
+
def initialize process_id: nil
|
|
90
|
+
super
|
|
91
|
+
@version = 1
|
|
92
|
+
@process_id = self.class.send :get_process_id, process_id
|
|
93
|
+
@client_id = self.class.send :next_client_id
|
|
94
|
+
@channel_id = self.class.send :next_channel_id
|
|
95
|
+
@request_id_counter = 0
|
|
96
|
+
@request_mutex = Mutex.new
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Intercepts a request_response rpc call
|
|
100
|
+
#
|
|
101
|
+
# @param [String] method The RPC method name
|
|
102
|
+
# @param [Google::Protobuf::MessageExts] request The request to be sent to the RPC call
|
|
103
|
+
# @param [GRPC::ActiveCall::InterceptableView] call An interceptable view object for the call class
|
|
104
|
+
# @param [Hash] metadata All the metadata to be sent to the RPC call
|
|
105
|
+
# @return [void]
|
|
106
|
+
def request_response method:, request:, call:, metadata:, &block
|
|
107
|
+
# Unused. This is to avoid Rubocop's Lint/UnusedMethodArgument
|
|
108
|
+
_method = method
|
|
109
|
+
_request = request
|
|
110
|
+
_call = call
|
|
111
|
+
update_metadata_for_call metadata, &block
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Intercepts a client_streamer rpc call
|
|
115
|
+
#
|
|
116
|
+
# @param [String] method The RPC method name
|
|
117
|
+
# @param [Google::Protobuf::MessageExts] request The request to be sent to the RPC call
|
|
118
|
+
# @param [GRPC::ActiveCall::InterceptableView] call An interceptable view object for the call class
|
|
119
|
+
# @param [Hash] metadata All the metadata to be sent to the RPC call
|
|
120
|
+
# @return [void]
|
|
121
|
+
def client_streamer method:, request:, call:, metadata:, &block
|
|
122
|
+
# Unused. This is to avoid Rubocop's Lint/UnusedMethodArgument
|
|
123
|
+
_method = method
|
|
124
|
+
_request = request
|
|
125
|
+
_call = call
|
|
126
|
+
update_metadata_for_call metadata, &block
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Intercepts a server_streamer rpc call
|
|
130
|
+
#
|
|
131
|
+
# @param [String] method The RPC method name
|
|
132
|
+
# @param [Google::Protobuf::MessageExts] request The request to be sent to the RPC call
|
|
133
|
+
# @param [GRPC::ActiveCall::InterceptableView] call An interceptable view object for the call class
|
|
134
|
+
# @param [Hash] metadata All the metadata to be sent to the RPC call
|
|
135
|
+
# @return [void]
|
|
136
|
+
def server_streamer method:, request:, call:, metadata:, &block
|
|
137
|
+
# Unused. This is to avoid Rubocop's Lint/UnusedMethodArgument
|
|
138
|
+
_method = method
|
|
139
|
+
_request = request
|
|
140
|
+
_call = call
|
|
141
|
+
update_metadata_for_call metadata, &block
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# Intercepts a bidi_streamer rpc call
|
|
145
|
+
#
|
|
146
|
+
# @param [String] method The RPC method name
|
|
147
|
+
# @param [Google::Protobuf::MessageExts] request The request to be sent to the RPC call
|
|
148
|
+
# @param [GRPC::ActiveCall::InterceptableView] call An interceptable view object for the call class
|
|
149
|
+
# @param [Hash] metadata The metadata to be sent to the RPC call
|
|
150
|
+
# @return [void]
|
|
151
|
+
def bidi_streamer method:, request:, call:, metadata:, &block
|
|
152
|
+
# Unused. This is to avoid Rubocop's Lint/UnusedMethodArgument
|
|
153
|
+
_method = method
|
|
154
|
+
_request = request
|
|
155
|
+
_call = call
|
|
156
|
+
update_metadata_for_call metadata, &block
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
private
|
|
160
|
+
|
|
161
|
+
# @private
|
|
162
|
+
# Inserts the Spanner request id header to the metadata for the RPC call
|
|
163
|
+
#
|
|
164
|
+
# @param [Hash] metadata The metadata to be sent to the RPC call
|
|
165
|
+
# @return [void]
|
|
166
|
+
def update_metadata_for_call metadata
|
|
167
|
+
request_id = nil
|
|
168
|
+
attempt = 1
|
|
169
|
+
|
|
170
|
+
if metadata.include? :"x-goog-spanner-request-id"
|
|
171
|
+
request_id, attempt = get_header_request_id_and_attempt metadata[:"x-goog-spanner-request-id"]
|
|
172
|
+
else
|
|
173
|
+
request_id = @request_mutex.synchronize { @request_id_counter += 1 }
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
formatted_request_id = format_request_id request_id, attempt
|
|
177
|
+
metadata[:"x-goog-spanner-request-id"] = formatted_request_id
|
|
178
|
+
|
|
179
|
+
yield
|
|
180
|
+
rescue StandardError => e
|
|
181
|
+
e.instance_variable_set :@spanner_header_id, formatted_request_id
|
|
182
|
+
raise e
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# @private
|
|
186
|
+
# Creates the Spanner request id header in the correct format
|
|
187
|
+
#
|
|
188
|
+
# @param [String] request_id The request id of the Spanner request
|
|
189
|
+
# @param [String] attempt The attempt of the current request after retries
|
|
190
|
+
# @return [String]
|
|
191
|
+
def format_request_id request_id, attempt
|
|
192
|
+
"#{@version}.#{@process_id}.#{@client_id}.#{@channel_id}.#{request_id}.#{attempt}"
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
# @private
|
|
196
|
+
# Parses a request id header and returns the request id and the attempt
|
|
197
|
+
#
|
|
198
|
+
# @param [String] header A string representation of a Spanner request ID.
|
|
199
|
+
# @return [array]
|
|
200
|
+
def get_header_request_id_and_attempt header
|
|
201
|
+
_, _, _, _, request_id, attempt = header.split "."
|
|
202
|
+
[request_id, attempt.to_i + 1]
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
end
|
|
@@ -36,6 +36,7 @@ module Google
|
|
|
36
36
|
attr_accessor :lib_name
|
|
37
37
|
attr_accessor :lib_version
|
|
38
38
|
attr_accessor :quota_project
|
|
39
|
+
attr_accessor :interceptors
|
|
39
40
|
attr_accessor :enable_leader_aware_routing
|
|
40
41
|
|
|
41
42
|
attr_reader :universe_domain
|
|
@@ -51,13 +52,15 @@ module Google
|
|
|
51
52
|
# @param timeout [::Numeric, nil] Optional. Timeout for Gapic client.
|
|
52
53
|
# @param lib_name [::String, nil] Optional. Library name for headers.
|
|
53
54
|
# @param lib_version [::String, nil] Optional. Library version for headers.
|
|
55
|
+
# @param interceptors [::Array<GRPC::ClientInterceptor>, nil] Optional.
|
|
56
|
+
# An array of interceptors that are run before calls are executed.
|
|
54
57
|
# @param enable_leader_aware_routing [::Boolean, nil] Optional. Whether Leader
|
|
55
58
|
# Aware Routing should be enabled.
|
|
56
59
|
# @param universe_domain [::String, nil] Optional. The domain of the universe to connect to.
|
|
57
60
|
# @private
|
|
58
61
|
def initialize project, credentials, quota_project: nil,
|
|
59
62
|
host: nil, timeout: nil, lib_name: nil, lib_version: nil,
|
|
60
|
-
enable_leader_aware_routing: nil, universe_domain: nil
|
|
63
|
+
interceptors: nil, enable_leader_aware_routing: nil, universe_domain: nil
|
|
61
64
|
@project = project
|
|
62
65
|
@credentials = credentials
|
|
63
66
|
@quota_project = quota_project || (credentials.quota_project_id if credentials.respond_to? :quota_project_id)
|
|
@@ -73,6 +76,7 @@ module Google
|
|
|
73
76
|
@timeout = timeout
|
|
74
77
|
@lib_name = lib_name
|
|
75
78
|
@lib_version = lib_version
|
|
79
|
+
@interceptors = interceptors
|
|
76
80
|
@enable_leader_aware_routing = enable_leader_aware_routing
|
|
77
81
|
end
|
|
78
82
|
|
|
@@ -106,6 +110,7 @@ module Google
|
|
|
106
110
|
config.lib_name = lib_name_with_prefix
|
|
107
111
|
config.lib_version = Google::Cloud::Spanner::VERSION
|
|
108
112
|
config.metadata = { "google-cloud-resource-prefix" => "projects/#{@project}" }
|
|
113
|
+
config.interceptors = @interceptors if @interceptors
|
|
109
114
|
end
|
|
110
115
|
end
|
|
111
116
|
attr_accessor :mocked_service
|
|
@@ -122,6 +127,7 @@ module Google
|
|
|
122
127
|
config.lib_name = lib_name_with_prefix
|
|
123
128
|
config.lib_version = Google::Cloud::Spanner::VERSION
|
|
124
129
|
config.metadata = { "google-cloud-resource-prefix" => "projects/#{@project}" }
|
|
130
|
+
config.interceptors = @interceptors if @interceptors
|
|
125
131
|
end
|
|
126
132
|
end
|
|
127
133
|
attr_accessor :mocked_instances
|
|
@@ -138,6 +144,7 @@ module Google
|
|
|
138
144
|
config.lib_name = lib_name_with_prefix
|
|
139
145
|
config.lib_version = Google::Cloud::Spanner::VERSION
|
|
140
146
|
config.metadata = { "google-cloud-resource-prefix" => "projects/#{@project}" }
|
|
147
|
+
config.interceptors = @interceptors if @interceptors
|
|
141
148
|
end
|
|
142
149
|
end
|
|
143
150
|
attr_accessor :mocked_databases
|
|
@@ -1488,17 +1488,24 @@ module Google
|
|
|
1488
1488
|
# @param exclude_txn_from_change_streams [::Boolean] Optional. Defaults to `false`.
|
|
1489
1489
|
# When `exclude_txn_from_change_streams` is set to `true`, it prevents read
|
|
1490
1490
|
# or write transactions from being tracked in change streams.
|
|
1491
|
+
# @param request_options [::Hash, nil] Optional. Common request options.
|
|
1492
|
+
# Example option: `:priority`.
|
|
1491
1493
|
# @private
|
|
1492
1494
|
# @return [::Google::Cloud::Spanner::Transaction]
|
|
1493
|
-
def create_transaction exclude_txn_from_change_streams: false, read_lock_mode: nil
|
|
1495
|
+
def create_transaction exclude_txn_from_change_streams: false, read_lock_mode: nil,
|
|
1496
|
+
request_options: nil
|
|
1494
1497
|
route_to_leader = LARHeaders.begin_transaction true
|
|
1498
|
+
request_options = Convert.to_request_options request_options, tag_type: :transaction_tag
|
|
1499
|
+
transaction_tag = request_options[:transaction_tag] if request_options
|
|
1495
1500
|
tx_grpc = service.begin_transaction path,
|
|
1496
1501
|
route_to_leader: route_to_leader,
|
|
1497
1502
|
exclude_txn_from_change_streams: exclude_txn_from_change_streams,
|
|
1503
|
+
request_options: request_options,
|
|
1498
1504
|
read_lock_mode: read_lock_mode
|
|
1499
1505
|
Transaction.from_grpc \
|
|
1500
1506
|
tx_grpc, self,
|
|
1501
|
-
exclude_txn_from_change_streams: exclude_txn_from_change_streams, read_lock_mode: read_lock_mode
|
|
1507
|
+
exclude_txn_from_change_streams: exclude_txn_from_change_streams, read_lock_mode: read_lock_mode,
|
|
1508
|
+
transaction_tag: transaction_tag
|
|
1502
1509
|
end
|
|
1503
1510
|
|
|
1504
1511
|
# Creates a new empty transaction wrapper without a server-side object.
|
|
@@ -1512,12 +1519,15 @@ module Google
|
|
|
1512
1519
|
# An id of the previous transaction, if this new transaction wrapper is being created
|
|
1513
1520
|
# as a part of a retry. Previous transaction id should be added to TransactionOptions
|
|
1514
1521
|
# of a new ReadWrite transaction when retry is attempted.
|
|
1522
|
+
# @param transaction_tag [::String, nil] Optional.
|
|
1523
|
+
# A tag used for statistics collection about this transaction.
|
|
1515
1524
|
# @private
|
|
1516
1525
|
# @return [::Google::Cloud::Spanner::Transaction] The new *empty-wrapper* transaction object.
|
|
1517
1526
|
def create_empty_transaction exclude_txn_from_change_streams: false, previous_transaction_id: nil,
|
|
1518
|
-
read_lock_mode: nil
|
|
1527
|
+
read_lock_mode: nil, transaction_tag: nil
|
|
1519
1528
|
Transaction.from_grpc nil, self, exclude_txn_from_change_streams: exclude_txn_from_change_streams,
|
|
1520
|
-
previous_transaction_id: previous_transaction_id, read_lock_mode: read_lock_mode
|
|
1529
|
+
previous_transaction_id: previous_transaction_id, read_lock_mode: read_lock_mode,
|
|
1530
|
+
transaction_tag: transaction_tag
|
|
1521
1531
|
end
|
|
1522
1532
|
|
|
1523
1533
|
# If the session is non-multiplexed, keeps the session alive by executing `"SELECT 1"`.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Copyright 2026 Google LLC
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
require "google/cloud/errors"
|
|
17
|
+
|
|
18
|
+
# This is a monkey patch for Google::Cloud::Error to add support for the request_id method
|
|
19
|
+
# to keep this Spanner exclusive method inside the Spanner code.
|
|
20
|
+
# This may be moved into the errors gem itself based on later assessment.
|
|
21
|
+
module Google
|
|
22
|
+
module Cloud
|
|
23
|
+
class Error
|
|
24
|
+
##
|
|
25
|
+
# The Spanner header ID if there was an error on the request.
|
|
26
|
+
#
|
|
27
|
+
# @return [String, nil]
|
|
28
|
+
#
|
|
29
|
+
def request_id
|
|
30
|
+
return nil unless cause.instance_variable_defined? :@spanner_header_id
|
|
31
|
+
cause.instance_variable_get :@spanner_header_id
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -124,13 +124,17 @@ module Google
|
|
|
124
124
|
# An id of the previous transaction, if this new transaction wrapper is being created
|
|
125
125
|
# as a part of a retry. Previous transaction id should be added to TransactionOptions
|
|
126
126
|
# of a new ReadWrite transaction when retry is attempted.
|
|
127
|
+
# @param transaction_tag [::String, nil] Optional.
|
|
128
|
+
# A tag used for statistics collection about this transaction.
|
|
127
129
|
# @private
|
|
128
130
|
# @return [::Google::Cloud::Spanner::Transaction]
|
|
129
|
-
def initialize grpc, session, exclude_txn_from_change_streams, previous_transaction_id: nil,
|
|
131
|
+
def initialize grpc, session, exclude_txn_from_change_streams, previous_transaction_id: nil,
|
|
132
|
+
read_lock_mode: nil, transaction_tag: nil
|
|
130
133
|
@grpc = grpc
|
|
131
134
|
@session = session
|
|
132
135
|
@exclude_txn_from_change_streams = exclude_txn_from_change_streams
|
|
133
136
|
@read_lock_mode = read_lock_mode
|
|
137
|
+
@transaction_tag = transaction_tag
|
|
134
138
|
|
|
135
139
|
# throwing away empty strings for simplicity
|
|
136
140
|
unless previous_transaction_id.nil? || previous_transaction_id.empty?
|
|
@@ -1253,12 +1257,14 @@ module Google
|
|
|
1253
1257
|
# An id of the previous transaction, if this new transaction wrapper is being created
|
|
1254
1258
|
# as a part of a retry. Previous transaction id should be added to TransactionOptions
|
|
1255
1259
|
# of a new ReadWrite transaction when retry is attempted.
|
|
1260
|
+
# @param transaction_tag [::String, nil] Optional.
|
|
1261
|
+
# A tag used for statistics collection about this transaction.
|
|
1256
1262
|
# @private
|
|
1257
1263
|
# @return [::Google::Cloud::Spanner::Transaction]
|
|
1258
1264
|
def self.from_grpc grpc, session, exclude_txn_from_change_streams: false, previous_transaction_id: nil,
|
|
1259
|
-
read_lock_mode: nil
|
|
1265
|
+
read_lock_mode: nil, transaction_tag: nil
|
|
1260
1266
|
new grpc, session, exclude_txn_from_change_streams, previous_transaction_id: previous_transaction_id,
|
|
1261
|
-
read_lock_mode: read_lock_mode
|
|
1267
|
+
read_lock_mode: read_lock_mode, transaction_tag: transaction_tag
|
|
1262
1268
|
end
|
|
1263
1269
|
|
|
1264
1270
|
##
|
|
@@ -1297,6 +1303,7 @@ read_lock_mode: read_lock_mode
|
|
|
1297
1303
|
return if existing_transaction?
|
|
1298
1304
|
ensure_session!
|
|
1299
1305
|
route_to_leader = LARHeaders.begin_transaction true
|
|
1306
|
+
request_options = build_request_options request_options
|
|
1300
1307
|
|
|
1301
1308
|
# TODO: [virost@, 2025-10] fix this so it uses tx_selector
|
|
1302
1309
|
# instead of re-creating it within `Service#begin_transaction`
|
|
@@ -1377,7 +1384,7 @@ read_lock_mode: read_lock_mode
|
|
|
1377
1384
|
|
|
1378
1385
|
##
|
|
1379
1386
|
# @private Build request options. If transaction tag is set
|
|
1380
|
-
# then add
|
|
1387
|
+
# then add it to the request options.
|
|
1381
1388
|
def build_request_options options
|
|
1382
1389
|
options = Convert.to_request_options options, tag_type: :request_tag
|
|
1383
1390
|
|
data/lib/google/cloud/spanner.rb
CHANGED
|
@@ -15,6 +15,8 @@
|
|
|
15
15
|
|
|
16
16
|
require "google-cloud-spanner"
|
|
17
17
|
require "google/cloud/spanner/project"
|
|
18
|
+
require "google/cloud/spanner/spanner_error"
|
|
19
|
+
require "google/cloud/spanner/request_id_interceptor"
|
|
18
20
|
require "google/cloud/config"
|
|
19
21
|
require "google/cloud/env"
|
|
20
22
|
|
|
@@ -96,7 +98,7 @@ module Google
|
|
|
96
98
|
def self.new project_id: nil, credentials: nil, scope: nil, timeout: nil,
|
|
97
99
|
endpoint: nil, project: nil, keyfile: nil,
|
|
98
100
|
emulator_host: nil, lib_name: nil, lib_version: nil,
|
|
99
|
-
enable_leader_aware_routing: true, universe_domain: nil
|
|
101
|
+
enable_leader_aware_routing: true, universe_domain: nil, process_id: nil
|
|
100
102
|
project_id ||= project || default_project_id
|
|
101
103
|
scope ||= configure.scope
|
|
102
104
|
timeout ||= configure.timeout
|
|
@@ -105,6 +107,7 @@ module Google
|
|
|
105
107
|
credentials ||= keyfile
|
|
106
108
|
lib_name ||= configure.lib_name
|
|
107
109
|
lib_version ||= configure.lib_version
|
|
110
|
+
interceptors = [RequestIdInterceptor.new(process_id: process_id)]
|
|
108
111
|
universe_domain ||= configure.universe_domain
|
|
109
112
|
|
|
110
113
|
if emulator_host
|
|
@@ -127,7 +130,8 @@ module Google
|
|
|
127
130
|
Spanner::Service.new(
|
|
128
131
|
project_id, credentials, quota_project: configure.quota_project,
|
|
129
132
|
host: endpoint, timeout: timeout, lib_name: lib_name,
|
|
130
|
-
lib_version: lib_version,
|
|
133
|
+
lib_version: lib_version, interceptors: interceptors,
|
|
134
|
+
universe_domain: universe_domain,
|
|
131
135
|
enable_leader_aware_routing: enable_leader_aware_routing
|
|
132
136
|
),
|
|
133
137
|
query_options: configure.query_options
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: google-cloud-spanner
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.35.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Mike Moore
|
|
@@ -158,12 +158,14 @@ files:
|
|
|
158
158
|
- lib/google/cloud/spanner/pool.rb
|
|
159
159
|
- lib/google/cloud/spanner/project.rb
|
|
160
160
|
- lib/google/cloud/spanner/range.rb
|
|
161
|
+
- lib/google/cloud/spanner/request_id_interceptor.rb
|
|
161
162
|
- lib/google/cloud/spanner/results.rb
|
|
162
163
|
- lib/google/cloud/spanner/service.rb
|
|
163
164
|
- lib/google/cloud/spanner/session.rb
|
|
164
165
|
- lib/google/cloud/spanner/session_cache.rb
|
|
165
166
|
- lib/google/cloud/spanner/session_creation_options.rb
|
|
166
167
|
- lib/google/cloud/spanner/snapshot.rb
|
|
168
|
+
- lib/google/cloud/spanner/spanner_error.rb
|
|
167
169
|
- lib/google/cloud/spanner/status.rb
|
|
168
170
|
- lib/google/cloud/spanner/transaction.rb
|
|
169
171
|
- lib/google/cloud/spanner/version.rb
|