google-cloud-spanner 2.19.1 → 2.20.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 +6 -0
- data/lib/google/cloud/spanner/client.rb +9 -4
- data/lib/google/cloud/spanner/lar_headers.rb +100 -0
- data/lib/google/cloud/spanner/service.rb +54 -21
- data/lib/google/cloud/spanner/session.rb +11 -6
- data/lib/google/cloud/spanner/transaction.rb +9 -3
- data/lib/google/cloud/spanner/version.rb +1 -1
- data/lib/google/cloud/spanner.rb +6 -2
- metadata +3 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: bb4b25a92a8c1064831ca356c5504c6114fde3efbda272ff4553dda86bf1a902
         | 
| 4 | 
            +
              data.tar.gz: 66c330a8e53e6e9ffac6735008586c5ad0027629e71f66f8401e2c58ea4394a9
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 6f296b9eb6930cad1c242402bc2dc8cb0ac47eaef1761acb598f35aaa63779d33192c0d92d5df852fe711ff7ad54c7b0f7695d2a0055b55a7dd05b80aa3d855d
         | 
| 7 | 
            +
              data.tar.gz: e3de3a8796cbcade1973cd2b4d3d5a632c6677173f24cd1ba0b9dfa7d8355e93122d9d0c0c3926d442271d057517adf9125cfb61e2f896faa54ec324d590aed4
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    
| @@ -24,6 +24,7 @@ require "google/cloud/spanner/range" | |
| 24 24 | 
             
            require "google/cloud/spanner/column_value"
         | 
| 25 25 | 
             
            require "google/cloud/spanner/convert"
         | 
| 26 26 | 
             
            require "google/cloud/spanner/commit_response"
         | 
| 27 | 
            +
            require "google/cloud/spanner/lar_headers"
         | 
| 27 28 |  | 
| 28 29 | 
             
            module Google
         | 
| 29 30 | 
             
              module Cloud
         | 
| @@ -466,12 +467,14 @@ module Google | |
| 466 467 | 
             
                      request_options = Convert.to_request_options request_options,
         | 
| 467 468 | 
             
                                                                   tag_type: :request_tag
         | 
| 468 469 | 
             
                      single_use_tx = single_use_transaction single_use
         | 
| 470 | 
            +
                      route_to_leader = LARHeaders.execute_query true
         | 
| 469 471 | 
             
                      results = nil
         | 
| 470 472 | 
             
                      @pool.with_session do |session|
         | 
| 471 473 | 
             
                        results = session.execute_query \
         | 
| 472 474 | 
             
                          sql, params: params, types: types, transaction: single_use_tx,
         | 
| 473 475 | 
             
                          query_options: query_options, request_options: request_options,
         | 
| 474 | 
            -
                          call_options: call_options, directed_read_options: (directed_read_options || @directed_read_options)
         | 
| 476 | 
            +
                          call_options: call_options, directed_read_options: (directed_read_options || @directed_read_options),
         | 
| 477 | 
            +
                          route_to_leader: route_to_leader
         | 
| 475 478 | 
             
                      end
         | 
| 476 479 | 
             
                      results
         | 
| 477 480 | 
             
                    end
         | 
| @@ -735,14 +738,14 @@ module Google | |
| 735 738 | 
             
                      params, types = Convert.to_input_params_and_types params, types
         | 
| 736 739 | 
             
                      request_options = Convert.to_request_options request_options,
         | 
| 737 740 | 
             
                                                                   tag_type: :request_tag
         | 
| 738 | 
            -
             | 
| 741 | 
            +
                      route_to_leader = LARHeaders.partition_query
         | 
| 739 742 | 
             
                      results = nil
         | 
| 740 743 | 
             
                      @pool.with_session do |session|
         | 
| 741 744 | 
             
                        results = session.execute_query \
         | 
| 742 745 | 
             
                          sql, params: params, types: types,
         | 
| 743 746 | 
             
                          transaction: pdml_transaction(session),
         | 
| 744 747 | 
             
                          query_options: query_options, request_options: request_options,
         | 
| 745 | 
            -
                          call_options: call_options
         | 
| 748 | 
            +
                          call_options: call_options, route_to_leader: route_to_leader
         | 
| 746 749 | 
             
                      end
         | 
| 747 750 | 
             
                      # Stream all PartialResultSet to get ResultSetStats
         | 
| 748 751 | 
             
                      results.rows.to_a
         | 
| @@ -956,6 +959,7 @@ module Google | |
| 956 959 | 
             
                      columns = Array(columns).map(&:to_s)
         | 
| 957 960 | 
             
                      keys = Convert.to_key_set keys
         | 
| 958 961 | 
             
                      single_use_tx = single_use_transaction single_use
         | 
| 962 | 
            +
                      route_to_leader = LARHeaders.read false
         | 
