From a7fa732c5b7e49784dddcaa77097214e43ca3e82 Mon Sep 17 00:00:00 2001 From: Alka Trivedi Date: Sat, 2 May 2026 16:05:58 +0530 Subject: [PATCH 1/4] feat(spanner): make affinity keys configurable via spanner_grpc_config.json --- handwritten/spanner/src/index.ts | 3 +- .../spanner/src/spanner_grpc_config.json | 33 +++++++-- handwritten/spanner/src/transaction.ts | 73 +++++++++++++++++-- handwritten/spanner/test/index.ts | 4 +- .../spanner/test/multiplexed-session.ts | 14 +++- 5 files changed, 107 insertions(+), 20 deletions(-) diff --git a/handwritten/spanner/src/index.ts b/handwritten/spanner/src/index.ts index 50d393249fe2..68babb219457 100644 --- a/handwritten/spanner/src/index.ts +++ b/handwritten/spanner/src/index.ts @@ -424,7 +424,8 @@ class Spanner extends GrpcService { // Enable grpc-gcp support 'grpc.callInvocationTransformer': grpcGcp.gcpCallInvocationTransformer, 'grpc.channelFactoryOverride': grpcGcp.gcpChannelFactoryOverride, - 'grpc.gcpApiConfig': grpcGcp.createGcpApiConfig(gcpApiConfig), + // Bypass createGcpApiConfig to preserve our custom metadata fields + 'grpc.gcpApiConfig': gcpApiConfig, grpc, }, options || {}, diff --git a/handwritten/spanner/src/spanner_grpc_config.json b/handwritten/spanner/src/spanner_grpc_config.json index bd640bdbe0b9..a13e0ecfaaa9 100644 --- a/handwritten/spanner/src/spanner_grpc_config.json +++ b/handwritten/spanner/src/spanner_grpc_config.json @@ -29,49 +29,67 @@ "name": ["/google.spanner.v1.Spanner/ExecuteSql"], "affinity": { "command": "BOUND", - "affinityKey": "session" + "affinityKey": "session", + "affinityKeyLocation": "METADATA", + "metadataKey": "x-grpc-gcp-affinity-key" } }, { "name": ["/google.spanner.v1.Spanner/ExecuteStreamingSql"], "affinity": { "command": "BOUND", - "affinityKey": "session" + "affinityKey": "session", + "affinityKeyLocation": "METADATA", + "metadataKey": "x-grpc-gcp-affinity-key" } }, { "name": ["/google.spanner.v1.Spanner/Read"], "affinity": { "command": "BOUND", - "affinityKey": "session" + "affinityKey": "session", + "affinityKeyLocation": "METADATA", + "metadataKey": "x-grpc-gcp-affinity-key" } }, { "name": ["/google.spanner.v1.Spanner/StreamingRead"], "affinity": { "command": "BOUND", - "affinityKey": "session" + "affinityKey": "session", + "affinityKeyLocation": "METADATA", + "metadataKey": "x-grpc-gcp-affinity-key" } }, { "name": ["/google.spanner.v1.Spanner/BeginTransaction"], "affinity": { "command": "BOUND", - "affinityKey": "session" + "affinityKey": "session", + "affinityKeyLocation": "METADATA", + "metadataKey": "x-grpc-gcp-affinity-key" } }, { "name": ["/google.spanner.v1.Spanner/Commit"], "affinity": { "command": "BOUND", - "affinityKey": "session" + "affinityKey": "session", + "affinityKeyLocation": "METADATA", + "metadataKey": "x-grpc-gcp-affinity-key", + "unbindKeyLocation": "METADATA", + "unbindMetadataKey": "x-grpc-gcp-unbind" } }, { "name": ["/google.spanner.v1.Spanner/Rollback"], "affinity": { "command": "BOUND", - "affinityKey": "session" + "affinityKey": "session", + "affinityKeyLocation": "METADATA", + "metadataKey": "x-grpc-gcp-affinity-key", + "unbindKeyLocation": "METADATA", + "unbindMetadataKey": "x-grpc-gcp-unbind" } }, { @@ -90,3 +108,4 @@ } ] } + diff --git a/handwritten/spanner/src/transaction.ts b/handwritten/spanner/src/transaction.ts index 75d4b2d00794..c1750c250dc0 100644 --- a/handwritten/spanner/src/transaction.ts +++ b/handwritten/spanner/src/transaction.ts @@ -55,6 +55,9 @@ import { } from './instrument'; import {RunTransactionOptions} from './transaction-runner'; import {injectRequestIDIntoHeaders, nextNthRequest} from './request_id_header'; +import * as uuid from 'uuid'; + +const gcpApiConfig = require('./spanner_grpc_config.json'); export type Rows = Array; const RETRY_INFO_TYPE = 'type.googleapis.com/google.rpc.retryinfo'; @@ -296,6 +299,7 @@ export class Snapshot extends EventEmitter { | undefined | null; id?: Uint8Array | string; + public _affinityKey?: string; multiplexedSessionPreviousTransactionId?: Uint8Array | string; ended: boolean; metadata?: spannerClient.spanner.v1.ITransaction; @@ -365,8 +369,39 @@ export class Snapshot extends EventEmitter { this.ended = false; this.session = session; this.queryOptions = Object.assign({}, queryOptions); - this.request = session.request.bind(session); - this.requestStream = session.requestStream.bind(session); + // If the session is multiplexed, generate a unique affinity key (UUID) for this + // specific transaction/snapshot. This allows requests using the same shared + // multiplexed session to be distributed across different gRPC channels. + if (session.metadata && session.metadata.multiplexed) { + this._affinityKey = uuid.v4(); + } + const getMetadataHeaderName = (rpcMethodName: string): string => { + const method = + rpcMethodName.charAt(0).toUpperCase() + rpcMethodName.slice(1); + const fullRpcPath = `/google.spanner.v1.Spanner/${method}`; + const methodConfig = gcpApiConfig.method.find(m => + m.name.includes(fullRpcPath), + ); + return methodConfig?.affinity?.metadataKey || 'x-grpc-gcp-affinity-key'; + }; + + this.request = (config: any, callback: Function) => { + if (this._affinityKey) { + const headerName = getMetadataHeaderName(config.method); + config.headers = config.headers || {}; + config.headers[headerName] = this._affinityKey; + } + return session.request(config, callback); + }; + + this.requestStream = (config: any) => { + if (this._affinityKey) { + const headerName = getMetadataHeaderName(config.method); + config.headers = config.headers || {}; + config.headers[headerName] = this._affinityKey; + } + return session.requestStream(config); + }; const readOnly = Snapshot.encodeTimestampBounds(options || {}); this._options = {readOnly}; @@ -1324,7 +1359,7 @@ export class Snapshot extends EventEmitter { * options as well as several convenience properties. * * @see [Query Syntax](https://cloud.google.com/spanner/docs/query-syntax) - * @see [ExecuteSql API Documentation](https://cloud.google.com/spanner/docs/reference/rpc/google.spanner.v1#google.spanner.v1.Spanner.ExecuteSql) + * @see [ExecuteSql API Documentation](https://cloud.google.com/spanner/docs/reference/rpc/google.spanner.v1#google.spanner.v1.ExecuteSql) * * @typedef {object} ExecuteSqlRequest * @property {string} resumeToken The token used to resume getting results. @@ -2453,6 +2488,20 @@ export class Transaction extends Dml { addLeaderAwareRoutingHeader(headers); } + // Create a copy to avoid leaking the unbind header to the global commonHeaders_. + const requestHeaders = Object.assign({}, headers); + + // Signal to grpc-gcp to unbind the affinity key and clean up memory + // since this transaction is now complete. + if (this._affinityKey) { + const commitConfig = gcpApiConfig.method.find(m => + m.name.includes('/google.spanner.v1.Spanner/Commit'), + ); + const unbindHeaderName = + commitConfig?.affinity?.unbindMetadataKey || 'x-grpc-gcp-unbind'; + requestHeaders[unbindHeaderName] = 'true'; + } + span.addEvent('Starting Commit'); const database = this.session.parent as Database; @@ -2463,7 +2512,7 @@ export class Transaction extends Dml { reqOpts, gaxOpts: gaxOpts, headers: injectRequestIDIntoHeaders( - headers, + requestHeaders, this.session, nextNthRequest(database), 1, @@ -2819,13 +2868,27 @@ export class Transaction extends Dml { addLeaderAwareRoutingHeader(headers); } + // Create a copy to avoid leaking the unbind header to the global commonHeaders_. + const requestHeaders = Object.assign({}, headers); + + // Signal to grpc-gcp to unbind the affinity key and clean up memory + // since this transaction is now complete. + if (this._affinityKey) { + const rollbackConfig = gcpApiConfig.method.find(m => + m.name.includes('/google.spanner.v1.Spanner/Rollback'), + ); + const unbindHeaderName = + rollbackConfig?.affinity?.unbindMetadataKey || 'x-grpc-gcp-unbind'; + requestHeaders[unbindHeaderName] = 'true'; + } + this.request( { client: 'SpannerClient', method: 'rollback', reqOpts, gaxOpts, - headers: headers, + headers: requestHeaders, }, (err: null | ServiceError) => { if (err) { diff --git a/handwritten/spanner/test/index.ts b/handwritten/spanner/test/index.ts index 9a47f920d99b..f2e57fd7e562 100644 --- a/handwritten/spanner/test/index.ts +++ b/handwritten/spanner/test/index.ts @@ -232,9 +232,7 @@ describe('Spanner', () => { 'grpc.callInvocationTransformer': fakeGrpcGcp().gcpCallInvocationTransformer, 'grpc.channelFactoryOverride': fakeGrpcGcp().gcpChannelFactoryOverride, - 'grpc.gcpApiConfig': { - calledWith_: apiConfig, - }, + 'grpc.gcpApiConfig': apiConfig, }); it('should localize a cached gapic client map', () => { diff --git a/handwritten/spanner/test/multiplexed-session.ts b/handwritten/spanner/test/multiplexed-session.ts index d21f912f5e8f..ba934dd25d5a 100644 --- a/handwritten/spanner/test/multiplexed-session.ts +++ b/handwritten/spanner/test/multiplexed-session.ts @@ -43,7 +43,11 @@ describe('MultiplexedSession', () => { return Object.assign(new Session(DATABASE, name), props, { create: sandbox.stub().resolves(), - transaction: sandbox.stub().returns(new FakeTransaction()), + transaction: sandbox.stub().callsFake(() => { + const txn = new FakeTransaction(); + (txn as any)._affinityKey = 'mock-uuid'; + return txn; + }), }); }; @@ -185,13 +189,15 @@ describe('MultiplexedSession', () => { }); }); - it('should pass back the session and txn', done => { - const fakeTxn = new FakeTransaction() as unknown as Transaction; + it('should pass back the session and txn with affinity key', done => { sandbox.stub(multiplexedSession, '_getSession').resolves(fakeMuxSession); multiplexedSession.getSession((err, session, txn) => { assert.ifError(err); assert.strictEqual(session, fakeMuxSession); - assert.deepStrictEqual(txn, fakeTxn); + assert(txn); + assert(txn._affinityKey); + assert.strictEqual(typeof txn._affinityKey, 'string'); + assert(txn._affinityKey.length > 0); done(); }); }); From 00ba3d6c77f86e3a2e0e0563d3e480264d5883fa Mon Sep 17 00:00:00 2001 From: Alka Trivedi Date: Sun, 3 May 2026 07:21:13 +0530 Subject: [PATCH 2/4] gemini review comments --- handwritten/spanner/src/transaction.ts | 51 ++++++++++++++++++-------- 1 file changed, 36 insertions(+), 15 deletions(-) diff --git a/handwritten/spanner/src/transaction.ts b/handwritten/spanner/src/transaction.ts index c1750c250dc0..91c467c04a22 100644 --- a/handwritten/spanner/src/transaction.ts +++ b/handwritten/spanner/src/transaction.ts @@ -59,6 +59,18 @@ import * as uuid from 'uuid'; const gcpApiConfig = require('./spanner_grpc_config.json'); +// Pre-compute a map for O(1) affinity lookups +const methodToAffinityMap = new Map(); +if (gcpApiConfig && gcpApiConfig.method) { + gcpApiConfig.method.forEach((m: any) => { + if (m.name && m.affinity) { + m.name.forEach((name: string) => { + methodToAffinityMap.set(name, m.affinity); + }); + } + }); +} + export type Rows = Array; const RETRY_INFO_TYPE = 'type.googleapis.com/google.rpc.retryinfo'; const RETRY_INFO_BIN = 'google.rpc.retryinfo-bin'; @@ -379,17 +391,21 @@ export class Snapshot extends EventEmitter { const method = rpcMethodName.charAt(0).toUpperCase() + rpcMethodName.slice(1); const fullRpcPath = `/google.spanner.v1.Spanner/${method}`; - const methodConfig = gcpApiConfig.method.find(m => - m.name.includes(fullRpcPath), - ); - return methodConfig?.affinity?.metadataKey || 'x-grpc-gcp-affinity-key'; + + const affinity = methodToAffinityMap.get(fullRpcPath); + return affinity?.metadataKey || 'x-grpc-gcp-affinity-key'; }; this.request = (config: any, callback: Function) => { if (this._affinityKey) { const headerName = getMetadataHeaderName(config.method); - config.headers = config.headers || {}; - config.headers[headerName] = this._affinityKey; + config = { + ...config, + headers: { + ...(config.headers || {}), + [headerName]: this._affinityKey, + }, + }; } return session.request(config, callback); }; @@ -397,8 +413,13 @@ export class Snapshot extends EventEmitter { this.requestStream = (config: any) => { if (this._affinityKey) { const headerName = getMetadataHeaderName(config.method); - config.headers = config.headers || {}; - config.headers[headerName] = this._affinityKey; + config = { + ...config, + headers: { + ...(config.headers || {}), + [headerName]: this._affinityKey, + }, + }; } return session.requestStream(config); }; @@ -1359,7 +1380,7 @@ export class Snapshot extends EventEmitter { * options as well as several convenience properties. * * @see [Query Syntax](https://cloud.google.com/spanner/docs/query-syntax) - * @see [ExecuteSql API Documentation](https://cloud.google.com/spanner/docs/reference/rpc/google.spanner.v1#google.spanner.v1.ExecuteSql) + * @see [ExecuteSql API Documentation](https://cloud.google.com/spanner/docs/reference/rpc/google.spanner.v1#google.spanner.v1.Spanner.ExecuteSql) * * @typedef {object} ExecuteSqlRequest * @property {string} resumeToken The token used to resume getting results. @@ -2494,11 +2515,11 @@ export class Transaction extends Dml { // Signal to grpc-gcp to unbind the affinity key and clean up memory // since this transaction is now complete. if (this._affinityKey) { - const commitConfig = gcpApiConfig.method.find(m => - m.name.includes('/google.spanner.v1.Spanner/Commit'), + const affinity = methodToAffinityMap.get( + '/google.spanner.v1.Spanner/Commit', ); const unbindHeaderName = - commitConfig?.affinity?.unbindMetadataKey || 'x-grpc-gcp-unbind'; + affinity?.unbindMetadataKey || 'x-grpc-gcp-unbind'; requestHeaders[unbindHeaderName] = 'true'; } @@ -2874,11 +2895,11 @@ export class Transaction extends Dml { // Signal to grpc-gcp to unbind the affinity key and clean up memory // since this transaction is now complete. if (this._affinityKey) { - const rollbackConfig = gcpApiConfig.method.find(m => - m.name.includes('/google.spanner.v1.Spanner/Rollback'), + const affinity = methodToAffinityMap.get( + '/google.spanner.v1.Spanner/Rollback', ); const unbindHeaderName = - rollbackConfig?.affinity?.unbindMetadataKey || 'x-grpc-gcp-unbind'; + affinity?.unbindMetadataKey || 'x-grpc-gcp-unbind'; requestHeaders[unbindHeaderName] = 'true'; } From ec16d7cfcf9e5286f6bedef548c3a71a039f1ac5 Mon Sep 17 00:00:00 2001 From: Alka Trivedi Date: Fri, 8 May 2026 12:51:40 +0530 Subject: [PATCH 3/4] use calloptions to pass affinity key --- handwritten/spanner/protos/protos.d.ts | 48 +++ handwritten/spanner/protos/protos.js | 273 +++++++++++++++++- handwritten/spanner/protos/protos.json | 43 +++ handwritten/spanner/src/database.ts | 1 + .../spanner/src/spanner_grpc_config.json | 32 +- handwritten/spanner/src/transaction.ts | 107 ++++--- 6 files changed, 433 insertions(+), 71 deletions(-) diff --git a/handwritten/spanner/protos/protos.d.ts b/handwritten/spanner/protos/protos.d.ts index 2beea4b0984b..9bc6110e43e7 100644 --- a/handwritten/spanner/protos/protos.d.ts +++ b/handwritten/spanner/protos/protos.d.ts @@ -5655,6 +5655,24 @@ export namespace google { /** Violation description */ description?: (string|null); + + /** Violation apiService */ + apiService?: (string|null); + + /** Violation quotaMetric */ + quotaMetric?: (string|null); + + /** Violation quotaId */ + quotaId?: (string|null); + + /** Violation quotaDimensions */ + quotaDimensions?: ({ [k: string]: string }|null); + + /** Violation quotaValue */ + quotaValue?: (number|Long|string|null); + + /** Violation futureQuotaValue */ + futureQuotaValue?: (number|Long|string|null); } /** Represents a Violation. */ @@ -5672,6 +5690,24 @@ export namespace google { /** Violation description. */ public description: string; + /** Violation apiService. */ + public apiService: string; + + /** Violation quotaMetric. */ + public quotaMetric: string; + + /** Violation quotaId. */ + public quotaId: string; + + /** Violation quotaDimensions. */ + public quotaDimensions: { [k: string]: string }; + + /** Violation quotaValue. */ + public quotaValue: (number|Long|string); + + /** Violation futureQuotaValue. */ + public futureQuotaValue?: (number|Long|string|null); + /** * Creates a new Violation instance using the specified properties. * @param [properties] Properties to set @@ -6067,6 +6103,12 @@ export namespace google { /** FieldViolation description */ description?: (string|null); + + /** FieldViolation reason */ + reason?: (string|null); + + /** FieldViolation localizedMessage */ + localizedMessage?: (google.rpc.ILocalizedMessage|null); } /** Represents a FieldViolation. */ @@ -6084,6 +6126,12 @@ export namespace google { /** FieldViolation description. */ public description: string; + /** FieldViolation reason. */ + public reason: string; + + /** FieldViolation localizedMessage. */ + public localizedMessage?: (google.rpc.ILocalizedMessage|null); + /** * Creates a new FieldViolation instance using the specified properties. * @param [properties] Properties to set diff --git a/handwritten/spanner/protos/protos.js b/handwritten/spanner/protos/protos.js index 1007227b2abe..b2caff00cdbb 100644 --- a/handwritten/spanner/protos/protos.js +++ b/handwritten/spanner/protos/protos.js @@ -16761,6 +16761,12 @@ * @interface IViolation * @property {string|null} [subject] Violation subject * @property {string|null} [description] Violation description + * @property {string|null} [apiService] Violation apiService + * @property {string|null} [quotaMetric] Violation quotaMetric + * @property {string|null} [quotaId] Violation quotaId + * @property {Object.|null} [quotaDimensions] Violation quotaDimensions + * @property {number|Long|null} [quotaValue] Violation quotaValue + * @property {number|Long|null} [futureQuotaValue] Violation futureQuotaValue */ /** @@ -16772,6 +16778,7 @@ * @param {google.rpc.QuotaFailure.IViolation=} [properties] Properties to set */ function Violation(properties) { + this.quotaDimensions = {}; if (properties) for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) if (properties[keys[i]] != null && keys[i] !== "__proto__") @@ -16794,6 +16801,63 @@ */ Violation.prototype.description = ""; + /** + * Violation apiService. + * @member {string} apiService + * @memberof google.rpc.QuotaFailure.Violation + * @instance + */ + Violation.prototype.apiService = ""; + + /** + * Violation quotaMetric. + * @member {string} quotaMetric + * @memberof google.rpc.QuotaFailure.Violation + * @instance + */ + Violation.prototype.quotaMetric = ""; + + /** + * Violation quotaId. + * @member {string} quotaId + * @memberof google.rpc.QuotaFailure.Violation + * @instance + */ + Violation.prototype.quotaId = ""; + + /** + * Violation quotaDimensions. + * @member {Object.} quotaDimensions + * @memberof google.rpc.QuotaFailure.Violation + * @instance + */ + Violation.prototype.quotaDimensions = $util.emptyObject; + + /** + * Violation quotaValue. + * @member {number|Long} quotaValue + * @memberof google.rpc.QuotaFailure.Violation + * @instance + */ + Violation.prototype.quotaValue = $util.Long ? $util.Long.fromBits(0,0,false) : 0; + + /** + * Violation futureQuotaValue. + * @member {number|Long|null|undefined} futureQuotaValue + * @memberof google.rpc.QuotaFailure.Violation + * @instance + */ + Violation.prototype.futureQuotaValue = null; + + // OneOf field names bound to virtual getters and setters + var $oneOfFields; + + // Virtual OneOf for proto3 optional field + Object.defineProperty(Violation.prototype, "_futureQuotaValue", { + get: $util.oneOfGetter($oneOfFields = ["futureQuotaValue"]), + set: $util.oneOfSetter($oneOfFields) + }); + /** * Creates a new Violation instance using the specified properties. * @function create @@ -16822,6 +16886,19 @@ writer.uint32(/* id 1, wireType 2 =*/10).string(message.subject); if (message.description != null && Object.hasOwnProperty.call(message, "description")) writer.uint32(/* id 2, wireType 2 =*/18).string(message.description); + if (message.apiService != null && Object.hasOwnProperty.call(message, "apiService")) + writer.uint32(/* id 3, wireType 2 =*/26).string(message.apiService); + if (message.quotaMetric != null && Object.hasOwnProperty.call(message, "quotaMetric")) + writer.uint32(/* id 4, wireType 2 =*/34).string(message.quotaMetric); + if (message.quotaId != null && Object.hasOwnProperty.call(message, "quotaId")) + writer.uint32(/* id 5, wireType 2 =*/42).string(message.quotaId); + if (message.quotaDimensions != null && Object.hasOwnProperty.call(message, "quotaDimensions")) + for (var keys = Object.keys(message.quotaDimensions), i = 0; i < keys.length; ++i) + writer.uint32(/* id 6, wireType 2 =*/50).fork().uint32(/* id 1, wireType 2 =*/10).string(keys[i]).uint32(/* id 2, wireType 2 =*/18).string(message.quotaDimensions[keys[i]]).ldelim(); + if (message.quotaValue != null && Object.hasOwnProperty.call(message, "quotaValue")) + writer.uint32(/* id 7, wireType 0 =*/56).int64(message.quotaValue); + if (message.futureQuotaValue != null && Object.hasOwnProperty.call(message, "futureQuotaValue")) + writer.uint32(/* id 8, wireType 0 =*/64).int64(message.futureQuotaValue); return writer; }; @@ -16856,7 +16933,7 @@ long = 0; if (long > $Reader.recursionLimit) throw Error("maximum nesting depth exceeded"); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.rpc.QuotaFailure.Violation(); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.rpc.QuotaFailure.Violation(), key, value; while (reader.pos < end) { var tag = reader.uint32(); if (tag === error) @@ -16870,6 +16947,51 @@ message.description = reader.string(); break; } + case 3: { + message.apiService = reader.string(); + break; + } + case 4: { + message.quotaMetric = reader.string(); + break; + } + case 5: { + message.quotaId = reader.string(); + break; + } + case 6: { + if (message.quotaDimensions === $util.emptyObject) + message.quotaDimensions = {}; + var end2 = reader.uint32() + reader.pos; + key = ""; + value = ""; + while (reader.pos < end2) { + var tag2 = reader.uint32(); + switch (tag2 >>> 3) { + case 1: + key = reader.string(); + break; + case 2: + value = reader.string(); + break; + default: + reader.skipType(tag2 & 7, long); + break; + } + } + if (key === "__proto__") + $util.makeProp(message.quotaDimensions, key); + message.quotaDimensions[key] = value; + break; + } + case 7: { + message.quotaValue = reader.int64(); + break; + } + case 8: { + message.futureQuotaValue = reader.int64(); + break; + } default: reader.skipType(tag & 7, long); break; @@ -16909,12 +17031,38 @@ long = 0; if (long > $util.recursionLimit) return "maximum nesting depth exceeded"; + var properties = {}; if (message.subject != null && message.hasOwnProperty("subject")) if (!$util.isString(message.subject)) return "subject: string expected"; if (message.description != null && message.hasOwnProperty("description")) if (!$util.isString(message.description)) return "description: string expected"; + if (message.apiService != null && message.hasOwnProperty("apiService")) + if (!$util.isString(message.apiService)) + return "apiService: string expected"; + if (message.quotaMetric != null && message.hasOwnProperty("quotaMetric")) + if (!$util.isString(message.quotaMetric)) + return "quotaMetric: string expected"; + if (message.quotaId != null && message.hasOwnProperty("quotaId")) + if (!$util.isString(message.quotaId)) + return "quotaId: string expected"; + if (message.quotaDimensions != null && message.hasOwnProperty("quotaDimensions")) { + if (!$util.isObject(message.quotaDimensions)) + return "quotaDimensions: object expected"; + var key = Object.keys(message.quotaDimensions); + for (var i = 0; i < key.length; ++i) + if (!$util.isString(message.quotaDimensions[key[i]])) + return "quotaDimensions: string{k:string} expected"; + } + if (message.quotaValue != null && message.hasOwnProperty("quotaValue")) + if (!$util.isInteger(message.quotaValue) && !(message.quotaValue && $util.isInteger(message.quotaValue.low) && $util.isInteger(message.quotaValue.high))) + return "quotaValue: integer|Long expected"; + if (message.futureQuotaValue != null && message.hasOwnProperty("futureQuotaValue")) { + properties._futureQuotaValue = 1; + if (!$util.isInteger(message.futureQuotaValue) && !(message.futureQuotaValue && $util.isInteger(message.futureQuotaValue.low) && $util.isInteger(message.futureQuotaValue.high))) + return "futureQuotaValue: integer|Long expected"; + } return null; }; @@ -16938,6 +17086,40 @@ message.subject = String(object.subject); if (object.description != null) message.description = String(object.description); + if (object.apiService != null) + message.apiService = String(object.apiService); + if (object.quotaMetric != null) + message.quotaMetric = String(object.quotaMetric); + if (object.quotaId != null) + message.quotaId = String(object.quotaId); + if (object.quotaDimensions) { + if (typeof object.quotaDimensions !== "object") + throw TypeError(".google.rpc.QuotaFailure.Violation.quotaDimensions: object expected"); + message.quotaDimensions = {}; + for (var keys = Object.keys(object.quotaDimensions), i = 0; i < keys.length; ++i) { + if (keys[i] === "__proto__") + $util.makeProp(message.quotaDimensions, keys[i]); + message.quotaDimensions[keys[i]] = String(object.quotaDimensions[keys[i]]); + } + } + if (object.quotaValue != null) + if ($util.Long) + (message.quotaValue = $util.Long.fromValue(object.quotaValue)).unsigned = false; + else if (typeof object.quotaValue === "string") + message.quotaValue = parseInt(object.quotaValue, 10); + else if (typeof object.quotaValue === "number") + message.quotaValue = object.quotaValue; + else if (typeof object.quotaValue === "object") + message.quotaValue = new $util.LongBits(object.quotaValue.low >>> 0, object.quotaValue.high >>> 0).toNumber(); + if (object.futureQuotaValue != null) + if ($util.Long) + (message.futureQuotaValue = $util.Long.fromValue(object.futureQuotaValue)).unsigned = false; + else if (typeof object.futureQuotaValue === "string") + message.futureQuotaValue = parseInt(object.futureQuotaValue, 10); + else if (typeof object.futureQuotaValue === "number") + message.futureQuotaValue = object.futureQuotaValue; + else if (typeof object.futureQuotaValue === "object") + message.futureQuotaValue = new $util.LongBits(object.futureQuotaValue.low >>> 0, object.futureQuotaValue.high >>> 0).toNumber(); return message; }; @@ -16954,14 +17136,52 @@ if (!options) options = {}; var object = {}; + if (options.objects || options.defaults) + object.quotaDimensions = {}; if (options.defaults) { object.subject = ""; object.description = ""; + object.apiService = ""; + object.quotaMetric = ""; + object.quotaId = ""; + if ($util.Long) { + var long = new $util.Long(0, 0, false); + object.quotaValue = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else + object.quotaValue = options.longs === String ? "0" : 0; } if (message.subject != null && message.hasOwnProperty("subject")) object.subject = message.subject; if (message.description != null && message.hasOwnProperty("description")) object.description = message.description; + if (message.apiService != null && message.hasOwnProperty("apiService")) + object.apiService = message.apiService; + if (message.quotaMetric != null && message.hasOwnProperty("quotaMetric")) + object.quotaMetric = message.quotaMetric; + if (message.quotaId != null && message.hasOwnProperty("quotaId")) + object.quotaId = message.quotaId; + var keys2; + if (message.quotaDimensions && (keys2 = Object.keys(message.quotaDimensions)).length) { + object.quotaDimensions = {}; + for (var j = 0; j < keys2.length; ++j) { + if (keys2[j] === "__proto__") + $util.makeProp(object.quotaDimensions, keys2[j]); + object.quotaDimensions[keys2[j]] = message.quotaDimensions[keys2[j]]; + } + } + if (message.quotaValue != null && message.hasOwnProperty("quotaValue")) + if (typeof message.quotaValue === "number") + object.quotaValue = options.longs === String ? String(message.quotaValue) : message.quotaValue; + else + object.quotaValue = options.longs === String ? $util.Long.prototype.toString.call(message.quotaValue) : options.longs === Number ? new $util.LongBits(message.quotaValue.low >>> 0, message.quotaValue.high >>> 0).toNumber() : message.quotaValue; + if (message.futureQuotaValue != null && message.hasOwnProperty("futureQuotaValue")) { + if (typeof message.futureQuotaValue === "number") + object.futureQuotaValue = options.longs === String ? String(message.futureQuotaValue) : message.futureQuotaValue; + else + object.futureQuotaValue = options.longs === String ? $util.Long.prototype.toString.call(message.futureQuotaValue) : options.longs === Number ? new $util.LongBits(message.futureQuotaValue.low >>> 0, message.futureQuotaValue.high >>> 0).toNumber() : message.futureQuotaValue; + if (options.oneofs) + object._futureQuotaValue = "futureQuotaValue"; + } return object; }; @@ -17742,6 +17962,8 @@ * @interface IFieldViolation * @property {string|null} [field] FieldViolation field * @property {string|null} [description] FieldViolation description + * @property {string|null} [reason] FieldViolation reason + * @property {google.rpc.ILocalizedMessage|null} [localizedMessage] FieldViolation localizedMessage */ /** @@ -17775,6 +17997,22 @@ */ FieldViolation.prototype.description = ""; + /** + * FieldViolation reason. + * @member {string} reason + * @memberof google.rpc.BadRequest.FieldViolation + * @instance + */ + FieldViolation.prototype.reason = ""; + + /** + * FieldViolation localizedMessage. + * @member {google.rpc.ILocalizedMessage|null|undefined} localizedMessage + * @memberof google.rpc.BadRequest.FieldViolation + * @instance + */ + FieldViolation.prototype.localizedMessage = null; + /** * Creates a new FieldViolation instance using the specified properties. * @function create @@ -17803,6 +18041,10 @@ writer.uint32(/* id 1, wireType 2 =*/10).string(message.field); if (message.description != null && Object.hasOwnProperty.call(message, "description")) writer.uint32(/* id 2, wireType 2 =*/18).string(message.description); + if (message.reason != null && Object.hasOwnProperty.call(message, "reason")) + writer.uint32(/* id 3, wireType 2 =*/26).string(message.reason); + if (message.localizedMessage != null && Object.hasOwnProperty.call(message, "localizedMessage")) + $root.google.rpc.LocalizedMessage.encode(message.localizedMessage, writer.uint32(/* id 4, wireType 2 =*/34).fork()).ldelim(); return writer; }; @@ -17851,6 +18093,14 @@ message.description = reader.string(); break; } + case 3: { + message.reason = reader.string(); + break; + } + case 4: { + message.localizedMessage = $root.google.rpc.LocalizedMessage.decode(reader, reader.uint32(), undefined, long + 1); + break; + } default: reader.skipType(tag & 7, long); break; @@ -17896,6 +18146,14 @@ if (message.description != null && message.hasOwnProperty("description")) if (!$util.isString(message.description)) return "description: string expected"; + if (message.reason != null && message.hasOwnProperty("reason")) + if (!$util.isString(message.reason)) + return "reason: string expected"; + if (message.localizedMessage != null && message.hasOwnProperty("localizedMessage")) { + var error = $root.google.rpc.LocalizedMessage.verify(message.localizedMessage, long + 1); + if (error) + return "localizedMessage." + error; + } return null; }; @@ -17919,6 +18177,13 @@ message.field = String(object.field); if (object.description != null) message.description = String(object.description); + if (object.reason != null) + message.reason = String(object.reason); + if (object.localizedMessage != null) { + if (typeof object.localizedMessage !== "object") + throw TypeError(".google.rpc.BadRequest.FieldViolation.localizedMessage: object expected"); + message.localizedMessage = $root.google.rpc.LocalizedMessage.fromObject(object.localizedMessage, long + 1); + } return message; }; @@ -17938,11 +18203,17 @@ if (options.defaults) { object.field = ""; object.description = ""; + object.reason = ""; + object.localizedMessage = null; } if (message.field != null && message.hasOwnProperty("field")) object.field = message.field; if (message.description != null && message.hasOwnProperty("description")) object.description = message.description; + if (message.reason != null && message.hasOwnProperty("reason")) + object.reason = message.reason; + if (message.localizedMessage != null && message.hasOwnProperty("localizedMessage")) + object.localizedMessage = $root.google.rpc.LocalizedMessage.toObject(message.localizedMessage, options); return object; }; diff --git a/handwritten/spanner/protos/protos.json b/handwritten/spanner/protos/protos.json index 99fcec0aa896..0198eb2563b2 100644 --- a/handwritten/spanner/protos/protos.json +++ b/handwritten/spanner/protos/protos.json @@ -1619,6 +1619,13 @@ }, "nested": { "Violation": { + "oneofs": { + "_futureQuotaValue": { + "oneof": [ + "futureQuotaValue" + ] + } + }, "fields": { "subject": { "type": "string", @@ -1627,6 +1634,34 @@ "description": { "type": "string", "id": 2 + }, + "apiService": { + "type": "string", + "id": 3 + }, + "quotaMetric": { + "type": "string", + "id": 4 + }, + "quotaId": { + "type": "string", + "id": 5 + }, + "quotaDimensions": { + "keyType": "string", + "type": "string", + "id": 6 + }, + "quotaValue": { + "type": "int64", + "id": 7 + }, + "futureQuotaValue": { + "type": "int64", + "id": 8, + "options": { + "proto3_optional": true + } } } } @@ -1677,6 +1712,14 @@ "description": { "type": "string", "id": 2 + }, + "reason": { + "type": "string", + "id": 3 + }, + "localizedMessage": { + "type": "LocalizedMessage", + "id": 4 } } } diff --git a/handwritten/spanner/src/database.ts b/handwritten/spanner/src/database.ts index 145018db064f..0666839b787f 100644 --- a/handwritten/spanner/src/database.ts +++ b/handwritten/spanner/src/database.ts @@ -471,6 +471,7 @@ class Database extends common.GrpcServiceObject { this.formattedName_ = formattedName_; this.instance = instance; + this.spanner = instance.parent as Spanner; const poolOpts = typeof poolOptions === 'object' ? poolOptions : null; this.databaseRole = databaseRole || poolOpts?.databaseRole || null; diff --git a/handwritten/spanner/src/spanner_grpc_config.json b/handwritten/spanner/src/spanner_grpc_config.json index a13e0ecfaaa9..426aa617d5e2 100644 --- a/handwritten/spanner/src/spanner_grpc_config.json +++ b/handwritten/spanner/src/spanner_grpc_config.json @@ -29,67 +29,49 @@ "name": ["/google.spanner.v1.Spanner/ExecuteSql"], "affinity": { "command": "BOUND", - "affinityKey": "session", - "affinityKeyLocation": "METADATA", - "metadataKey": "x-grpc-gcp-affinity-key" + "affinityKey": "session" } }, { "name": ["/google.spanner.v1.Spanner/ExecuteStreamingSql"], "affinity": { "command": "BOUND", - "affinityKey": "session", - "affinityKeyLocation": "METADATA", - "metadataKey": "x-grpc-gcp-affinity-key" + "affinityKey": "session" } }, { "name": ["/google.spanner.v1.Spanner/Read"], "affinity": { "command": "BOUND", - "affinityKey": "session", - "affinityKeyLocation": "METADATA", - "metadataKey": "x-grpc-gcp-affinity-key" + "affinityKey": "session" } }, { "name": ["/google.spanner.v1.Spanner/StreamingRead"], "affinity": { "command": "BOUND", - "affinityKey": "session", - "affinityKeyLocation": "METADATA", - "metadataKey": "x-grpc-gcp-affinity-key" + "affinityKey": "session" } }, { "name": ["/google.spanner.v1.Spanner/BeginTransaction"], "affinity": { "command": "BOUND", - "affinityKey": "session", - "affinityKeyLocation": "METADATA", - "metadataKey": "x-grpc-gcp-affinity-key" + "affinityKey": "session" } }, { "name": ["/google.spanner.v1.Spanner/Commit"], "affinity": { "command": "BOUND", - "affinityKey": "session", - "affinityKeyLocation": "METADATA", - "metadataKey": "x-grpc-gcp-affinity-key", - "unbindKeyLocation": "METADATA", - "unbindMetadataKey": "x-grpc-gcp-unbind" + "affinityKey": "session" } }, { "name": ["/google.spanner.v1.Spanner/Rollback"], "affinity": { "command": "BOUND", - "affinityKey": "session", - "affinityKeyLocation": "METADATA", - "metadataKey": "x-grpc-gcp-affinity-key", - "unbindKeyLocation": "METADATA", - "unbindMetadataKey": "x-grpc-gcp-unbind" + "affinityKey": "session" } }, { diff --git a/handwritten/spanner/src/transaction.ts b/handwritten/spanner/src/transaction.ts index 91c467c04a22..1a81462917c6 100644 --- a/handwritten/spanner/src/transaction.ts +++ b/handwritten/spanner/src/transaction.ts @@ -387,23 +387,19 @@ export class Snapshot extends EventEmitter { if (session.metadata && session.metadata.multiplexed) { this._affinityKey = uuid.v4(); } - const getMetadataHeaderName = (rpcMethodName: string): string => { - const method = - rpcMethodName.charAt(0).toUpperCase() + rpcMethodName.slice(1); - const fullRpcPath = `/google.spanner.v1.Spanner/${method}`; - - const affinity = methodToAffinityMap.get(fullRpcPath); - return affinity?.metadataKey || 'x-grpc-gcp-affinity-key'; - }; - this.request = (config: any, callback: Function) => { if (this._affinityKey) { - const headerName = getMetadataHeaderName(config.method); config = { ...config, - headers: { - ...(config.headers || {}), - [headerName]: this._affinityKey, + gaxOpts: { + ...(config.gaxOpts || {}), + otherArgs: { + ...(config.gaxOpts?.otherArgs || {}), + options: { + ...(config.gaxOpts?.otherArgs?.options || {}), + affinityKey: this._affinityKey, + }, + }, }, }; } @@ -412,12 +408,17 @@ export class Snapshot extends EventEmitter { this.requestStream = (config: any) => { if (this._affinityKey) { - const headerName = getMetadataHeaderName(config.method); config = { ...config, - headers: { - ...(config.headers || {}), - [headerName]: this._affinityKey, + gaxOpts: { + ...(config.gaxOpts || {}), + otherArgs: { + ...(config.gaxOpts?.otherArgs || {}), + options: { + ...(config.gaxOpts?.otherArgs?.options || {}), + affinityKey: this._affinityKey, + }, + }, }, }; } @@ -1087,6 +1088,24 @@ export class Snapshot extends EventEmitter { this.ended = true; process.nextTick(() => this.emit('end')); + + if (this._affinityKey) { + const database = this.session.parent as Database; + const spanner = database.spanner; + const client = spanner.clients_.get('SpannerClient') as any; + if (client && client.spannerStub) { + client.spannerStub + .then((stub: any) => { + if (stub && typeof stub.getChannel === 'function') { + const channel = stub.getChannel(); + if (channel && typeof channel.unbind === 'function') { + channel.unbind(this._affinityKey); + } + } + }) + .catch(() => {}); + } + } } /** @@ -2509,31 +2528,30 @@ export class Transaction extends Dml { addLeaderAwareRoutingHeader(headers); } - // Create a copy to avoid leaking the unbind header to the global commonHeaders_. - const requestHeaders = Object.assign({}, headers); + span.addEvent('Starting Commit'); - // Signal to grpc-gcp to unbind the affinity key and clean up memory - // since this transaction is now complete. + const database = this.session.parent as Database; + let newGaxOpts = gaxOpts; if (this._affinityKey) { - const affinity = methodToAffinityMap.get( - '/google.spanner.v1.Spanner/Commit', - ); - const unbindHeaderName = - affinity?.unbindMetadataKey || 'x-grpc-gcp-unbind'; - requestHeaders[unbindHeaderName] = 'true'; + newGaxOpts = Object.assign({}, gaxOpts, { + otherArgs: { + ...((gaxOpts as any)?.otherArgs || {}), + options: { + ...((gaxOpts as any)?.otherArgs?.options || {}), + unbind: true, + }, + }, + }); } - span.addEvent('Starting Commit'); - - const database = this.session.parent as Database; this.request( { client: 'SpannerClient', method: 'commit', reqOpts, - gaxOpts: gaxOpts, + gaxOpts: newGaxOpts, headers: injectRequestIDIntoHeaders( - requestHeaders, + headers, this.session, nextNthRequest(database), 1, @@ -2889,18 +2907,17 @@ export class Transaction extends Dml { addLeaderAwareRoutingHeader(headers); } - // Create a copy to avoid leaking the unbind header to the global commonHeaders_. - const requestHeaders = Object.assign({}, headers); - - // Signal to grpc-gcp to unbind the affinity key and clean up memory - // since this transaction is now complete. + let newGaxOpts = gaxOpts; if (this._affinityKey) { - const affinity = methodToAffinityMap.get( - '/google.spanner.v1.Spanner/Rollback', - ); - const unbindHeaderName = - affinity?.unbindMetadataKey || 'x-grpc-gcp-unbind'; - requestHeaders[unbindHeaderName] = 'true'; + newGaxOpts = Object.assign({}, gaxOpts, { + otherArgs: { + ...((gaxOpts as any)?.otherArgs || {}), + options: { + ...((gaxOpts as any)?.otherArgs?.options || {}), + unbind: true, + }, + }, + }); } this.request( @@ -2908,8 +2925,8 @@ export class Transaction extends Dml { client: 'SpannerClient', method: 'rollback', reqOpts, - gaxOpts, - headers: requestHeaders, + gaxOpts: newGaxOpts, + headers: headers, }, (err: null | ServiceError) => { if (err) { From 906a0263a3478aaeb7723416cf4ab7c32dbeeb01 Mon Sep 17 00:00:00 2001 From: Owl Bot Date: Fri, 8 May 2026 07:30:54 +0000 Subject: [PATCH 4/4] =?UTF-8?q?=F0=9F=A6=89=20Updates=20from=20OwlBot=20po?= =?UTF-8?q?st-processor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md --- handwritten/spanner/protos/protos.d.ts | 48 ----- handwritten/spanner/protos/protos.js | 273 +------------------------ handwritten/spanner/protos/protos.json | 43 ---- 3 files changed, 1 insertion(+), 363 deletions(-) diff --git a/handwritten/spanner/protos/protos.d.ts b/handwritten/spanner/protos/protos.d.ts index 9bc6110e43e7..2beea4b0984b 100644 --- a/handwritten/spanner/protos/protos.d.ts +++ b/handwritten/spanner/protos/protos.d.ts @@ -5655,24 +5655,6 @@ export namespace google { /** Violation description */ description?: (string|null); - - /** Violation apiService */ - apiService?: (string|null); - - /** Violation quotaMetric */ - quotaMetric?: (string|null); - - /** Violation quotaId */ - quotaId?: (string|null); - - /** Violation quotaDimensions */ - quotaDimensions?: ({ [k: string]: string }|null); - - /** Violation quotaValue */ - quotaValue?: (number|Long|string|null); - - /** Violation futureQuotaValue */ - futureQuotaValue?: (number|Long|string|null); } /** Represents a Violation. */ @@ -5690,24 +5672,6 @@ export namespace google { /** Violation description. */ public description: string; - /** Violation apiService. */ - public apiService: string; - - /** Violation quotaMetric. */ - public quotaMetric: string; - - /** Violation quotaId. */ - public quotaId: string; - - /** Violation quotaDimensions. */ - public quotaDimensions: { [k: string]: string }; - - /** Violation quotaValue. */ - public quotaValue: (number|Long|string); - - /** Violation futureQuotaValue. */ - public futureQuotaValue?: (number|Long|string|null); - /** * Creates a new Violation instance using the specified properties. * @param [properties] Properties to set @@ -6103,12 +6067,6 @@ export namespace google { /** FieldViolation description */ description?: (string|null); - - /** FieldViolation reason */ - reason?: (string|null); - - /** FieldViolation localizedMessage */ - localizedMessage?: (google.rpc.ILocalizedMessage|null); } /** Represents a FieldViolation. */ @@ -6126,12 +6084,6 @@ export namespace google { /** FieldViolation description. */ public description: string; - /** FieldViolation reason. */ - public reason: string; - - /** FieldViolation localizedMessage. */ - public localizedMessage?: (google.rpc.ILocalizedMessage|null); - /** * Creates a new FieldViolation instance using the specified properties. * @param [properties] Properties to set diff --git a/handwritten/spanner/protos/protos.js b/handwritten/spanner/protos/protos.js index b2caff00cdbb..1007227b2abe 100644 --- a/handwritten/spanner/protos/protos.js +++ b/handwritten/spanner/protos/protos.js @@ -16761,12 +16761,6 @@ * @interface IViolation * @property {string|null} [subject] Violation subject * @property {string|null} [description] Violation description - * @property {string|null} [apiService] Violation apiService - * @property {string|null} [quotaMetric] Violation quotaMetric - * @property {string|null} [quotaId] Violation quotaId - * @property {Object.|null} [quotaDimensions] Violation quotaDimensions - * @property {number|Long|null} [quotaValue] Violation quotaValue - * @property {number|Long|null} [futureQuotaValue] Violation futureQuotaValue */ /** @@ -16778,7 +16772,6 @@ * @param {google.rpc.QuotaFailure.IViolation=} [properties] Properties to set */ function Violation(properties) { - this.quotaDimensions = {}; if (properties) for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) if (properties[keys[i]] != null && keys[i] !== "__proto__") @@ -16801,63 +16794,6 @@ */ Violation.prototype.description = ""; - /** - * Violation apiService. - * @member {string} apiService - * @memberof google.rpc.QuotaFailure.Violation - * @instance - */ - Violation.prototype.apiService = ""; - - /** - * Violation quotaMetric. - * @member {string} quotaMetric - * @memberof google.rpc.QuotaFailure.Violation - * @instance - */ - Violation.prototype.quotaMetric = ""; - - /** - * Violation quotaId. - * @member {string} quotaId - * @memberof google.rpc.QuotaFailure.Violation - * @instance - */ - Violation.prototype.quotaId = ""; - - /** - * Violation quotaDimensions. - * @member {Object.} quotaDimensions - * @memberof google.rpc.QuotaFailure.Violation - * @instance - */ - Violation.prototype.quotaDimensions = $util.emptyObject; - - /** - * Violation quotaValue. - * @member {number|Long} quotaValue - * @memberof google.rpc.QuotaFailure.Violation - * @instance - */ - Violation.prototype.quotaValue = $util.Long ? $util.Long.fromBits(0,0,false) : 0; - - /** - * Violation futureQuotaValue. - * @member {number|Long|null|undefined} futureQuotaValue - * @memberof google.rpc.QuotaFailure.Violation - * @instance - */ - Violation.prototype.futureQuotaValue = null; - - // OneOf field names bound to virtual getters and setters - var $oneOfFields; - - // Virtual OneOf for proto3 optional field - Object.defineProperty(Violation.prototype, "_futureQuotaValue", { - get: $util.oneOfGetter($oneOfFields = ["futureQuotaValue"]), - set: $util.oneOfSetter($oneOfFields) - }); - /** * Creates a new Violation instance using the specified properties. * @function create @@ -16886,19 +16822,6 @@ writer.uint32(/* id 1, wireType 2 =*/10).string(message.subject); if (message.description != null && Object.hasOwnProperty.call(message, "description")) writer.uint32(/* id 2, wireType 2 =*/18).string(message.description); - if (message.apiService != null && Object.hasOwnProperty.call(message, "apiService")) - writer.uint32(/* id 3, wireType 2 =*/26).string(message.apiService); - if (message.quotaMetric != null && Object.hasOwnProperty.call(message, "quotaMetric")) - writer.uint32(/* id 4, wireType 2 =*/34).string(message.quotaMetric); - if (message.quotaId != null && Object.hasOwnProperty.call(message, "quotaId")) - writer.uint32(/* id 5, wireType 2 =*/42).string(message.quotaId); - if (message.quotaDimensions != null && Object.hasOwnProperty.call(message, "quotaDimensions")) - for (var keys = Object.keys(message.quotaDimensions), i = 0; i < keys.length; ++i) - writer.uint32(/* id 6, wireType 2 =*/50).fork().uint32(/* id 1, wireType 2 =*/10).string(keys[i]).uint32(/* id 2, wireType 2 =*/18).string(message.quotaDimensions[keys[i]]).ldelim(); - if (message.quotaValue != null && Object.hasOwnProperty.call(message, "quotaValue")) - writer.uint32(/* id 7, wireType 0 =*/56).int64(message.quotaValue); - if (message.futureQuotaValue != null && Object.hasOwnProperty.call(message, "futureQuotaValue")) - writer.uint32(/* id 8, wireType 0 =*/64).int64(message.futureQuotaValue); return writer; }; @@ -16933,7 +16856,7 @@ long = 0; if (long > $Reader.recursionLimit) throw Error("maximum nesting depth exceeded"); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.rpc.QuotaFailure.Violation(), key, value; + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.rpc.QuotaFailure.Violation(); while (reader.pos < end) { var tag = reader.uint32(); if (tag === error) @@ -16947,51 +16870,6 @@ message.description = reader.string(); break; } - case 3: { - message.apiService = reader.string(); - break; - } - case 4: { - message.quotaMetric = reader.string(); - break; - } - case 5: { - message.quotaId = reader.string(); - break; - } - case 6: { - if (message.quotaDimensions === $util.emptyObject) - message.quotaDimensions = {}; - var end2 = reader.uint32() + reader.pos; - key = ""; - value = ""; - while (reader.pos < end2) { - var tag2 = reader.uint32(); - switch (tag2 >>> 3) { - case 1: - key = reader.string(); - break; - case 2: - value = reader.string(); - break; - default: - reader.skipType(tag2 & 7, long); - break; - } - } - if (key === "__proto__") - $util.makeProp(message.quotaDimensions, key); - message.quotaDimensions[key] = value; - break; - } - case 7: { - message.quotaValue = reader.int64(); - break; - } - case 8: { - message.futureQuotaValue = reader.int64(); - break; - } default: reader.skipType(tag & 7, long); break; @@ -17031,38 +16909,12 @@ long = 0; if (long > $util.recursionLimit) return "maximum nesting depth exceeded"; - var properties = {}; if (message.subject != null && message.hasOwnProperty("subject")) if (!$util.isString(message.subject)) return "subject: string expected"; if (message.description != null && message.hasOwnProperty("description")) if (!$util.isString(message.description)) return "description: string expected"; - if (message.apiService != null && message.hasOwnProperty("apiService")) - if (!$util.isString(message.apiService)) - return "apiService: string expected"; - if (message.quotaMetric != null && message.hasOwnProperty("quotaMetric")) - if (!$util.isString(message.quotaMetric)) - return "quotaMetric: string expected"; - if (message.quotaId != null && message.hasOwnProperty("quotaId")) - if (!$util.isString(message.quotaId)) - return "quotaId: string expected"; - if (message.quotaDimensions != null && message.hasOwnProperty("quotaDimensions")) { - if (!$util.isObject(message.quotaDimensions)) - return "quotaDimensions: object expected"; - var key = Object.keys(message.quotaDimensions); - for (var i = 0; i < key.length; ++i) - if (!$util.isString(message.quotaDimensions[key[i]])) - return "quotaDimensions: string{k:string} expected"; - } - if (message.quotaValue != null && message.hasOwnProperty("quotaValue")) - if (!$util.isInteger(message.quotaValue) && !(message.quotaValue && $util.isInteger(message.quotaValue.low) && $util.isInteger(message.quotaValue.high))) - return "quotaValue: integer|Long expected"; - if (message.futureQuotaValue != null && message.hasOwnProperty("futureQuotaValue")) { - properties._futureQuotaValue = 1; - if (!$util.isInteger(message.futureQuotaValue) && !(message.futureQuotaValue && $util.isInteger(message.futureQuotaValue.low) && $util.isInteger(message.futureQuotaValue.high))) - return "futureQuotaValue: integer|Long expected"; - } return null; }; @@ -17086,40 +16938,6 @@ message.subject = String(object.subject); if (object.description != null) message.description = String(object.description); - if (object.apiService != null) - message.apiService = String(object.apiService); - if (object.quotaMetric != null) - message.quotaMetric = String(object.quotaMetric); - if (object.quotaId != null) - message.quotaId = String(object.quotaId); - if (object.quotaDimensions) { - if (typeof object.quotaDimensions !== "object") - throw TypeError(".google.rpc.QuotaFailure.Violation.quotaDimensions: object expected"); - message.quotaDimensions = {}; - for (var keys = Object.keys(object.quotaDimensions), i = 0; i < keys.length; ++i) { - if (keys[i] === "__proto__") - $util.makeProp(message.quotaDimensions, keys[i]); - message.quotaDimensions[keys[i]] = String(object.quotaDimensions[keys[i]]); - } - } - if (object.quotaValue != null) - if ($util.Long) - (message.quotaValue = $util.Long.fromValue(object.quotaValue)).unsigned = false; - else if (typeof object.quotaValue === "string") - message.quotaValue = parseInt(object.quotaValue, 10); - else if (typeof object.quotaValue === "number") - message.quotaValue = object.quotaValue; - else if (typeof object.quotaValue === "object") - message.quotaValue = new $util.LongBits(object.quotaValue.low >>> 0, object.quotaValue.high >>> 0).toNumber(); - if (object.futureQuotaValue != null) - if ($util.Long) - (message.futureQuotaValue = $util.Long.fromValue(object.futureQuotaValue)).unsigned = false; - else if (typeof object.futureQuotaValue === "string") - message.futureQuotaValue = parseInt(object.futureQuotaValue, 10); - else if (typeof object.futureQuotaValue === "number") - message.futureQuotaValue = object.futureQuotaValue; - else if (typeof object.futureQuotaValue === "object") - message.futureQuotaValue = new $util.LongBits(object.futureQuotaValue.low >>> 0, object.futureQuotaValue.high >>> 0).toNumber(); return message; }; @@ -17136,52 +16954,14 @@ if (!options) options = {}; var object = {}; - if (options.objects || options.defaults) - object.quotaDimensions = {}; if (options.defaults) { object.subject = ""; object.description = ""; - object.apiService = ""; - object.quotaMetric = ""; - object.quotaId = ""; - if ($util.Long) { - var long = new $util.Long(0, 0, false); - object.quotaValue = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; - } else - object.quotaValue = options.longs === String ? "0" : 0; } if (message.subject != null && message.hasOwnProperty("subject")) object.subject = message.subject; if (message.description != null && message.hasOwnProperty("description")) object.description = message.description; - if (message.apiService != null && message.hasOwnProperty("apiService")) - object.apiService = message.apiService; - if (message.quotaMetric != null && message.hasOwnProperty("quotaMetric")) - object.quotaMetric = message.quotaMetric; - if (message.quotaId != null && message.hasOwnProperty("quotaId")) - object.quotaId = message.quotaId; - var keys2; - if (message.quotaDimensions && (keys2 = Object.keys(message.quotaDimensions)).length) { - object.quotaDimensions = {}; - for (var j = 0; j < keys2.length; ++j) { - if (keys2[j] === "__proto__") - $util.makeProp(object.quotaDimensions, keys2[j]); - object.quotaDimensions[keys2[j]] = message.quotaDimensions[keys2[j]]; - } - } - if (message.quotaValue != null && message.hasOwnProperty("quotaValue")) - if (typeof message.quotaValue === "number") - object.quotaValue = options.longs === String ? String(message.quotaValue) : message.quotaValue; - else - object.quotaValue = options.longs === String ? $util.Long.prototype.toString.call(message.quotaValue) : options.longs === Number ? new $util.LongBits(message.quotaValue.low >>> 0, message.quotaValue.high >>> 0).toNumber() : message.quotaValue; - if (message.futureQuotaValue != null && message.hasOwnProperty("futureQuotaValue")) { - if (typeof message.futureQuotaValue === "number") - object.futureQuotaValue = options.longs === String ? String(message.futureQuotaValue) : message.futureQuotaValue; - else - object.futureQuotaValue = options.longs === String ? $util.Long.prototype.toString.call(message.futureQuotaValue) : options.longs === Number ? new $util.LongBits(message.futureQuotaValue.low >>> 0, message.futureQuotaValue.high >>> 0).toNumber() : message.futureQuotaValue; - if (options.oneofs) - object._futureQuotaValue = "futureQuotaValue"; - } return object; }; @@ -17962,8 +17742,6 @@ * @interface IFieldViolation * @property {string|null} [field] FieldViolation field * @property {string|null} [description] FieldViolation description - * @property {string|null} [reason] FieldViolation reason - * @property {google.rpc.ILocalizedMessage|null} [localizedMessage] FieldViolation localizedMessage */ /** @@ -17997,22 +17775,6 @@ */ FieldViolation.prototype.description = ""; - /** - * FieldViolation reason. - * @member {string} reason - * @memberof google.rpc.BadRequest.FieldViolation - * @instance - */ - FieldViolation.prototype.reason = ""; - - /** - * FieldViolation localizedMessage. - * @member {google.rpc.ILocalizedMessage|null|undefined} localizedMessage - * @memberof google.rpc.BadRequest.FieldViolation - * @instance - */ - FieldViolation.prototype.localizedMessage = null; - /** * Creates a new FieldViolation instance using the specified properties. * @function create @@ -18041,10 +17803,6 @@ writer.uint32(/* id 1, wireType 2 =*/10).string(message.field); if (message.description != null && Object.hasOwnProperty.call(message, "description")) writer.uint32(/* id 2, wireType 2 =*/18).string(message.description); - if (message.reason != null && Object.hasOwnProperty.call(message, "reason")) - writer.uint32(/* id 3, wireType 2 =*/26).string(message.reason); - if (message.localizedMessage != null && Object.hasOwnProperty.call(message, "localizedMessage")) - $root.google.rpc.LocalizedMessage.encode(message.localizedMessage, writer.uint32(/* id 4, wireType 2 =*/34).fork()).ldelim(); return writer; }; @@ -18093,14 +17851,6 @@ message.description = reader.string(); break; } - case 3: { - message.reason = reader.string(); - break; - } - case 4: { - message.localizedMessage = $root.google.rpc.LocalizedMessage.decode(reader, reader.uint32(), undefined, long + 1); - break; - } default: reader.skipType(tag & 7, long); break; @@ -18146,14 +17896,6 @@ if (message.description != null && message.hasOwnProperty("description")) if (!$util.isString(message.description)) return "description: string expected"; - if (message.reason != null && message.hasOwnProperty("reason")) - if (!$util.isString(message.reason)) - return "reason: string expected"; - if (message.localizedMessage != null && message.hasOwnProperty("localizedMessage")) { - var error = $root.google.rpc.LocalizedMessage.verify(message.localizedMessage, long + 1); - if (error) - return "localizedMessage." + error; - } return null; }; @@ -18177,13 +17919,6 @@ message.field = String(object.field); if (object.description != null) message.description = String(object.description); - if (object.reason != null) - message.reason = String(object.reason); - if (object.localizedMessage != null) { - if (typeof object.localizedMessage !== "object") - throw TypeError(".google.rpc.BadRequest.FieldViolation.localizedMessage: object expected"); - message.localizedMessage = $root.google.rpc.LocalizedMessage.fromObject(object.localizedMessage, long + 1); - } return message; }; @@ -18203,17 +17938,11 @@ if (options.defaults) { object.field = ""; object.description = ""; - object.reason = ""; - object.localizedMessage = null; } if (message.field != null && message.hasOwnProperty("field")) object.field = message.field; if (message.description != null && message.hasOwnProperty("description")) object.description = message.description; - if (message.reason != null && message.hasOwnProperty("reason")) - object.reason = message.reason; - if (message.localizedMessage != null && message.hasOwnProperty("localizedMessage")) - object.localizedMessage = $root.google.rpc.LocalizedMessage.toObject(message.localizedMessage, options); return object; }; diff --git a/handwritten/spanner/protos/protos.json b/handwritten/spanner/protos/protos.json index 0198eb2563b2..99fcec0aa896 100644 --- a/handwritten/spanner/protos/protos.json +++ b/handwritten/spanner/protos/protos.json @@ -1619,13 +1619,6 @@ }, "nested": { "Violation": { - "oneofs": { - "_futureQuotaValue": { - "oneof": [ - "futureQuotaValue" - ] - } - }, "fields": { "subject": { "type": "string", @@ -1634,34 +1627,6 @@ "description": { "type": "string", "id": 2 - }, - "apiService": { - "type": "string", - "id": 3 - }, - "quotaMetric": { - "type": "string", - "id": 4 - }, - "quotaId": { - "type": "string", - "id": 5 - }, - "quotaDimensions": { - "keyType": "string", - "type": "string", - "id": 6 - }, - "quotaValue": { - "type": "int64", - "id": 7 - }, - "futureQuotaValue": { - "type": "int64", - "id": 8, - "options": { - "proto3_optional": true - } } } } @@ -1712,14 +1677,6 @@ "description": { "type": "string", "id": 2 - }, - "reason": { - "type": "string", - "id": 3 - }, - "localizedMessage": { - "type": "LocalizedMessage", - "id": 4 } } }