Google Cloud Spanner C++ Client  1.32.0
A C++ Client Library for Google Cloud Spanner
transaction.h
Go to the documentation of this file.
1 // Copyright 2019 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 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_SPANNER_TRANSACTION_H
16 #define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_SPANNER_TRANSACTION_H
17 
18 #include "google/cloud/spanner/internal/transaction_impl.h"
19 #include "google/cloud/spanner/timestamp.h"
20 #include "google/cloud/spanner/version.h"
21 #include "absl/types/optional.h"
22 #include <google/spanner/v1/transaction.pb.h>
23 #include <chrono>
24 #include <memory>
25 #include <string>
26 
27 namespace google {
28 namespace cloud {
29 namespace spanner_internal {
30 inline namespace SPANNER_CLIENT_NS {
31 struct TransactionInternals;
32 } // namespace SPANNER_CLIENT_NS
33 } // namespace spanner_internal
34 
35 namespace spanner {
36 inline namespace SPANNER_CLIENT_NS {
37 
38 /**
39  * The representation of a Cloud Spanner transaction.
40  *
41  * A transaction is a set of reads and writes that execute atomically at a
42  * single logical point in time across the columns/rows/tables in a database.
43  * Those reads and writes are grouped by passing them the same `Transaction`.
44  *
45  * All reads/writes in the transaction must be executed within the same
46  * session, and that session may have only one transaction active at a time.
47  *
48  * Spanner supports these transaction modes:
49  * - ReadOnly. Provides guaranteed consistency across several reads, but does
50  * not allow writes. Can be configured to read at timestamps in the past.
51  * Does not need to be committed and does not take locks.
52  * - ReadWrite. Supports reading and writing data at a single point in time.
53  * Uses pessimistic locking and, if necessary, two-phase commit. May abort,
54  * requiring the application to rerun.
55  * - SingleUse. A restricted form of a ReadOnly transaction where Spanner
56  * chooses the read timestamp.
57  */
58 class Transaction {
59  public:
60  /**
61  * Options for ReadOnly transactions.
62  */
64  public:
65  // Strong: Guarantees visibility of the effects of all transactions that
66  // committed before the start of the reads.
68 
69  // Exact Staleness: Executes all reads at `read_timestamp`.
70  explicit ReadOnlyOptions(Timestamp read_timestamp);
71 
72  // Exact Staleness: Executes all reads at a timestamp `exact_staleness`
73  // old. The actual timestamp is chosen soon after the reads are started.
74  explicit ReadOnlyOptions(std::chrono::nanoseconds exact_staleness);
75 
76  private:
77  friend Transaction;
78  google::spanner::v1::TransactionOptions_ReadOnly ro_opts_;
79  };
80 
81  /**
82  * Options for ReadWrite transactions.
83  */
85  public:
86  // There are currently no read-write options.
88 
89  // A tag used for collecting statistics about the transaction.
90  ReadWriteOptions& WithTag(absl::optional<std::string> tag);
91 
92  private:
93  friend Transaction;
94  google::spanner::v1::TransactionOptions_ReadWrite rw_opts_;
95  absl::optional<std::string> tag_;
96  };
97 
98  /**
99  * Options for "single-use", ReadOnly transactions, where Spanner chooses
100  * the read timestamp, subject to user-provided bounds. This allows reading
101  * without blocking.
102  *
103  * Because selection of the timestamp requires knowledge of which rows will
104  * be read, a single-use transaction can only be used with one read. See
105  * Client::Read() and Client::ExecuteQuery(). SingleUseOptions cannot be used
106  * to construct an application-level Transaction.
107  */
109  public:
110  // Strong or Exact Staleness: See ReadOnlyOptions.
111  // NOLINTNEXTLINE(google-explicit-constructor)
113 
114  // Bounded Staleness: Executes all reads at a timestamp that is not
115  // before `min_read_timestamp`.
116  explicit SingleUseOptions(Timestamp min_read_timestamp);
117 
118  // Bounded Staleness: Executes all reads at a timestamp that is not
119  // before `NOW - max_staleness`.
120  explicit SingleUseOptions(std::chrono::nanoseconds max_staleness);
121 
122  private:
123  friend Transaction;
124  google::spanner::v1::TransactionOptions_ReadOnly ro_opts_;
125  };
126 
127  /// @name Construction of read-only and read-write transactions.
128  ///@{
129  /**
130  * @note This is a lazy evaluated operation. No RPCs are made as part of
131  * creating a `Transaction` object. Instead, the first request to the
132  * server (for example as part of a `ExecuteQuery()` call) will also
133  * create the transaction.
134  */
135  explicit Transaction(ReadOnlyOptions opts);
136  /// @copydoc Transaction(ReadOnlyOptions)
137  explicit Transaction(ReadWriteOptions opts);
138  /// @copydoc Transaction(ReadOnlyOptions)
139  Transaction(Transaction const& txn, ReadWriteOptions opts);
140  ///@}
141 
143 
144  /// @name Regular value type, supporting copy, assign, move.
145  ///@{
146  Transaction(Transaction&&) = default;
148  Transaction(Transaction const&) = default;
149  Transaction& operator=(Transaction const&) = default;
150  ///@}
151 
152  /// @name Equality operators
153  ///@{
154  friend bool operator==(Transaction const& a, Transaction const& b) {
155  return a.impl_ == b.impl_;
156  }
157  friend bool operator!=(Transaction const& a, Transaction const& b) {
158  return !(a == b);
159  }
160  ///@}
161 
162  private:
163  // Friendship for access by internal helpers.
164  friend struct spanner_internal::SPANNER_CLIENT_NS::TransactionInternals;
165 
166  // Construction of a single-use transaction.
167  explicit Transaction(SingleUseOptions opts);
168  // Construction of a transaction with existing IDs.
169  Transaction(std::string session_id, std::string transaction_id,
170  std::string transaction_tag);
171 
172  std::shared_ptr<spanner_internal::TransactionImpl> impl_;
173 };
174 
175 /**
176  * Create a read-only transaction configured with @p opts.
177  *
178  * @copydoc Transaction::Transaction(ReadOnlyOptions)
179  */
182  return Transaction(std::move(opts));
183 }
184 
185 /**
186  * Create a read-write transaction configured with @p opts.
187  *
188  * @copydoc Transaction::Transaction(ReadOnlyOptions)
189  */
192  return Transaction(std::move(opts));
193 }
194 
195 /**
196  * Create a read-write transaction configured with @p opts, and sharing
197  * lock priority with @p txn. This should be used when rerunning an aborted
198  * transaction, so that the new attempt has a slightly better chance of
199  * success.
200  */
202  Transaction const& txn, Transaction::ReadWriteOptions opts = {}) {
203  return Transaction(txn, std::move(opts));
204 }
205 
206 } // namespace SPANNER_CLIENT_NS
207 } // namespace spanner
208 
209 namespace spanner_internal {
210 inline namespace SPANNER_CLIENT_NS {
211 
212 struct TransactionInternals {
213  template <typename T>
214  static spanner::Transaction MakeSingleUseTransaction(T&& opts) {
215  // Requires that `opts` is implicitly convertible to SingleUseOptions.
216  spanner::Transaction::SingleUseOptions su_opts = std::forward<T>(opts);
217  return spanner::Transaction(std::move(su_opts));
218  }
219 
220  template <typename Functor>
221  // Pass `txn` by value, despite being used only once. This avoids the
222  // possibility of `txn` being destroyed by `f` before `Visit()` can
223  // return. Therefore, ...
224  // NOLINTNEXTLINE(performance-unnecessary-value-param)
225  static VisitInvokeResult<Functor> Visit(spanner::Transaction txn,
226  Functor&& f) {
227  return txn.impl_->Visit(std::forward<Functor>(f));
228  }
229 
230  static spanner::Transaction MakeTransactionFromIds(
231  std::string session_id, std::string transaction_id,
232  std::string transaction_tag);
233 };
234 
235 template <typename T>
236 spanner::Transaction MakeSingleUseTransaction(T&& opts) {
237  return TransactionInternals::MakeSingleUseTransaction(std::forward<T>(opts));
238 }
239 
240 template <typename Functor>
241 // Pass `txn` by value, despite being used only once. This avoids the
242 // possibility of `txn` being destroyed by `f` before `Visit()` can
243 // return. Therefore, ...
244 // NOLINTNEXTLINE(performance-unnecessary-value-param)
245 VisitInvokeResult<Functor> Visit(spanner::Transaction txn, Functor&& f) {
246  return TransactionInternals::Visit(std::move(txn), std::forward<Functor>(f));
247 }
248 
249 inline spanner::Transaction MakeTransactionFromIds(
250  std::string session_id, std::string transaction_id,
251  std::string transaction_tag) {
252  return TransactionInternals::MakeTransactionFromIds(
253  std::move(session_id), std::move(transaction_id),
254  std::move(transaction_tag));
255 }
256 
257 } // namespace SPANNER_CLIENT_NS
258 } // namespace spanner_internal
259 } // namespace cloud
260 } // namespace google
261 
262 #endif // GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_SPANNER_TRANSACTION_H