Skip to content

Commit 051dc62

Browse files
committed
impl(spanner): introduce concurrency control options
This adds support for Transaction_ReadWriteOptions_ReadLockMode by adding a constructor of ReadWriteOptions with a special enum, whose values can be "optimistic", "pessimistic" and "unspecified".
1 parent 05b46d0 commit 051dc62

File tree

3 files changed

+69
-2
lines changed

3 files changed

+69
-2
lines changed

google/cloud/spanner/transaction.cc

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ google::protobuf::Duration ToProto(std::chrono::nanoseconds ns) {
3434
return proto;
3535
}
3636

37+
google::spanner::v1::TransactionOptions_ReadWrite_ReadLockMode ToProto(Transaction::ReadLockMode read_lock_mode) {
38+
return static_cast<google::spanner::v1::TransactionOptions_ReadWrite_ReadLockMode>(read_lock_mode);
39+
}
40+
3741
google::spanner::v1::TransactionOptions MakeOpts(
3842
google::spanner::v1::TransactionOptions_ReadOnly ro_opts) {
3943
google::spanner::v1::TransactionOptions opts;
@@ -71,14 +75,20 @@ Transaction::ReadOnlyOptions::ReadOnlyOptions(
7175
ro_opts_.set_return_read_timestamp(true);
7276
}
7377

74-
Transaction::ReadWriteOptions::ReadWriteOptions() = default; // currently none
78+
Transaction::ReadWriteOptions::ReadWriteOptions() = default;
79+
80+
Transaction::ReadWriteOptions::ReadWriteOptions(
81+
ReadLockMode read_lock_mode) {
82+
rw_opts_.set_read_lock_mode(ToProto(read_lock_mode));
83+
}
7584

7685
Transaction::ReadWriteOptions& Transaction::ReadWriteOptions::WithTag(
7786
absl::optional<std::string> tag) {
7887
tag_ = std::move(tag);
7988
return *this;
8089
}
8190

91+
8292
Transaction::SingleUseOptions::SingleUseOptions(ReadOnlyOptions opts) {
8393
ro_opts_ = std::move(opts.ro_opts_);
8494
}

google/cloud/spanner/transaction.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,28 @@ class Transaction {
7878
google::spanner::v1::TransactionOptions_ReadOnly ro_opts_;
7979
};
8080

81+
/**
82+
* Read lock mode for ReadWrite transactions
83+
* The Spanner V1 Transaction proto classes have their own enum
84+
* implementations.
85+
* See google::spanner::v1::TransactionOptions_ReadWrite_ReadLockMode
86+
* This is a shorthand convenience for the developer.
87+
*/
88+
enum class ReadLockMode {
89+
kUnspecified,
90+
kPessimistic,
91+
kOptimistic,
92+
};
93+
8194
/**
8295
* Options for ReadWrite transactions.
8396
*/
8497
class ReadWriteOptions {
8598
public:
86-
// There are currently no read-write options.
8799
ReadWriteOptions();
88100

101+
ReadWriteOptions(ReadLockMode read_lock_mode);
102+
89103
// A tag used for collecting statistics about the transaction.
90104
ReadWriteOptions& WithTag(absl::optional<std::string> tag);
91105

google/cloud/spanner/transaction_test.cc

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,14 @@ using ::testing::IsEmpty;
2727
TEST(TransactionOptions, Construction) {
2828
Timestamp read_timestamp{};
2929
std::chrono::nanoseconds staleness{};
30+
auto read_lock_mode = Transaction::ReadLockMode::kOptimistic;
3031

3132
Transaction::ReadOnlyOptions strong;
3233
Transaction::ReadOnlyOptions exact_ts(read_timestamp);
3334
Transaction::ReadOnlyOptions exact_dur(staleness);
3435

3536
Transaction::ReadWriteOptions none;
37+
Transaction::ReadWriteOptions rw_with_read_lock(read_lock_mode);
3638

3739
Transaction::SingleUseOptions su_strong(strong);
3840
Transaction::SingleUseOptions su_exact_ts(exact_ts);
@@ -130,6 +132,47 @@ TEST(Transaction, SessionAffinity) {
130132
});
131133
}
132134

135+
TEST(Transaction, ReadWriteOptions_WithTag) {
136+
auto opts = Transaction::ReadWriteOptions().WithTag("test-tag");
137+
Transaction txn = MakeReadWriteTransaction(opts);
138+
spanner_internal::Visit(
139+
txn, [&](spanner_internal::SessionHolder& /*session*/,
140+
StatusOr<google::spanner::v1::TransactionSelector>& s,
141+
spanner_internal::TransactionContext const& ctx) {
142+
EXPECT_TRUE(s->has_begin());
143+
EXPECT_TRUE(s->begin().has_read_write());
144+
EXPECT_EQ(ctx.tag, "test-tag");
145+
return 0;
146+
});
147+
}
148+
149+
TEST(Transaction, ReadWriteOptions_WithReadLockMode) {
150+
auto check_lock_mode =
151+
[](Transaction::ReadLockMode mode,
152+
google::spanner::v1::TransactionOptions_ReadWrite_ReadLockMode
153+
expected_proto_mode) {
154+
auto opts = Transaction::ReadWriteOptions(mode);
155+
Transaction txn = MakeReadWriteTransaction(opts);
156+
spanner_internal::Visit(
157+
txn, [&](spanner_internal::SessionHolder& /*session*/,
158+
StatusOr<google::spanner::v1::TransactionSelector>& s,
159+
spanner_internal::TransactionContext const& /*ctx*/) {
160+
EXPECT_TRUE(s->has_begin());
161+
EXPECT_TRUE(s->begin().has_read_write());
162+
EXPECT_EQ(s->begin().read_write().read_lock_mode(),
163+
expected_proto_mode);
164+
return 0;
165+
});
166+
};
167+
168+
check_lock_mode(
169+
Transaction::ReadLockMode::kPessimistic,
170+
google::spanner::v1::TransactionOptions_ReadWrite::PESSIMISTIC);
171+
check_lock_mode(
172+
Transaction::ReadLockMode::kOptimistic,
173+
google::spanner::v1::TransactionOptions_ReadWrite::OPTIMISTIC);
174+
}
175+
133176
} // namespace
134177
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
135178
} // namespace spanner

0 commit comments

Comments
 (0)