| 959 963 | 
             
                      request_options = Convert.to_request_options request_options,
         | 
| 960 964 | 
             
                                                                   tag_type: :request_tag
         | 
| 961 965 |  | 
| @@ -966,7 +970,8 @@ module Google | |
| 966 970 | 
             
                                          transaction: single_use_tx,
         | 
| 967 971 | 
             
                                          request_options: request_options,
         | 
| 968 972 | 
             
                                          call_options: call_options,
         | 
| 969 | 
            -
                                          directed_read_options: (directed_read_options || @directed_read_options)
         | 
| 973 | 
            +
                                          directed_read_options: (directed_read_options || @directed_read_options),
         | 
| 974 | 
            +
                                          route_to_leader: route_to_leader
         | 
| 970 975 | 
             
                      end
         | 
| 971 976 | 
             
                      results
         | 
| 972 977 | 
             
                    end
         | 
| @@ -0,0 +1,100 @@ | |
| 1 | 
            +
            # Copyright 2024 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 | 
            +
            module Google
         | 
| 17 | 
            +
              module Cloud
         | 
| 18 | 
            +
                module Spanner
         | 
| 19 | 
            +
                  ##
         | 
| 20 | 
            +
                  # @private Helper module to access header values
         | 
| 21 | 
            +
                  # for Leader Aware Routing (LAR).
         | 
| 22 | 
            +
                  #
         | 
| 23 | 
            +
                  # For a multi-region Cloud Spanner instance, the majority of
         | 
| 24 | 
            +
                  # the write latency is attributed to the network round trip
         | 
| 25 | 
            +
                  # caused by several RPCs between SpanFE and SpanServer. This
         | 
| 26 | 
            +
                  # latency is amplified when the client application is deployed
         | 
| 27 | 
            +
                  # away from the leader region.
         | 
| 28 | 
            +
                  #
         | 
| 29 | 
            +
                  # To decrease the latency, we use LAR to help Google Front End (GFE)
         | 
| 30 | 
            +
                  # or Cloudpath Front End (CFE) to route requests directly to the
         | 
| 31 | 
            +
                  # leader region or the nearest non-leader region.
         | 
| 32 | 
            +
                  #
         | 
| 33 | 
            +
                  # For every RPC, we pass the header `x-goog-spanner-route-to-leader`,
         | 
| 34 | 
            +
                  # whose value is either 'true' or 'false'. Some RPCs (such as admin APIs)
         | 
| 35 | 
            +
                  # don't pass the header since they're deprecated in the handwritten
         | 
| 36 | 
            +
                  # client. Also, users of the client can choose to opt out of the
         | 
| 37 | 
            +
                  # LAR feature, in which case, we don't pass the header.
         | 
| 38 | 
            +
                  #
         | 
| 39 | 
            +
                  # This module lists the header values for different RPCs to be used
         | 
| 40 | 
            +
                  # by the client. These values are expected to be constant. Some RPCs
         | 
| 41 | 
            +
                  # (such as `execute_streaming_sql`) can have different values
         | 
| 42 | 
            +
                  # depending on whether they're run within read-only transactions
         | 
| 43 | 
            +
                  # or read-write transactions.
         | 
| 44 | 
            +
                  #
         | 
| 45 | 
            +
                  module LARHeaders
         | 
| 46 | 
            +
                    class << self
         | 
| 47 | 
            +
                      def begin_transaction is_read_write_tx
         | 
| 48 | 
            +
                        is_read_write_tx ? "true" : "false"
         | 
| 49 | 
            +
                      end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                      def read is_read_write_tx
         | 
| 52 | 
            +
                        is_read_write_tx ? "true" : "false"
         | 
| 53 | 
            +
                      end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                      def execute_query is_read_write_tx
         | 
| 56 | 
            +
                        is_read_write_tx ? "true" : "false"
         | 
| 57 | 
            +
                      end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                      def commit
         | 
| 60 | 
            +
                        "true"
         | 
| 61 | 
            +
                      end
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                      def execute_batch_dml
         | 
| 64 | 
            +
                        "true"
         | 
| 65 | 
            +
                      end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                      def create_session
         | 
| 68 | 
            +
                        "true"
         | 
| 69 | 
            +
                      end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                      def batch_create_sessions
         | 
| 72 | 
            +
                        "true"
         | 
| 73 | 
            +
                      end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                      def delete_session
         | 
| 76 | 
            +
                        "false"
         | 
| 77 | 
            +
                      end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                      # rubocop:disable Naming/AccessorMethodName
         | 
| 80 | 
            +
                      def get_session
         | 
| 81 | 
            +
                        "true"
         | 
| 82 | 
            +
                      end
         | 
