tui: prioritize live pending pods in picker
This commit is contained in:
parent
08397f3f3b
commit
56bb46634c
|
|
@ -360,4 +360,37 @@ mod tests {
|
|||
fn picker_title_names_pods_not_sessions() {
|
||||
assert_eq!(picker_title(), "resume pod pick a pod");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn picker_row_shows_live_pending_preview_and_runtime_segment_id() {
|
||||
let segment_id = session_store::new_segment_id();
|
||||
let entry = PodList::from_sources(
|
||||
PodVisibilitySource::ResumePicker,
|
||||
vec![],
|
||||
vec![crate::pod_list::LivePodInfo {
|
||||
pod_name: "pending".to_string(),
|
||||
socket_path: PathBuf::from("/tmp/pending.sock"),
|
||||
status: Some(protocol::PodStatus::Idle),
|
||||
reachable: true,
|
||||
segment_id: Some(segment_id),
|
||||
summary: crate::pod_list::PodEntrySummary::default(),
|
||||
}],
|
||||
None,
|
||||
10,
|
||||
)
|
||||
.entries
|
||||
.into_iter()
|
||||
.next()
|
||||
.unwrap();
|
||||
|
||||
let text = row_line(&entry, false)
|
||||
.spans
|
||||
.iter()
|
||||
.map(|span| span.content.as_ref())
|
||||
.collect::<String>();
|
||||
|
||||
assert!(text.contains("[live]"));
|
||||
assert!(text.contains("[live, pending segment]"));
|
||||
assert!(text.contains(&format!("g:{}", short_id(segment_id))));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,9 +48,9 @@ impl PodList {
|
|||
entry.finalize();
|
||||
}
|
||||
entries.sort_by(|a, b| {
|
||||
b.summary
|
||||
.updated_at
|
||||
.cmp(&a.summary.updated_at)
|
||||
b.has_reachable_live()
|
||||
.cmp(&a.has_reachable_live())
|
||||
.then_with(|| b.summary.updated_at.cmp(&a.summary.updated_at))
|
||||
.then_with(|| a.name.cmp(&b.name))
|
||||
});
|
||||
entries.truncate(max_entries);
|
||||
|
|
@ -164,10 +164,27 @@ impl PodListEntry {
|
|||
}
|
||||
|
||||
fn finalize(&mut self) {
|
||||
self.fill_live_pending_preview();
|
||||
self.diagnostics = build_diagnostics(self);
|
||||
self.actions = build_actions(self);
|
||||
}
|
||||
|
||||
fn has_reachable_live(&self) -> bool {
|
||||
self.live.as_ref().is_some_and(|live| live.reachable)
|
||||
}
|
||||
|
||||
fn fill_live_pending_preview(&mut self) {
|
||||
if !self.has_reachable_live() || self.summary.updated_at != 0 {
|
||||
return;
|
||||
}
|
||||
let preview_is_pending = self.summary.preview.as_deref() == Some("[pending segment]");
|
||||
let preview_is_incomplete = self.summary.preview.is_none() || preview_is_pending;
|
||||
if preview_is_incomplete && (self.summary.active_segment_id.is_some() || preview_is_pending)
|
||||
{
|
||||
self.summary.preview = Some("[live, pending segment]".to_string());
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn attach_socket_path(&self) -> Option<&Path> {
|
||||
self.live
|
||||
.as_ref()
|
||||
|
|
@ -593,6 +610,98 @@ mod tests {
|
|||
assert_eq!(entries[1].name, "older");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reachable_live_rows_sort_before_stopped_rows_before_truncation() {
|
||||
let stopped = (0..10)
|
||||
.map(|index| stopped_info_with_updated_at(&format!("stopped-{index}"), 1_000 - index))
|
||||
.collect::<Vec<_>>();
|
||||
let live = live_info_with_updated_at("live-pending", PodStatus::Idle, 0);
|
||||
|
||||
let entries = PodList::from_sources(SOURCE, stopped, vec![live], None, 10).entries;
|
||||
|
||||
assert_eq!(entries.len(), 10);
|
||||
assert_eq!(entries[0].name, "live-pending");
|
||||
assert!(entries.iter().all(|entry| entry.name != "stopped-9"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reachable_live_sort_does_not_promote_unreachable_registry_allocations() {
|
||||
let mut unreachable = live_info_with_updated_at("unreachable", PodStatus::Idle, 0);
|
||||
unreachable.reachable = false;
|
||||
unreachable.status = None;
|
||||
|
||||
let entries = PodList::from_sources(
|
||||
SOURCE,
|
||||
vec![stopped_info_with_updated_at("stopped", 100)],
|
||||
vec![unreachable],
|
||||
None,
|
||||
10,
|
||||
)
|
||||
.entries;
|
||||
|
||||
assert_eq!(entries[0].name, "stopped");
|
||||
assert_eq!(entries[1].name, "unreachable");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn live_pending_with_runtime_segment_is_attach_only_and_gets_pending_preview() {
|
||||
let session_id = new_session_id();
|
||||
let runtime_segment_id = new_segment_id();
|
||||
let entry = single_entry(PodList::from_sources(
|
||||
SOURCE,
|
||||
vec![pending_metadata_info("pending", session_id)],
|
||||
vec![live_info_with_segment(
|
||||
"pending",
|
||||
PodStatus::Idle,
|
||||
runtime_segment_id,
|
||||
)],
|
||||
None,
|
||||
10,
|
||||
));
|
||||
|
||||
assert_eq!(entry.name, "pending");
|
||||
assert_eq!(entry.summary.active_session_id, Some(session_id));
|
||||
assert_eq!(entry.summary.active_segment_id, Some(runtime_segment_id));
|
||||
assert_eq!(
|
||||
entry.summary.preview.as_deref(),
|
||||
Some("[live, pending segment]")
|
||||
);
|
||||
assert!(entry.actions.can_open);
|
||||
assert!(!entry.actions.can_restore);
|
||||
assert_eq!(
|
||||
entry.attach_socket_path(),
|
||||
Some(Path::new("/tmp/pending.sock"))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn live_only_runtime_segment_is_attach_only_and_not_restorable() {
|
||||
let runtime_segment_id = new_segment_id();
|
||||
let entry = single_entry(PodList::from_sources(
|
||||
SOURCE,
|
||||
vec![],
|
||||
vec![live_info_with_segment(
|
||||
"runtime-only",
|
||||
PodStatus::Idle,
|
||||
runtime_segment_id,
|
||||
)],
|
||||
None,
|
||||
10,
|
||||
));
|
||||
|
||||
assert_eq!(entry.summary.active_segment_id, Some(runtime_segment_id));
|
||||
assert_eq!(
|
||||
entry.summary.preview.as_deref(),
|
||||
Some("[live, pending segment]")
|
||||
);
|
||||
assert!(entry.actions.can_open);
|
||||
assert!(!entry.actions.can_restore);
|
||||
assert_eq!(
|
||||
entry.attach_socket_path(),
|
||||
Some(Path::new("/tmp/runtime-only.sock"))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn stored_only_row_can_restore_and_open_but_not_direct_send() {
|
||||
let dir = tempdir().unwrap();
|
||||
|
|
@ -820,10 +929,42 @@ mod tests {
|
|||
)
|
||||
}
|
||||
|
||||
fn pending_metadata_info(pod_name: &str, session_id: SessionId) -> StoredPodInfo {
|
||||
StoredPodInfo {
|
||||
pod_name: pod_name.to_string(),
|
||||
metadata_state: StoredMetadataState::Present,
|
||||
active_session_id: Some(session_id),
|
||||
active_segment_id: None,
|
||||
updated_at: 0,
|
||||
preview: Some("[pending segment]".to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
fn stopped_info_with_updated_at(pod_name: &str, updated_at: u64) -> StoredPodInfo {
|
||||
StoredPodInfo {
|
||||
pod_name: pod_name.to_string(),
|
||||
metadata_state: StoredMetadataState::Present,
|
||||
active_session_id: None,
|
||||
active_segment_id: None,
|
||||
updated_at,
|
||||
preview: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn live_info(pod_name: &str, status: PodStatus) -> LivePodInfo {
|
||||
live_info_with_updated_at(pod_name, status, 0)
|
||||
}
|
||||
|
||||
fn live_info_with_segment(
|
||||
pod_name: &str,
|
||||
status: PodStatus,
|
||||
segment_id: SegmentId,
|
||||
) -> LivePodInfo {
|
||||
let mut info = live_info(pod_name, status);
|
||||
info.segment_id = Some(segment_id);
|
||||
info
|
||||
}
|
||||
|
||||
fn live_info_with_updated_at(
|
||||
pod_name: &str,
|
||||
status: PodStatus,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user