spanner_rs/
transaction.rs

1use std::time::Duration;
2use std::time::SystemTime;
3
4use google_api_proto::google::spanner::v1 as proto;
5
6/// Specifies the bounds withing wich to make reads in Spanner.
7///
8/// See [the Spanner Documentation](https://cloud.google.com/spanner/docs/reference/rpc/google.spanner.v1#google.spanner.v1.TransactionOptions.ReadOnly)
9#[derive(Clone, Debug)]
10pub enum TimestampBound {
11    /// Read at a timestamp where all previously committed transactions are visible.
12    ///
13    /// Strong reads are guaranteed to see the effects of all transactions that have committed before the start of the read.
14    /// Furthermore, all rows yielded by a single read are consistent with each other -- if any part of the read observes a transaction, all parts of the read see the transaction.
15    Strong,
16
17    /// Executes all reads at the given timestamp.
18    ///
19    /// Unlike other modes, reads at a specific timestamp are repeatable; the same read at the same timestamp always returns the same data.
20    /// If the timestamp is in the future, the read will block until the specified timestamp, modulo the read's deadline.
21    ///
22    /// Useful for large scale consistent reads such as mapreduces, or for coordinating many reads against a consistent snapshot of the data.
23    ReadTimestamp(SystemTime),
24
25    /// Executes all reads at a timestamp >= the provided timestamp.
26    ///
27    /// This is useful for requesting fresher data than some previous read,
28    /// or data that is fresh enough to observe the effects of some previously committed transaction whose timestamp is known.
29    MinReadTimestamp(SystemTime),
30
31    /// Executes all reads at a timestamp that is `ExactStaleness` old. The timestamp is chosen soon after the read is started.
32    ///
33    /// Guarantees that all writes that have committed more than the specified number of seconds ago are visible.
34    ExactStaleness(Duration),
35
36    /// Read data at a timestamp `>= now() - MaxStaleness` seconds.
37    ///
38    /// Guarantees that all writes that have committed more than the specified number of seconds ago are visible.
39    MaxStaleness(Duration),
40}
41
42impl TryFrom<TimestampBound> for proto::transaction_options::read_only::TimestampBound {
43    type Error = super::Error;
44
45    fn try_from(value: TimestampBound) -> Result<Self, Self::Error> {
46        match value {
47            TimestampBound::Strong => {
48                Ok(proto::transaction_options::read_only::TimestampBound::Strong(true))
49            }
50            TimestampBound::ReadTimestamp(timestamp) => Ok(
51                proto::transaction_options::read_only::TimestampBound::ReadTimestamp(
52                    timestamp.into(),
53                ),
54            ),
55            TimestampBound::MinReadTimestamp(timestamp) => Ok(
56                proto::transaction_options::read_only::TimestampBound::MinReadTimestamp(
57                    timestamp.into(),
58                ),
59            ),
60            TimestampBound::MaxStaleness(duration) => Ok(
61                proto::transaction_options::read_only::TimestampBound::MaxStaleness(
62                    duration
63                        .try_into()
64                        .map_err(|_| super::Error::Client(format!("invalid bound {duration:?}")))?,
65                ),
66            ),
67            TimestampBound::ExactStaleness(duration) => Ok(
68                proto::transaction_options::read_only::TimestampBound::ExactStaleness(
69                    duration
70                        .try_into()
71                        .map_err(|_| super::Error::Client(format!("invalid bound {duration:?}")))?,
72                ),
73            ),
74        }
75    }
76}
77
78#[derive(Clone, Debug)]
79pub(crate) enum TransactionSelector {
80    SingleUse(Option<TimestampBound>),
81    Id(Transaction),
82    Begin,
83}
84
85impl TryFrom<TransactionSelector> for proto::TransactionSelector {
86    type Error = super::Error;
87    fn try_from(value: TransactionSelector) -> Result<Self, Self::Error> {
88        match value {
89            TransactionSelector::SingleUse(bound) => Ok(proto::TransactionSelector {
90                selector: Some(proto::transaction_selector::Selector::SingleUse(
91                    proto::TransactionOptions {
92                        mode: Some(proto::transaction_options::Mode::ReadOnly(
93                            proto::transaction_options::ReadOnly {
94                                return_read_timestamp: false,
95                                timestamp_bound: match bound {
96                                    Some(bound) => Some(bound.try_into()?),
97                                    None => None,
98                                },
99                            },
100                        )),
101                    },
102                )),
103            }),
104            TransactionSelector::Id(tx) => Ok(proto::TransactionSelector {
105                selector: Some(proto::transaction_selector::Selector::Id(tx.spanner_tx.id)),
106            }),
107            TransactionSelector::Begin => Ok(proto::TransactionSelector {
108                selector: Some(proto::transaction_selector::Selector::Begin(
109                    proto::TransactionOptions {
110                        mode: Some(proto::transaction_options::Mode::ReadWrite(
111                            proto::transaction_options::ReadWrite {},
112                        )),
113                    },
114                )),
115            }),
116        }
117    }
118}
119
120#[derive(Debug, Clone)]
121pub(crate) struct Transaction {
122    spanner_tx: proto::Transaction,
123}
124
125impl Transaction {
126    pub(crate) fn id(&self) -> &prost::bytes::Bytes {
127        &self.spanner_tx.id
128    }
129}
130
131impl From<proto::Transaction> for Transaction {
132    fn from(spanner_tx: proto::Transaction) -> Self {
133        Transaction { spanner_tx }
134    }
135}
136
137impl From<Transaction> for proto::Transaction {
138    fn from(tx: Transaction) -> Self {
139        tx.spanner_tx
140    }
141}