Prevent panics when remote datastore transactions fail to start

This commit is contained in:
Tobie Morgan Hitchcock 2022-08-29 13:20:30 +01:00
parent cdf244f0f5
commit b9fc84bf18
2 changed files with 64 additions and 47 deletions

View file

@ -79,8 +79,7 @@ impl<'a> Executor<'a> {
async fn cancel(&mut self, local: bool) { async fn cancel(&mut self, local: bool) {
if local { if local {
match self.txn.as_ref() { if let Some(txn) = self.txn.as_ref() {
Some(txn) => {
let txn = txn.clone(); let txn = txn.clone();
let mut txn = txn.lock().await; let mut txn = txn.lock().await;
if txn.cancel().await.is_err() { if txn.cancel().await.is_err() {
@ -88,8 +87,6 @@ impl<'a> Executor<'a> {
} }
self.txn = None; self.txn = None;
} }
None => unreachable!(),
}
} }
} }
@ -212,6 +209,12 @@ impl<'a> Executor<'a> {
Statement::Set(stm) => { Statement::Set(stm) => {
// Create a transaction // Create a transaction
let loc = self.begin(stm.writeable()).await; let loc = self.begin(stm.writeable()).await;
// Check the transaction
match self.err {
// We failed to create a transaction
true => Err(Error::TxFailure),
// The transaction began successfully
false => {
// Process the statement // Process the statement
match stm.compute(&ctx, &opt, &self.txn(), None).await { match stm.compute(&ctx, &opt, &self.txn(), None).await {
Ok(val) => { Ok(val) => {
@ -227,6 +230,8 @@ impl<'a> Executor<'a> {
// Return nothing // Return nothing
Ok(Value::None) Ok(Value::None)
} }
}
}
// Process all other normal statements // Process all other normal statements
_ => match self.err { _ => match self.err {
// This transaction has failed // This transaction has failed
@ -235,6 +240,12 @@ impl<'a> Executor<'a> {
false => { false => {
// Create a transaction // Create a transaction
let loc = self.begin(stm.writeable()).await; let loc = self.begin(stm.writeable()).await;
// Check the transaction
match self.err {
// We failed to create a transaction
true => Err(Error::TxFailure),
// The transaction began successfully
false => {
// Process the statement // Process the statement
let res = match stm.timeout() { let res = match stm.timeout() {
// There is a timeout clause // There is a timeout clause
@ -264,6 +275,8 @@ impl<'a> Executor<'a> {
// Return the result // Return the result
res res
} }
}
}
}, },
}; };
// Get the statement end time // Get the statement end time

View file

@ -21,6 +21,10 @@ pub enum Error {
#[error("There was a problem with a datastore transaction: {0}")] #[error("There was a problem with a datastore transaction: {0}")]
Tx(String), Tx(String),
/// There was an error when starting a new datastore transaction
#[error("There was an error when starting a new datastore transaction")]
TxFailure,
/// The transaction was already cancelled or committed /// The transaction was already cancelled or committed
#[error("Couldn't update a finished transaction")] #[error("Couldn't update a finished transaction")]
TxFinished, TxFinished,