From 0b592098d899cfc52b6a7fca04fb5892d6a7e564 Mon Sep 17 00:00:00 2001 From: Carl Meyer Date: Thu, 31 Oct 2024 15:56:07 -0700 Subject: [PATCH] better fix for multi-revision bug --- src/function/execute.rs | 18 +++++++++--------- src/function/fetch.rs | 5 ++++- src/function/maybe_changed_after.rs | 8 ++------ src/zalsa_local.rs | 4 ++-- 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/function/execute.rs b/src/function/execute.rs index 89d1a93a4..158f94a02 100644 --- a/src/function/execute.rs +++ b/src/function/execute.rs @@ -57,15 +57,6 @@ where let mut new_value = C::execute(db, C::id_to_input(db, id)); let mut revisions = active_query.pop(); - // If the new value is equal to the old one, then it didn't - // really change, even if some of its inputs have. So we can - // "backdate" its `changed_at` revision to be the same as the - // old value. - if let Some(old_memo) = &opt_old_memo { - self.backdate_if_appropriate(old_memo, &mut revisions, &new_value); - self.diff_outputs(db, database_key_index, old_memo, &mut revisions); - } - // Did the new result we got depend on our own provisional value, in a cycle? if revisions.cycle_heads.contains(&database_key_index) { let opt_owned_last_provisional; @@ -145,6 +136,15 @@ where tracing::debug!("{database_key_index:?}: execute: result.revisions = {revisions:#?}"); + // If the new value is equal to the old one, then it didn't + // really change, even if some of its inputs have. So we can + // "backdate" its `changed_at` revision to be the same as the + // old value. + if let Some(old_memo) = &opt_old_memo { + self.backdate_if_appropriate(old_memo, &mut revisions, &new_value); + self.diff_outputs(db, database_key_index, old_memo, &mut revisions); + } + return self.insert_memo( zalsa, id, diff --git a/src/function/fetch.rs b/src/function/fetch.rs index ae4c6c376..6dcc4e3ac 100644 --- a/src/function/fetch.rs +++ b/src/function/fetch.rs @@ -90,7 +90,10 @@ where Memo::new( Some(initial_value), zalsa.current_revision(), - QueryRevisions::fixpoint_initial(database_key_index), + QueryRevisions::fixpoint_initial( + database_key_index, + zalsa.current_revision(), + ), ), ) }) diff --git a/src/function/maybe_changed_after.rs b/src/function/maybe_changed_after.rs index ad55bcf26..e0b33eb8c 100644 --- a/src/function/maybe_changed_after.rs +++ b/src/function/maybe_changed_after.rs @@ -96,12 +96,8 @@ where // the value has not logically changed. if old_memo.value.is_some() { let memo = self.execute(db, database_key_index, Some(old_memo)); - // If we get back a memo that's part of a cycle and requires further iteration to - // resolve, we can't backdate that. - if !memo.revisions.cycle_ignore { - let changed_at = memo.revisions.changed_at; - return Some(changed_at > revision); - } + let changed_at = memo.revisions.changed_at; + return Some(changed_at > revision); } // Otherwise, nothing for it: have to consider the value to have changed. diff --git a/src/zalsa_local.rs b/src/zalsa_local.rs index 1ba09b0c2..4ef67f64d 100644 --- a/src/zalsa_local.rs +++ b/src/zalsa_local.rs @@ -371,10 +371,10 @@ pub(crate) struct QueryRevisions { } impl QueryRevisions { - pub(crate) fn fixpoint_initial(query: DatabaseKeyIndex) -> Self { + pub(crate) fn fixpoint_initial(query: DatabaseKeyIndex, revision: Revision) -> Self { let cycle_heads = FxHashSet::from_iter([query]); Self { - changed_at: Revision::start(), + changed_at: revision, durability: Durability::MAX, origin: QueryOrigin::FixpointInitial, tracked_struct_ids: Default::default(),