fix(desktop): invalidate filtered catalog on changed hosted head
This commit is contained in:
@@ -396,6 +396,19 @@ impl App {
|
||||
let catalog_changed = match &result {
|
||||
Ok(Outcome::Remote(remote)) => {
|
||||
matches!(request.operation, Operation::Publish | Operation::Save)
|
||||
// A changed bound head can enter/leave the active
|
||||
// filter or page even when no row was displayed.
|
||||
|| self.hosted.session.as_ref().is_some_and(|session| {
|
||||
session.connection.base() == request.connection.base()
|
||||
&& session.resource_id == remote.resource_id
|
||||
&& session.etag != remote.etag
|
||||
})
|
||||
|| self.hosted.uncertain.as_ref().is_some_and(|failed| {
|
||||
failed.operation == Operation::Save
|
||||
&& failed.connection.base() == request.connection.base()
|
||||
&& failed.resource_id == Some(remote.resource_id)
|
||||
&& failed.etag.as_ref().is_some_and(|etag| etag != &remote.etag)
|
||||
})
|
||||
|| self.hosted.catalog.iter().any(|item| {
|
||||
item.resource_id == remote.resource_id
|
||||
&& item.revision != remote.revision
|
||||
|
||||
@@ -729,3 +729,89 @@ fn hosted_catalog_invalidation_follows_service_writes_and_observed_revision_chan
|
||||
"Leaving the hosted destination cannot make old results fresh"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hosted_new_revision_invalidates_filtered_catalog_even_without_a_displayed_row() {
|
||||
let mut app = App::with_project(Project::empty());
|
||||
rename(&mut app, "Original");
|
||||
let resource = bind(&mut app);
|
||||
send(&mut app, Event::Query("Renamed".into()));
|
||||
send(&mut app, Event::Connect);
|
||||
complete(
|
||||
&mut app,
|
||||
Ok(Outcome::Catalog(crate::hosted::client::Catalog {
|
||||
items: vec![],
|
||||
next_after: None,
|
||||
})),
|
||||
);
|
||||
assert!(!app.hosted.catalog_stale);
|
||||
assert!(
|
||||
app.hosted
|
||||
.catalog_message()
|
||||
.unwrap()
|
||||
.starts_with("No models found")
|
||||
);
|
||||
|
||||
let mut unchanged = remote(app.document.snapshot(), resource, 1);
|
||||
unchanged.etag = app.hosted.session.as_ref().unwrap().etag.clone();
|
||||
send(&mut app, Event::Check);
|
||||
complete(&mut app, Ok(Outcome::Remote(unchanged)));
|
||||
assert!(
|
||||
!app.hosted.catalog_stale,
|
||||
"An unchanged bound head keeps the filtered snapshot fresh"
|
||||
);
|
||||
|
||||
// A different engineer changes the hosted model so it now matches the filter.
|
||||
let mut changed = Document::from_bundle(app.document.bundle().clone(), LIMITS).unwrap();
|
||||
changed
|
||||
.execute(Command::Rename(changed.project().id, "Renamed".into()))
|
||||
.unwrap();
|
||||
send(&mut app, Event::Check);
|
||||
complete(
|
||||
&mut app,
|
||||
Ok(Outcome::Remote(remote(changed.snapshot(), resource, 2))),
|
||||
);
|
||||
assert_eq!(app.hosted.review.as_ref().unwrap().remote.revision, 2);
|
||||
assert!(
|
||||
app.hosted.request.is_none(),
|
||||
"No polling or automatic catalog request"
|
||||
);
|
||||
assert!(
|
||||
app.hosted.catalog_stale,
|
||||
"Known newer revision can change membership in an empty filtered catalog"
|
||||
);
|
||||
assert!(
|
||||
!app.hosted
|
||||
.catalog_message()
|
||||
.unwrap()
|
||||
.starts_with("No models found")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hosted_changed_bound_head_does_not_invalidate_another_services_empty_filter() {
|
||||
let mut app = App::with_project(Project::empty());
|
||||
let resource = bind(&mut app);
|
||||
send(&mut app, Event::Base("http://127.0.0.1:9876".into()));
|
||||
send(&mut app, Event::Query("Renamed".into()));
|
||||
send(&mut app, Event::Connect);
|
||||
complete(
|
||||
&mut app,
|
||||
Ok(Outcome::Catalog(crate::hosted::client::Catalog {
|
||||
items: vec![],
|
||||
next_after: None,
|
||||
})),
|
||||
);
|
||||
send(&mut app, Event::Check);
|
||||
let changed = remote(app.document.snapshot(), resource, 2);
|
||||
complete(&mut app, Ok(Outcome::Remote(changed)));
|
||||
assert!(app.hosted.review.is_some());
|
||||
assert!(!app.hosted.catalog_stale);
|
||||
assert!(
|
||||
app.hosted
|
||||
.catalog_message()
|
||||
.unwrap()
|
||||
.starts_with("No models found")
|
||||
);
|
||||
assert!(app.hosted.request.is_none());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user