Skip to content
This repository was archived by the owner on Mar 31, 2026. It is now read-only.

Commit 2451afe

Browse files
committed
feat(x-goog-spanner-request-id)
request-id: generate rand_process_id, increment nth_request per client
1 parent 054a186 commit 2451afe

File tree

3 files changed

+58
-0
lines changed

3 files changed

+58
-0
lines changed

google/cloud/spanner_v1/client.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import grpc
2727
import os
2828
import warnings
29+
import threading
2930

3031
from google.api_core.gapic_v1 import client_info
3132
from google.auth.credentials import AnonymousCredentials
@@ -147,6 +148,8 @@ class Client(ClientWithProject):
147148
SCOPE = (SPANNER_ADMIN_SCOPE,)
148149
"""The scopes required for Google Cloud Spanner."""
149150

151+
NTH_CLIENT = 0
152+
150153
def __init__(
151154
self,
152155
project=None,
@@ -199,6 +202,16 @@ def __init__(
199202
self._route_to_leader_enabled = route_to_leader_enabled
200203
self._directed_read_options = directed_read_options
201204
self._observability_options = observability_options
205+
Client.NTH_CLIENT += 1
206+
self._nth_client_id = Client.NTH_CLIENT
207+
self._nth_request = 0
208+
self.__lock = threading.lock()
209+
210+
@property
211+
def _next_nth_request(self):
212+
with self.__lock:
213+
self._nth_request += 1
214+
return self._nth_request
202215

203216
@property
204217
def credentials(self):

google/cloud/spanner_v1/database.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,9 @@ def execute_partitioned_dml(
693693
_metadata_with_leader_aware_routing(self._route_to_leader_enabled)
694694
)
695695

696+
nth_request = self._increment_request_count()
697+
attempt = 1
698+
696699
def execute_pdml():
697700
with SessionCheckout(self._pool) as session:
698701
txn = api.begin_transaction(
@@ -728,6 +731,9 @@ def execute_pdml():
728731

729732
return _retry_on_aborted(execute_pdml, DEFAULT_RETRY_BACKOFF)()
730733

734+
def _next_nth_request(self):
735+
return self._instance._client._next_nth_request()
736+
731737
def session(self, labels=None, database_role=None):
732738
"""Factory to create a session for this database.
733739
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Copyright 2024 Google LLC All rights reserved.
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+
# http://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+
import os
16+
17+
REQ_ID_VERSION = 1 # The version of the x-goog-spanner-request-id spec.
18+
REQ_ID_HEADER_KEY = "x-goog-spanner-request-id"
19+
20+
21+
def generate_rand_uint64():
22+
b = os.urandom(8)
23+
return (
24+
b[7] & 0xFF
25+
| (b[6] & 0xFF) << 8
26+
| (b[5] & 0xFF) << 16
27+
| (b[4] & 0xFF) << 24
28+
| (b[3] & 0xFF) << 32
29+
| (b[2] & 0xFF) << 36
30+
| (b[1] & 0xFF) << 48
31+
| (b[0] & 0xFF) << 56
32+
)
33+
34+
35+
REQ_RAND_PROCESS_ID = generate_rand_uint64()
36+
37+
38+
def metadata_with_request_id(req_id):
39+
return [(REQ_ID_HEADER_KEY, req_id)]

0 commit comments

Comments
 (0)