Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
185 changes: 128 additions & 57 deletions google-cloud-spanner/lib/google/cloud/spanner/client.rb

Large diffs are not rendered by default.

23 changes: 21 additions & 2 deletions google-cloud-spanner/lib/google/cloud/spanner/project.rb
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,22 @@ def create_database instance_id, database_id, statements: [],
# Spanner will wait for a replica in the list to become available,
# requests may fail due to DEADLINE_EXCEEDED errors.
#
# @param isolation_level [::Symbol, nil] Optional. The isolation level for the transactions. Can be
# overridden by the isolation level set on the transaction.
# Can be one of the following:
# * `:ISOLATION_LEVEL_UNSPECIFIED` : The default unspecified isolation level.
# * `:SERIALIZABLE` : The serializable isolation level.
# * `:REPEATABLE_READ` : The repeatable read isolation level.
# @param read_lock_mode [::Symbol, nil] Optional. The read lock mode for the transactions. Can be
# overridden by the read lock mode set on the transaction.
# Can be one of the following:
# * `:READ_LOCK_MODE_UNSPECIFIED` : The default unspecified read lock mode.
# * `:PESSIMISTIC` : The pessimistic lock mode, where depending on the isolation level and/or lock
# requested, locks are acquired on read.
# * `:OPTIMISTIC` : The optimistic lock mode, where locks are not acquired on read. Depending on the
# isolation level and/or lock requested on a read, data may be validated at commit time to be not
# changed since the transaction started.
#
# @return [::Google::Cloud::Spanner::Client] The newly created client.
#
# @example
Expand All @@ -566,7 +582,8 @@ def create_database instance_id, database_id, statements: [],
# end
#
def client instance_id, database_id, pool: {}, labels: nil,
query_options: nil, database_role: nil, directed_read_options: nil
query_options: nil, database_role: nil, directed_read_options: nil,
isolation_level: nil, read_lock_mode: nil
# Convert from possible Google::Protobuf::Map
labels = labels.to_h { |k, v| [String(k), String(v)] } if labels
# Configs set by environment variables take over client-level configs.
Expand All @@ -582,7 +599,9 @@ def client instance_id, database_id, pool: {}, labels: nil,
session_labels: labels,
query_options: query_options,
database_role: database_role,
directed_read_options: directed_read_options
directed_read_options: directed_read_options,
isolation_level: isolation_level,
read_lock_mode: read_lock_mode
end

##
Expand Down
19 changes: 17 additions & 2 deletions google-cloud-spanner/lib/google/cloud/spanner/service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,19 @@ def rollback session_name, transaction_id, call_options: nil
# An id of the previous transaction, if this new transaction wrapper is being created
# as a part of a retry. Previous transaction id should be added to TransactionOptions
# of a new ReadWrite transaction when retry is attempted.
# @param read_lock_mode [::Symbol, nil] Optional. The read lock mode for the transaction.
# Can be one of the following:
# * `:READ_LOCK_MODE_UNSPECIFIED` : The default unspecified read lock mode.
# * `:PESSIMISTIC` : The pessimistic lock mode, where depending on the isolation level and/or lock
# requested, locks are acquired on read.
# * `:OPTIMISTIC` : The optimistic lock mode, where locks are not acquired on read. Depending on the
# isolation level and/or lock requested on a read, data may be validated at commit time to be not
# changed since the transaction started.
# @param isolation_level [::Symbol, nil] Optional. The isolation level for the transaction.
# Can be one of the following:
# * `:ISOLATION_LEVEL_UNSPECIFIED` : The default unspecified isolation level.
# * `:SERIALIZABLE` : The serializable isolation level.
# * `:REPEATABLE_READ` : The repeatable read isolation level.
# @private
# @return [::Google::Cloud::Spanner::V1::Transaction]
def begin_transaction session_name,
Expand All @@ -649,7 +662,8 @@ def begin_transaction session_name,
route_to_leader: nil,
mutation_key: nil,
previous_transaction_id: nil,
read_lock_mode: nil
read_lock_mode: nil,
isolation_level: nil
read_write = if previous_transaction_id.nil?
V1::TransactionOptions::ReadWrite.new
else
Expand All @@ -664,7 +678,8 @@ def begin_transaction session_name,

tx_opts = V1::TransactionOptions.new(
read_write: read_write,
exclude_txn_from_change_streams: exclude_txn_from_change_streams
exclude_txn_from_change_streams: exclude_txn_from_change_streams,
isolation_level: isolation_level
)