| 83 | 
            +
                      # rubocop:enable Naming/AccessorMethodName
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                      def partition_read
         | 
| 86 | 
            +
                        "true"
         | 
| 87 | 
            +
                      end
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                      def partition_query
         | 
| 90 | 
            +
                        "true"
         | 
| 91 | 
            +
                      end
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                      def rollback
         | 
| 94 | 
            +
                        "true"
         | 
| 95 | 
            +
                      end
         | 
| 96 | 
            +
                    end
         | 
| 97 | 
            +
                  end
         | 
| 98 | 
            +
                end
         | 
| 99 | 
            +
              end
         | 
| 100 | 
            +
            end
         | 
| @@ -20,6 +20,7 @@ require "google/cloud/spanner/v1" | |
| 20 20 | 
             
            require "google/cloud/spanner/admin/instance/v1"
         | 
| 21 21 | 
             
            require "google/cloud/spanner/admin/database/v1"
         | 
| 22 22 | 
             
            require "google/cloud/spanner/convert"
         | 
| 23 | 
            +
            require "google/cloud/spanner/lar_headers"
         | 
| 23 24 |  | 
| 24 25 | 
             
            module Google
         | 
| 25 26 | 
             
              module Cloud
         | 
| @@ -35,6 +36,7 @@ module Google | |
| 35 36 | 
             
                    attr_accessor :lib_name
         | 
| 36 37 | 
             
                    attr_accessor :lib_version
         | 
| 37 38 | 
             
                    attr_accessor :quota_project
         | 
| 39 | 
            +
                    attr_accessor :enable_leader_aware_routing
         | 
| 38 40 |  | 
| 39 41 | 
             
                    RST_STREAM_INTERNAL_ERROR = "Received RST_STREAM".freeze
         | 
| 40 42 | 
             
                    EOS_INTERNAL_ERROR = "Received unexpected EOS on DATA frame from server".freeze
         | 
| @@ -42,7 +44,8 @@ module Google | |
| 42 44 | 
             
                    ##
         | 
| 43 45 | 
             
                    # Creates a new Service instance.
         | 
| 44 46 | 
             
                    def initialize project, credentials, quota_project: nil,
         | 
| 45 | 
            -
                                   host: nil, timeout: nil, lib_name: nil, lib_version: nil
         | 
| 47 | 
            +
                                   host: nil, timeout: nil, lib_name: nil, lib_version: nil,
         | 
| 48 | 
            +
                                   enable_leader_aware_routing: nil
         | 
| 46 49 | 
             
                      @project = project
         | 
| 47 50 | 
             
                      @credentials = credentials
         | 
| 48 51 | 
             
                      @quota_project = quota_project || (credentials.quota_project_id if credentials.respond_to? :quota_project_id)
         | 
| @@ -50,6 +53,7 @@ module Google | |
| 50 53 | 
             
                      @timeout = timeout
         | 
| 51 54 | 
             
                      @lib_name = lib_name
         | 
| 52 55 | 
             
                      @lib_version = lib_version
         | 
| 56 | 
            +
                      @enable_leader_aware_routing = enable_leader_aware_routing
         | 
| 53 57 | 
             
                    end
         | 
| 54 58 |  | 
| 55 59 | 
             
                    def channel
         | 
| @@ -290,15 +294,19 @@ module Google | |
| 290 294 | 
             
                    end
         | 
| 291 295 |  | 
| 292 296 | 
             
                    def get_session session_name, call_options: nil
         | 
| 297 | 
            +
                      route_to_leader = LARHeaders.get_session
         | 
| 293 298 | 
             
                      opts = default_options session_name: session_name,
         | 
| 294 | 
            -
                                             call_options: call_options
         | 
| 299 | 
            +
                                             call_options: call_options,
         | 
| 300 | 
            +
                                             route_to_leader: route_to_leader
         | 
| 295 301 | 
             
                      service.get_session({ name: session_name }, opts)
         | 
| 296 302 | 
             
                    end
         | 
| 297 303 |  | 
| 298 304 | 
             
                    def create_session database_name, labels: nil,
         | 
| 299 305 | 
             
                                       call_options: nil, database_role: nil
         | 
| 306 | 
            +
                      route_to_leader = LARHeaders.create_session
         | 
| 300 307 | 
             
                      opts = default_options session_name: database_name,
         | 
| 301 | 
            -
                                             call_options: call_options
         | 
| 308 | 
            +
                                             call_options: call_options,
         | 
| 309 | 
            +
                                             route_to_leader: route_to_leader
         | 
| 302 310 | 
             
                      session = V1::Session.new labels: labels, creator_role: database_role if labels || database_role
         | 
