find cycle recovery strategy for a given cycle

This commit is contained in:
Niko Matsakis 2021-10-25 05:37:05 -04:00
parent fc826b0689
commit bcffa4a836
3 changed files with 32 additions and 2 deletions

View file

@ -378,6 +378,7 @@ where
Err(err) => {
let err = runtime.report_unexpected_cycle(
db.ops_database(),
self.database_key_index,
err,
revision_now,

View file

@ -90,6 +90,7 @@ pub trait QueryFunction: Query {
/// Cycle recovery strategy: Is this query capable of recovering from
/// a cycle that results from executing the function? If so, how?
#[derive(Debug, PartialEq, Eq)]
pub enum CycleRecoveryStrategy {
/// Cannot recover from cycles: panic.
///

View file

@ -1,6 +1,7 @@
use crate::plumbing::CycleDetected;
use crate::durability::Durability;
use crate::plumbing::{CycleDetected, CycleRecoveryStrategy};
use crate::revision::{AtomicRevision, Revision};
use crate::{durability::Durability, Cancelled};
use crate::Cancelled;
use crate::{CycleError, Database, DatabaseKeyIndex, Event, EventKind};
use log::debug;
use parking_lot::lock_api::{RawRwLock, RawRwLockRecursive};
@ -287,6 +288,7 @@ impl Runtime {
/// Obviously, this should be user configurable at some point.
pub(crate) fn report_unexpected_cycle(
&self,
db: &dyn Database,
database_key_index: DatabaseKeyIndex,
error: CycleDetected,
changed_at: Revision,
@ -297,6 +299,11 @@ impl Runtime {
);
let cycle = self.find_cycle_participants(database_key_index, error);
let crs = self.mutual_cycle_recovery_strategy(db, &cycle);
debug!(
"cycle recovery strategy {:?} for participants {:?}",
crs, cycle
);
CycleError {
cycle,
changed_at,
@ -304,6 +311,27 @@ impl Runtime {
}
}
fn mutual_cycle_recovery_strategy(
&self,
db: &dyn Database,
cycle: &[DatabaseKeyIndex],
) -> CycleRecoveryStrategy {
let crs = db.cycle_recovery_strategy(cycle[0]);
if let Some(key) = cycle[1..]
.iter()
.copied()
.find(|&key| db.cycle_recovery_strategy(key) != crs)
{
debug!("mutual_cycle_recovery_strategy: cycle had multiple strategies ({:?} for {:?} vs {:?} for {:?})",
crs, cycle[0],
db.cycle_recovery_strategy(key), key
);
CycleRecoveryStrategy::Panic
} else {
crs
}
}
fn find_cycle_participants(
&self,
database_key_index: DatabaseKeyIndex,