opts = default_options session_name: session_name,
Expand Down
17 changes: 15 additions & 2 deletions google-cloud-spanner/lib/google/cloud/spanner/session.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1521,13 +1521,26 @@ def create_transaction exclude_txn_from_change_streams: false, read_lock_mode: n
# of a new ReadWrite transaction when retry is attempted.
# @param transaction_tag [::String, nil] Optional.
# A tag used for statistics collection about this transaction.
# @param read_lock_mode [::Symbol, nil] Optional. The read lock mode for the transaction.
# Can be one of the following:
# * `:READ_LOCK_MODE_UNSPECIFIED` : The default unspecified read lock mode.
# * `:PESSIMISTIC` : The pessimistic lock mode, where depending on the isolation level and/or lock
# requested, locks are acquired on read.
# * `:OPTIMISTIC` : The optimistic lock mode, where locks are not acquired on read. Depending on the
# isolation level and/or lock requested on a read, data may be validated at commit time to be not
# changed since the transaction started.
# @param isolation_level [::Symbol, nil] Optional. The isolation level for the transaction.
# Can be one of the following:
# * `:ISOLATION_LEVEL_UNSPECIFIED` : The default unspecified isolation level.
# * `:SERIALIZABLE` : The serializable isolation level.
# * `:REPEATABLE_READ` : The repeatable read isolation level.
# @private
# @return [::Google::Cloud::Spanner::Transaction] The new *empty-wrapper* transaction object.
def create_empty_transaction exclude_txn_from_change_streams: false, previous_transaction_id: nil,
read_lock_mode: nil, transaction_tag: nil
read_lock_mode: nil, transaction_tag: nil, isolation_level: nil
Transaction.from_grpc nil, self, exclude_txn_from_change_streams: exclude_txn_from_change_streams,
previous_transaction_id: previous_transaction_id, read_lock_mode: read_lock_mode,
transaction_tag: transaction_tag
transaction_tag: transaction_tag, isolation_level: isolation_level
end

# If the session is non-multiplexed, keeps the session alive by executing `"SELECT 1"`.
Expand Down
64 changes: 54 additions & 10 deletions google-cloud-spanner/lib/google/cloud/spanner/transaction.rb
Original file line number Diff line number Diff line change
Expand Up @@ -129,12 +129,13 @@ class Transaction
# @private
# @return [::Google::Cloud::Spanner::Transaction]
def initialize grpc, session, exclude_txn_from_change_streams, previous_transaction_id: nil,
read_lock_mode: nil, transaction_tag: nil
read_lock_mode: nil, transaction_tag: nil, isolation_level: nil
@grpc = grpc
@session = session
@exclude_txn_from_change_streams = exclude_txn_from_change_streams
@read_lock_mode = read_lock_mode
@transaction_tag = transaction_tag
@isolation_level = isolation_level

# throwing away empty strings for simplicity
unless previous_transaction_id.nil? || previous_transaction_id.empty?
Expand All @@ -144,7 +145,6 @@ def initialize grpc, session, exclude_txn_from_change_streams, previous_transact
@commit = Commit.new
@seqno = 0
@exclude_txn_from_change_streams = false
@read_lock_mode = nil

# Mutex to enfore thread safety for transaction creation and query executions.
#
Expand Down Expand Up @@ -1259,12 +1259,25 @@ def mutations
# of a new ReadWrite transaction when retry is attempted.
# @param transaction_tag [::String, nil] Optional.
# A tag used for statistics collection about this transaction.
# @param read_lock_mode [::Symbol, nil] Optional. The read lock mode for the transaction.
# Can be one of the following:
# * `:READ_LOCK_MODE_UNSPECIFIED` : The default unspecified read lock mode.
# * `:PESSIMISTIC` : The pessimistic lock mode, where depending on the isolation level and/or lock
# requested, locks are acquired on read.
# * `:OPTIMISTIC` : The optimistic lock mode, where locks are not acquired on read. Depending on the
# isolation level and/or lock requested on a read, data may be validated at commit time to be not
# changed since the transaction started.
# @param isolation_level [::Symbol, nil] Optional. The isolation level for the transaction.
# Can be one of the following:
# * `:ISOLATION_LEVEL_UNSPECIFIED` : The default unspecified isolation level.
# * `:SERIALIZABLE` : The serializable isolation level.
# * `:REPEATABLE_READ` : The repeatable read isolation level.
# @private
# @return [::Google::Cloud::Spanner::Transaction]
def self.from_grpc grpc, session, exclude_txn_from_change_streams: false, previous_transaction_id: nil,
read_lock_mode: nil, transaction_tag: nil
read_lock_mode: nil, transaction_tag: nil, isolation_level: nil
new grpc, session, exclude_txn_from_change_streams, previous_transaction_id: previous_transaction_id,
read_lock_mode: read_lock_mode, transaction_tag: transaction_tag
read_lock_mode: read_lock_mode, transaction_tag: transaction_tag, isolation_level: isolation_level
end