| 303 311 | 
             
                      service.create_session(
         | 
| 304 312 | 
             
                        { database: database_name, session: session }, opts
         | 
| @@ -307,8 +315,10 @@ module Google | |
| 307 315 |  | 
| 308 316 | 
             
                    def batch_create_sessions database_name, session_count, labels: nil,
         | 
| 309 317 | 
             
                                              call_options: nil, database_role: nil
         | 
| 318 | 
            +
                      route_to_leader = LARHeaders.batch_create_sessions
         | 
| 310 319 | 
             
                      opts = default_options session_name: database_name,
         | 
| 311 | 
            -
                                             call_options: call_options
         | 
| 320 | 
            +
                                             call_options: call_options,
         | 
| 321 | 
            +
                                             route_to_leader: route_to_leader
         | 
| 312 322 | 
             
                      session = V1::Session.new labels: labels, creator_role: database_role if labels || database_role
         | 
| 313 323 | 
             
                      # The response may have fewer sessions than requested in the RPC.
         | 
| 314 324 | 
             
                      request = {
         | 
| @@ -320,8 +330,10 @@ module Google | |
| 320 330 | 
             
                    end
         | 
| 321 331 |  | 
| 322 332 | 
             
                    def delete_session session_name, call_options: nil
         | 
| 333 | 
            +
                      route_to_leader = LARHeaders.delete_session
         | 
| 323 334 | 
             
                      opts = default_options session_name: session_name,
         | 
| 324 | 
            -
                                             call_options: call_options
         | 
| 335 | 
            +
                                             call_options: call_options,
         | 
| 336 | 
            +
                                             route_to_leader: route_to_leader
         | 
| 325 337 | 
             
                      service.delete_session({ name: session_name }, opts)
         | 
| 326 338 | 
             
                    end
         | 
| 327 339 |  | 
| @@ -330,9 +342,11 @@ module Google | |
| 330 342 | 
             
                                              partition_token: nil, seqno: nil,
         | 
| 331 343 | 
             
                                              query_options: nil, request_options: nil,
         | 
| 332 344 | 
             
                                              call_options: nil, data_boost_enabled: nil,
         | 
| 333 | 
            -
                                              directed_read_options: nil
         | 
| 345 | 
            +
                                              directed_read_options: nil,
         | 
| 346 | 
            +
                                              route_to_leader: nil
         | 
| 334 347 | 
             
                      opts = default_options session_name: session_name,
         | 
| 335 | 
            -
                                             call_options: call_options
         | 
| 348 | 
            +
                                             call_options: call_options,
         | 
| 349 | 
            +
                                             route_to_leader: route_to_leader
         | 
| 336 350 | 
             
                      request =  {
         | 
| 337 351 | 
             
                        session: session_name,
         | 
| 338 352 | 
             
                        sql: sql,
         | 
| @@ -352,8 +366,10 @@ module Google | |
| 352 366 |  | 
| 353 367 | 
             
                    def execute_batch_dml session_name, transaction, statements, seqno,
         | 
| 354 368 | 
             
                                          request_options: nil, call_options: nil
         | 
| 369 | 
            +
                      route_to_leader = LARHeaders.execute_batch_dml
         | 
| 355 370 | 
             
                      opts = default_options session_name: session_name,
         | 
| 356 | 
            -
                                             call_options: call_options
         | 
| 371 | 
            +
                                             call_options: call_options,
         | 
| 372 | 
            +
                                             route_to_leader: route_to_leader
         | 
| 357 373 | 
             
                      statements = statements.map(&:to_grpc)
         | 
| 358 374 | 
             
                      request = {
         | 
| 359 375 | 
             
                        session: session_name,
         | 
| @@ -369,9 +385,11 @@ module Google | |
| 369 385 | 
             
                                             index: nil, transaction: nil, limit: nil,
         | 
| 370 386 | 
             
                                             resume_token: nil, partition_token: nil,
         | 
| 371 387 | 
             
                                             request_options: nil, call_options: nil,
         | 
| 372 | 
            -
                                             data_boost_enabled: nil, directed_read_options: nil
         | 
| 388 | 
            +
                                             data_boost_enabled: nil, directed_read_options: nil,
         | 
| 389 | 
            +
                                             route_to_leader: nil
         | 
| 373 390 | 
             
                      opts = default_options session_name: session_name,
         | 
| 374 | 
            -
                                             call_options: call_options
         | 
| 391 | 
            +
                                             call_options: call_options,
         | 
| 392 | 
            +
                                             route_to_leader: route_to_leader
         | 
| 375 393 | 
             
                      request = {
         | 
| 376 394 | 
             
                        session: session_name, table: table_name, columns: columns,
         | 
| 377 395 | 
             
                        key_set: keys, transaction: transaction, index: index,
         | 
| @@ -388,9 +406,10 @@ module Google | |
| 388 406 | 
             
                                       max_partitions: nil, call_options: nil
         | 
| 389 407 | 
             
                      partition_opts = partition_options partition_size_bytes,
         | 
| 390 408 | 
             
                                                         max_partitions
         | 
| 391 | 
            -
             | 
| 409 | 
            +
                      route_to_leader = LARHeaders.partition_read
         | 
| 392 410 | 
             
                      opts = default_options session_name: session_name,
         | 
| 393 | 
            -
                                             call_options: call_options
         | 
| 411 | 
            +
                                             call_options: call_options,
         | 
| 412 | 
            +
                                             route_to_leader: route_to_leader
         | 
| 394 413 | 
             
                      request = {
         | 
| 395 414 | 
             
                        session: session_name, table: table_name, key_set: keys,
         | 
| 396 415 | 
             
                        transaction: transaction, index: index, columns: columns,
         | 
| @@ -404,9 +423,10 @@ module Google | |
| 404 423 | 
             
                                        max_partitions: nil, call_options: nil
         | 
| 405 424 | 
             
                      partition_opts = partition_options partition_size_bytes,
         | 
| 406 425 | 
             
                                                         max_partitions
         | 
| 407 | 
            -
             | 
| 426 | 
            +
                      route_to_leader = LARHeaders.partition_query
         | 
| 408 427 | 
             
                      opts = default_options session_name: session_name,
         | 
| 409 | 
            -
                                             call_options: call_options
         | 
| 428 | 
            +
                                             call_options: call_options,
         | 
| 429 | 
            +
                                             route_to_leader: route_to_leader
         | 
| 410 430 | 
             
                      request = {
         | 
| 411 431 | 
             
                        session: session_name, sql: sql, transaction: transaction,
         | 
| 412 432 | 
             
                        params: params, param_types: types,
         | 
| @@ -417,6 +437,7 @@ module Google | |
| 417 437 |  | 
| 418 438 | 
             
                    def commit session_name, mutations = [], transaction_id: nil,
         | 
| 419 439 | 
             
                               commit_options: nil, request_options: nil, call_options: nil
         | 
| 440 | 
            +
                      route_to_leader = LARHeaders.commit
         | 
| 420 441 | 
             
                      tx_opts = nil
         | 
| 421 442 | 
             
                      if transaction_id.nil?
         | 
| 422 443 | 
             
                        tx_opts = V1::TransactionOptions.new(
         | 
| @@ -424,7 +445,8 @@ module Google | |
| 424 445 | 
             
                        )
         | 
| 425 446 | 
             
                      end
         | 
| 426 447 | 
             
                      opts = default_options session_name: session_name,
         | 
| 427 | 
            -
                                             call_options: call_options
         | 
| 448 | 
            +
                                             call_options: call_options,
         | 
| 449 | 
            +
                                             route_to_leader: route_to_leader
         | 
| 428 450 | 
             
                      request = {
         | 
| 429 451 | 
             
                        session: session_name, transaction_id: transaction_id,
         | 
| 430 452 | 
             
                        single_use_transaction: tx_opts, mutations: mutations,
         | 
| @@ -439,19 +461,23 @@ module Google | |
| 439 461 | 
             
                    end
         | 
| 440 462 |  | 
| 441 463 | 
             
                    def rollback session_name, transaction_id, call_options: nil
         | 
| 464 | 
            +
                      route_to_leader = LARHeaders.rollback
         | 
| 442 465 | 
             
                      opts = default_options session_name: session_name,
         | 
| 443 | 
            -
                                             call_options: call_options
         | 
| 466 | 
            +
                                             call_options: call_options,
         | 
| 467 | 
            +
                                             route_to_leader: route_to_leader
         | 
| 444 468 | 
             
                      request = { session: session_name, transaction_id: transaction_id }
         | 
| 445 469 | 
             
                      service.rollback request, opts
         | 
| 446 470 | 
             
                    end
         | 
| 447 471 |  | 
| 448 472 | 
             
                    def begin_transaction session_name, request_options: nil,
         | 
| 449 | 
            -
                                          call_options: nil
         | 
| 473 | 
            +
                                          call_options: nil,
         | 
| 474 | 
            +
                                          route_to_leader: nil
         | 
| 450 475 | 
             
                      tx_opts = V1::TransactionOptions.new(
         | 
| 451 476 | 
             
                        read_write: V1::TransactionOptions::ReadWrite.new
         | 
| 452 477 | 
             
                      )
         | 
| 453 478 | 
             
                      opts = default_options session_name: session_name,
         | 
| 454 | 
            -
                                             call_options: call_options
         | 
| 479 | 
            +
                                             call_options: call_options,
         | 
| 480 | 
            +
                                             route_to_leader: route_to_leader
         | 
| 455 481 | 
             
                      request = {
         | 
| 456 482 | 
             
                        session: session_name,
         | 
| 457 483 | 
             
                        options: tx_opts,
         | 
| @@ -482,8 +508,10 @@ module Google | |
| 482 508 | 
             
                      tx_opts = V1::TransactionOptions.new(
         | 
| 483 509 | 
             
                        partitioned_dml: V1::TransactionOptions::PartitionedDml.new
         | 
| 484 510 | 
             
                      )
         | 
| 511 | 
            +
                      route_to_leader = LARHeaders.begin_transaction true
         | 
| 485 512 | 
             
                      opts = default_options session_name: session_name,
         | 
| 486 | 
            -
                                             call_options: call_options
         | 
| 513 | 
            +
                                             call_options: call_options,
         | 
| 514 | 
            +
                                             route_to_leader: route_to_leader
         | 
| 487 515 | 
             
                      request = { session: session_name, options: tx_opts }
         | 
| 488 516 | 
             
                      service.begin_transaction request, opts
         | 
| 489 517 | 
             
                    end
         | 
| @@ -608,12 +636,17 @@ module Google | |
| 608 636 | 
             
                      value << " gccl"
         | 
| 609 637 | 
             
                    end
         | 
| 610 638 |  | 
| 611 | 
            -
                    def default_options session_name: nil, call_options: nil
         | 
| 639 | 
            +
                    def default_options session_name: nil, call_options: nil, route_to_leader: nil
         | 
| 612 640 | 
             
                      opts = {}
         | 
| 641 | 
            +
                      metadata = {}
         | 
| 613 642 | 
             
                      if session_name
         | 
| 614 643 | 
             
                        default_prefix = session_name.split("/sessions/").first
         | 
| 615 | 
            -
                         | 
| 644 | 
            +
                        metadata["google-cloud-resource-prefix"] = default_prefix
         | 
| 645 | 
            +
                      end
         | 
| 646 | 
            +
                      if @enable_leader_aware_routing && !route_to_leader.nil?
         | 
| 647 | 
            +
                        metadata["x-goog-spanner-route-to-leader"] = route_to_leader
         | 
| 616 648 | 
             
                      end
         | 
| 649 | 
            +
                      opts[:metadata] = metadata
         | 
| 617 650 | 
             
                      if call_options
         | 
| 618 651 | 
             
                        opts[:timeout] = call_options[:timeout] if call_options[:timeout]
         | 
| 619 652 | 
             
                        opts[:retry_policy] = call_options[:retry_policy] if call_options[:retry_policy]
         | 
| @@ -339,7 +339,7 @@ module Google | |
| 339 339 | 
             
                    def execute_query sql, params: nil, types: nil, transaction: nil,
         | 
| 340 340 | 
             
                                      partition_token: nil, seqno: nil, query_options: nil,
         | 
| 341 341 | 
             
                                      request_options: nil, call_options: nil, data_boost_enabled: nil,
         | 
| 342 | 
            -
                                      directed_read_options: nil
         | 
| 342 | 
            +
                                      directed_read_options: nil, route_to_leader: nil
         | 
| 343 343 | 
             
                      ensure_service!
         | 
| 344 344 | 
             
                      query_options = merge_if_present query_options, @query_options
         | 
| 345 345 |  | 
| @@ -347,7 +347,8 @@ module Google | |
| 347 347 | 
             
                        transaction: transaction, params: params, types: types,
         | 
| 348 348 | 
             
                        partition_token: partition_token, seqno: seqno,
         | 
| 349 349 | 
             
                        query_options: query_options, request_options: request_options,
         | 
| 350 | 
            -
                        call_options: call_options
         | 
| 350 | 
            +
                        call_options: call_options,
         | 
| 351 | 
            +
                        route_to_leader: route_to_leader
         | 
| 351 352 | 
             
                      }
         | 
| 352 353 | 
             
                      execute_query_options[:data_boost_enabled] = data_boost_enabled unless data_boost_enabled.nil?
         | 
| 353 354 | 
             
                      execute_query_options[:directed_read_options] = directed_read_options unless directed_read_options.nil?
         | 
| @@ -497,7 +498,8 @@ module Google | |
| 497 498 | 
             
                    #
         | 
| 498 499 | 
             
                    def read table, columns, keys: nil, index: nil, limit: nil,
         | 
| 499 500 | 
             
                             transaction: nil, partition_token: nil, request_options: nil,
         | 
| 500 | 
            -
                             call_options: nil, data_boost_enabled: nil, directed_read_options: nil
         | 
| 501 | 
            +
                             call_options: nil, data_boost_enabled: nil, directed_read_options: nil,
         | 
| 502 | 
            +
                             route_to_leader: nil
         | 
| 501 503 | 
             
                      ensure_service!
         | 
| 502 504 |  | 
| 503 505 | 
             
                      read_options = {
         | 
| @@ -505,7 +507,8 @@ module Google | |
| 505 507 | 
             
                        transaction: transaction,
         | 
| 506 508 | 
             
                        partition_token: partition_token,
         | 
| 507 509 | 
             
                        request_options: request_options,
         | 
| 508 | 
            -
                        call_options: call_options
         | 
| 510 | 
            +
                        call_options: call_options,
         | 
| 511 | 
            +
                        route_to_leader: route_to_leader
         | 
| 509 512 | 
             
                      }
         | 
| 510 513 | 
             
                      read_options[:data_boost_enabled] = data_boost_enabled unless data_boost_enabled.nil?
         | 
| 511 514 | 
             
                      read_options[:directed_read_options] = directed_read_options unless directed_read_options.nil?
         | 
| @@ -1178,7 +1181,8 @@ module Google | |
| 1178 1181 | 
             
                    # @private
         | 
| 1179 1182 | 
             
                    # Creates a new transaction object every time.
         | 
| 1180 1183 | 
             
                    def create_transaction
         | 
| 1181 | 
            -
                       | 
| 1184 | 
            +
                      route_to_leader = LARHeaders.begin_transaction true
         | 
| 1185 | 
            +
                      tx_grpc = service.begin_transaction path, route_to_leader: route_to_leader
         | 
| 1182 1186 | 
             
                      Transaction.from_grpc tx_grpc, self
         | 
| 1183 1187 | 
             
                    end
         | 
| 1184 1188 |  | 
| @@ -1214,7 +1218,8 @@ module Google | |
| 1214 1218 | 
             
                    # Keeps the session alive by executing `"SELECT 1"`.
         | 
| 1215 1219 | 
             
                    def keepalive!
         | 
| 1216 1220 | 
             
                      ensure_service!
         | 
| 1217 | 
            -
                      execute_query  | 
| 1221 | 
            +
                      route_to_leader = LARHeaders.execute_query false
         | 
| 1222 | 
            +
                      execute_query "SELECT 1", route_to_leader: route_to_leader
         | 
| 1218 1223 | 
             
                      true
         | 
| 1219 1224 | 
             
                    rescue Google::Cloud::NotFoundError
         | 
| 1220 1225 | 
             
                      labels = @grpc.labels.to_h unless @grpc.labels.to_h.empty?
         | 
| @@ -18,6 +18,7 @@ require "google/cloud/spanner/convert" | |
| 18 18 | 
             
            require "google/cloud/spanner/results"
         | 
| 19 19 | 
             
            require "google/cloud/spanner/commit"
         | 
| 20 20 | 
             
            require "google/cloud/spanner/batch_update_results"
         | 
| 21 | 
            +
            require "google/cloud/spanner/lar_headers"
         | 
| 21 22 |  | 
| 22 23 | 
             
            module Google
         | 
| 23 24 | 
             
              module Cloud
         | 
| @@ -361,13 +362,15 @@ module Google | |
| 361 362 |  | 
| 362 363 | 
             
                      params, types = Convert.to_input_params_and_types params, types
         | 
| 363 364 | 
             
                      request_options = build_request_options request_options
         | 
| 365 | 
            +
                      route_to_leader = LARHeaders.execute_query true
         | 
| 364 366 |  | 
| 365 367 | 
             
                      safe_execute do |seqno|
         | 
| 366 368 | 
             
                        results = session.execute_query sql, params: params, types: types,
         | 
| 367 369 | 
             
                                                        transaction: tx_selector, seqno: seqno,
         | 
| 368 370 | 
             
                                                        query_options: query_options,
         | 
| 369 371 | 
             
                                                        request_options: request_options,
         | 
| 370 | 
            -
                                                        call_options: call_options
         | 
| 372 | 
            +
                                                        call_options: call_options,
         | 
| 373 | 
            +
                                                        route_to_leader: route_to_leader
         | 
| 371 374 | 
             
                        @grpc ||= results.transaction
         | 
| 372 375 | 
             
                        results
         | 
| 373 376 | 
             
                      end
         | 
| @@ -715,12 +718,14 @@ module Google | |
| 715 718 | 
             
                      columns = Array(columns).map(&:to_s)
         | 
| 716 719 | 
             
                      keys = Convert.to_key_set keys
         | 
| 717 720 | 
             
                      request_options = build_request_options request_options
         | 
| 721 | 
            +
                      route_to_leader = LARHeaders.read true
         | 
| 718 722 |  | 
| 719 723 | 
             
                      safe_execute do
         | 
| 720 724 | 
             
                        results = session.read table, columns, keys: keys, index: index, limit: limit,
         | 
| 721 725 | 
             
                                               transaction: tx_selector,
         | 
| 722 726 | 
             
                                               request_options: request_options,
         | 
| 723 | 
            -
                                               call_options: call_options
         | 
| 727 | 
            +
                                               call_options: call_options,
         | 
| 728 | 
            +
                                               route_to_leader: route_to_leader
         | 
| 724 729 | 
             
                        @grpc ||= results.transaction
         | 
| 725 730 | 
             
                        results
         | 
| 726 731 | 
             
                      end
         | 
| @@ -1190,7 +1195,8 @@ module Google | |
| 1190 1195 | 
             
                      @mutex.synchronize do
         | 
| 1191 1196 | 
             
                        return if existing_transaction?
         | 
| 1192 1197 | 
             
                        ensure_session!
         | 
| 1193 | 
            -
                         | 
| 1198 | 
            +
                        route_to_leader = LARHeaders.begin_transaction true
         | 
| 1199 | 
            +
                        @grpc = service.begin_transaction session.path, route_to_leader: route_to_leader
         | 
| 1194 1200 | 
             
                      end
         | 
| 1195 1201 | 
             
                    end
         | 
| 1196 1202 |  | 
    
        data/lib/google/cloud/spanner.rb
    CHANGED
    
    | @@ -82,6 +82,8 @@ module Google | |
| 82 82 | 
             
                  #   `spanner-activerecord/0.0.1` is provided custom library name and
         | 
| 83 83 | 
             
                  #   version and `gccl/1.13.1` represents the Cloud Spanner Ruby library
         | 
| 84 84 | 
             
                  #   with version.
         | 
| 85 | 
            +
                  # @param enable_leader_aware_routing [Boolean] Specifies whether Leader
         | 
| 86 | 
            +
                  #   Aware Routing should be enabled. Defaults to true.
         | 
| 85 87 | 
             
                  #
         | 
| 86 88 | 
             
                  # @return [Google::Cloud::Spanner::Project]
         | 
| 87 89 | 
             
                  #
         | 
| @@ -92,7 +94,8 @@ module Google | |
| 92 94 | 
             
                  #
         | 
| 93 95 | 
             
                  def self.new project_id: nil, credentials: nil, scope: nil, timeout: nil,
         | 
| 94 96 | 
             
                               endpoint: nil, project: nil, keyfile: nil,
         | 
| 95 | 
            -
                               emulator_host: nil, lib_name: nil, lib_version: nil
         | 
| 97 | 
            +
                               emulator_host: nil, lib_name: nil, lib_version: nil,
         | 
| 98 | 
            +
                               enable_leader_aware_routing: true
         | 
| 96 99 | 
             
                    project_id    ||= project || default_project_id
         | 
| 97 100 | 
             
                    scope         ||= configure.scope
         | 
| 98 101 | 
             
                    timeout       ||= configure.timeout
         | 
| @@ -122,7 +125,8 @@ module Google | |
| 122 125 | 
             
                      Spanner::Service.new(
         | 
| 123 126 | 
             
                        project_id, credentials, quota_project: configure.quota_project,
         | 
| 124 127 | 
             
                        host: endpoint, timeout: timeout, lib_name: lib_name,
         | 
| 125 | 
            -
                        lib_version: lib_version
         | 
| 128 | 
            +
                        lib_version: lib_version,
         | 
| 129 | 
            +
                        enable_leader_aware_routing: enable_leader_aware_routing
         | 
| 126 130 | 
             
                      ),
         | 
| 127 131 | 
             
                      query_options: configure.query_options
         | 
| 128 132 | 
             
                    )
         | 
    
        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.20.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Mike Moore
         | 
| @@ -9,7 +9,7 @@ authors: | |
| 9 9 | 
             
            autorequire: 
         | 
| 10 10 | 
             
            bindir: bin
         | 
| 11 11 | 
             
            cert_chain: []
         | 
| 12 | 
            -
            date: 2024-01- | 
| 12 | 
            +
            date: 2024-01-31 00:00:00.000000000 Z
         | 
| 13 13 | 
             
            dependencies:
         | 
| 14 14 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 15 15 | 
             
              name: google-cloud-core
         | 
| @@ -317,6 +317,7 @@ files: | |
| 317 317 | 
             
            - lib/google/cloud/spanner/instance/config/list.rb
         | 
| 318 318 | 
             
            - lib/google/cloud/spanner/instance/job.rb
         | 
| 319 319 | 
             
            - lib/google/cloud/spanner/instance/list.rb
         | 
| 320 | 
            +
            - lib/google/cloud/spanner/lar_headers.rb
         | 
| 320 321 | 
             
            - lib/google/cloud/spanner/partition.rb
         | 
| 321 322 | 
             
            - lib/google/cloud/spanner/policy.rb
         | 
| 322 323 | 
             
            - lib/google/cloud/spanner/pool.rb
         |