##
Expand All @@ -1288,11 +1301,24 @@ def no_existing_transaction?
# Example option: `:priority`.
# @param call_options [::Hash, nil] Optional. A hash of values to specify the custom
# call options. Example option `:timeout`.
# @param read_lock_mode [::Symbol, nil] Optional. The read lock mode for the transaction.
# Can be one of the following:
# * `:READ_LOCK_MODE_UNSPECIFIED` : The default unspecified read lock mode.
# * `:PESSIMISTIC` : The pessimistic lock mode, where depending on the isolation level and/or lock
# requested, locks are acquired on read.
# * `:OPTIMISTIC` : The optimistic lock mode, where locks are not acquired on read. Depending on the
# isolation level and/or lock requested on a read, data may be validated at commit time to be not
# changed since the transaction started.
# @param isolation_level [::Symbol, nil] Optional. The isolation level for the transaction.
# Can be one of the following:
# * `:ISOLATION_LEVEL_UNSPECIFIED` : The default unspecified isolation level.
# * `:SERIALIZABLE` : The serializable isolation level.
# * `:REPEATABLE_READ` : The repeatable read isolation level.
# @private
# @return [::Google::Cloud::Spanner::V1::Transaction, nil] The new transaction
# object, or `nil` if a transaction already exists.
def safe_begin_transaction! exclude_from_change_streams: false, request_options: nil, call_options: nil,
read_lock_mode: nil
read_lock_mode: nil, isolation_level: nil
# If a read-write transaction on a multiplexed session commit mutations
# without performing any reads or queries, one of the mutations from the mutation set
# must be sent as a mutation key for `BeginTransaction`.
Expand All @@ -1315,7 +1341,8 @@ def safe_begin_transaction! exclude_from_change_streams: false, request_options:
route_to_leader: route_to_leader,
mutation_key: mutation_key,
previous_transaction_id: previous_transaction_id,
read_lock_mode: read_lock_mode
read_lock_mode: read_lock_mode || @read_lock_mode,
isolation_level: isolation_level || @isolation_level
)
end
end
Expand Down Expand Up @@ -1357,9 +1384,24 @@ def safe_execute
# @param exclude_txn_from_change_streams [::Boolean] Optional. Defaults to `false`.
# When `exclude_txn_from_change_streams` is set to `true`, it prevents read
# or write transactions from being tracked in change streams.
# @param read_lock_mode [::Symbol, nil] Optional. The read lock mode for the transaction. If not
# specified, the client-level read lock mode will be used.
# Can be one of the following:
# * `:READ_LOCK_MODE_UNSPECIFIED` : The default unspecified read lock mode.
# * `:PESSIMISTIC` : The pessimistic lock mode, where depending on the isolation level and/or lock
# requested, locks are acquired on read.
# * `:OPTIMISTIC` : The optimistic lock mode, where locks are not acquired on read. Depending on the
# isolation level and/or lock requested on a read, data may be validated at commit time to be not
# changed since the transaction started.
# @param isolation_level [::Symbol, nil] Optional. The isolation level for the transaction. If not
# specified, the client-level isolation level will be used.
# Can be one of the following:
# * `:ISOLATION_LEVEL_UNSPECIFIED` : The default unspecified isolation level.
# * `:SERIALIZABLE` : The serializable isolation level.
# * `:REPEATABLE_READ` : The repeatable read isolation level.
# @private
# @return [::Google::Cloud::Spanner::V1::TransactionSelector]
def tx_selector exclude_txn_from_change_streams: false, read_lock_mode: nil
def tx_selector exclude_txn_from_change_streams: false, read_lock_mode: nil, isolation_level: nil
return V1::TransactionSelector.new id: transaction_id if existing_transaction?

read_write = if @previous_transaction_id.nil?
Expand All @@ -1370,14 +1412,16 @@ def tx_selector exclude_txn_from_change_streams: false, read_lock_mode: nil
)
end

unless read_lock_mode.nil?
read_write.read_lock_mode = read_lock_mode
read_lock = read_lock_mode || @read_lock_mode
unless read_lock.nil?
read_write.read_lock_mode = read_lock
end

V1::TransactionSelector.new(
begin: V1::TransactionOptions.new(
read_write: read_write,
exclude_txn_from_change_streams: exclude_txn_from_change_streams
exclude_txn_from_change_streams: exclude_txn_from_change_streams,
isolation_level: isolation_level || @isolation_level
)
)
end
Expand Down
Loading
Loading