fix: remove cached task children list

This commit is contained in:
xeruf 2024-09-22 16:47:26 +02:00
parent 753afad2fd
commit afe3fa8670
3 changed files with 37 additions and 50 deletions

View File

@ -326,10 +326,6 @@ async fn main() -> Result<()> {
} }
loop { loop {
trace!("All Root Tasks:\n{}", relays.iter().map(|(url, tasks)|
format!("{}: [{}]",
url.as_ref().map(ToString::to_string).unwrap_or(LOCAL_RELAY_NAME.to_string()),
tasks.children_for(None).map(|task| tasks.get_task_title(task.get_id())).join("; "))).join("\n"));
println!(); println!();
let tasks = relays.get(&selected_relay).unwrap(); let tasks = relays.get(&selected_relay).unwrap();
let prompt = format!( let prompt = format!(

View File

@ -24,9 +24,6 @@ pub(crate) struct Task {
pub(crate) tags: Option<BTreeSet<Tag>>, pub(crate) tags: Option<BTreeSet<Tag>>,
/// Task references derived from the event tags /// Task references derived from the event tags
refs: Vec<(String, EventId)>, refs: Vec<(String, EventId)>,
/// Reference to children, populated dynamically
pub(crate) children: HashSet<EventId>,
/// Events belonging to this task, such as state updates and notes /// Events belonging to this task, such as state updates and notes
pub(crate) props: BTreeSet<Event>, pub(crate) props: BTreeSet<Event>,
} }
@ -52,7 +49,6 @@ impl Task {
}); });
// Separate refs for dependencies // Separate refs for dependencies
Task { Task {
children: Default::default(),
props: Default::default(), props: Default::default(),
tags: Some(tags).filter(|t: &BTreeSet<Tag>| !t.is_empty()), tags: Some(tags).filter(|t: &BTreeSet<Tag>| !t.is_empty()),
refs, refs,

View File

@ -24,6 +24,27 @@ fn now() -> Timestamp {
} }
type TaskMap = HashMap<EventId, Task>; type TaskMap = HashMap<EventId, Task>;
trait TaskMapMethods {
fn children_of<'a>(&'a self, task: &'a Task) -> impl Iterator<Item=&Task> + 'a;
fn children_for<'a>(&'a self, id: Option<&'a EventId>) -> impl Iterator<Item=&Task> + 'a;
fn children_ids_for<'a>(&'a self, id: &'a EventId) -> impl Iterator<Item=&EventId> + 'a;
}
impl TaskMapMethods for TaskMap {
fn children_of<'a>(&'a self, task: &'a Task) -> impl Iterator<Item=&Task> + 'a {
self.children_for(Some(task.get_id()))
}
fn children_for<'a>(&'a self, id: Option<&'a EventId>) -> impl Iterator<Item=&Task> + 'a {
self.values()
.filter(move |t| t.parent_id() == id)
}
fn children_ids_for<'a>(&'a self, id: &'a EventId) -> impl Iterator<Item=&EventId> + 'a {
self.children_for(Some(id))
.map(|t| t.get_id())
}
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub(crate) struct Tasks { pub(crate) struct Tasks {
/// The Tasks /// The Tasks
@ -271,7 +292,7 @@ impl Tasks {
_ => { _ => {
let mut sum = 0f32; let mut sum = 0f32;
let mut count = 0; let mut count = 0;
for prog in self.children_ids_for(task.get_id()).filter_map(|e| self.total_progress(e)) { for prog in self.tasks.children_ids_for(task.get_id()).filter_map(|e| self.total_progress(e)) {
sum += prog; sum += prog;
count += 1; count += 1;
} }
@ -314,7 +335,6 @@ impl Tasks {
ParentIterator { ParentIterator {
tasks: &self.tasks, tasks: &self.tasks,
current: id, current: id,
prev: None,
} }
} }
@ -345,7 +365,7 @@ impl Tasks {
iter.flat_map(move |task| { iter.flat_map(move |task| {
let new_depth = depth - 1; let new_depth = depth - 1;
if new_depth > 0 { if new_depth > 0 {
let mut children = self.resolve_tasks_rec(self.children_of(&task), sparse, new_depth); let mut children = self.resolve_tasks_rec(self.tasks.children_of(&task), sparse, new_depth);
if !children.is_empty() { if !children.is_empty() {
if !sparse { if !sparse {
children.push(task); children.push(task);
@ -380,21 +400,6 @@ impl Tasks {
self.get_position_ref().and_then(|id| self.get_by_id(id)) self.get_position_ref().and_then(|id| self.get_by_id(id))
} }
pub(crate) fn children_of<'a>(&'a self, task: &'a Task) -> impl Iterator<Item=&Task> + 'a {
self.children_for(Some(task.get_id()))
}
pub(crate) fn children_for<'a>(&'a self, id: Option<&'a EventId>) -> impl Iterator<Item=&Task> + 'a {
self.tasks
.values()
.filter(move |t| t.parent_id() == id)
}
pub(crate) fn children_ids_for<'a>(&'a self, id: &'a EventId) -> impl Iterator<Item=&EventId> + 'a {
self.children_for(Some(id))
.map(|t| t.get_id())
}
fn filter(&self, task: &Task) -> bool { fn filter(&self, task: &Task) -> bool {
self.state.matches(task) && self.state.matches(task) &&
task.tags.as_ref().map_or(true, |tags| { task.tags.as_ref().map_or(true, |tags| {
@ -408,10 +413,10 @@ impl Tasks {
} }
pub(crate) fn filtered_tasks<'a>(&'a self, position: Option<&'a EventId>, sparse: bool) -> Vec<&'a Task> { pub(crate) fn filtered_tasks<'a>(&'a self, position: Option<&'a EventId>, sparse: bool) -> Vec<&'a Task> {
let mut current = self.resolve_tasks(self.children_for(position), sparse); let mut current = self.resolve_tasks(self.tasks.children_for(position), sparse);
if current.is_empty() { if current.is_empty() {
if !self.tags.is_empty() { if !self.tags.is_empty() {
let mut children = self.children_for(self.get_position_ref()).peekable(); let mut children = self.tasks.children_for(self.get_position_ref()).peekable();
if children.peek().is_some() { if children.peek().is_some() {
current = self.resolve_tasks_rec(children, true, 9); current = self.resolve_tasks_rec(children, true, 9);
if sparse { if sparse {
@ -517,7 +522,7 @@ impl Tasks {
} }
fn get_property(&self, task: &Task, str: &str) -> String { fn get_property(&self, task: &Task, str: &str) -> String {
let mut children = self.children_of(task).peekable(); let mut children = self.tasks.children_of(task).peekable();
let progress = let progress =
self.total_progress(task.get_id()) self.total_progress(task.get_id())
.filter(|_| children.peek().is_some()); .filter(|_| children.peek().is_some());
@ -826,7 +831,7 @@ impl Tasks {
self.get_by_id(pos) self.get_by_id(pos)
.map(|task| { .map(|task| {
if task.pure_state() == State::Procedure { if task.pure_state() == State::Procedure {
self.children_of(task) self.tasks.children_of(task)
.max() .max()
.map(|t| tags.push(self.make_event_tag(&t.event, MARKER_DEPENDS))); .map(|t| tags.push(self.make_event_tag(&t.event, MARKER_DEPENDS)));
} }
@ -953,9 +958,6 @@ impl Tasks {
} else { } else {
let id = event.id; let id = event.id;
let task = Task::new(event); let task = Task::new(event);
task.find_refs(MARKER_PARENT).for_each(|parent| {
self.tasks.get_mut(parent).map(|t| { t.children.insert(id); });
});
self.tasks.insert(id, task); self.tasks.insert(id, task);
} }
} }
@ -1360,8 +1362,7 @@ impl<'a> ChildIterator<'a> {
if let Some(task) = self.tasks.get(id) { if let Some(task) = self.tasks.get(id) {
let take = filter(task); let take = filter(task);
if take.takes_children() { if take.takes_children() {
self.queue.reserve(task.children.len()); self.queue_children_of(&task);
self.queue.extend(task.children.iter());
} }
if take.takes_self() { if take.takes_self() {
self.check_depth(); self.check_depth();
@ -1372,6 +1373,10 @@ impl<'a> ChildIterator<'a> {
self.next_filtered(filter) self.next_filtered(filter)
}) })
} }
fn queue_children_of(&mut self, task: &'a Task) {
self.queue.extend(self.tasks.children_ids_for(task.get_id()));
}
} }
impl FusedIterator for ChildIterator<'_> {} impl FusedIterator for ChildIterator<'_> {}
impl<'a> Iterator for ChildIterator<'a> { impl<'a> Iterator for ChildIterator<'a> {
@ -1389,8 +1394,7 @@ impl<'a> Iterator for ChildIterator<'a> {
} }
} }
Some(task) => { Some(task) => {
self.queue.reserve(task.children.len()); self.queue_children_of(&task);
self.queue.extend(task.children.iter());
} }
} }
self.check_depth(); self.check_depth();
@ -1402,23 +1406,12 @@ impl<'a> Iterator for ChildIterator<'a> {
struct ParentIterator<'a> { struct ParentIterator<'a> {
tasks: &'a TaskMap, tasks: &'a TaskMap,
current: Option<EventId>, current: Option<EventId>,
/// Inexpensive helper to assert correctness
prev: Option<EventId>,
} }
impl<'a> Iterator for ParentIterator<'a> { impl<'a> Iterator for ParentIterator<'a> {
type Item = &'a Task; type Item = &'a Task;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
self.current.and_then(|id| self.tasks.get(&id)).map(|t| { self.current.and_then(|id| self.tasks.get(&id)).map(|t| {
self.prev.inspect(|id| {
// Fails if child is discovered before parent
// Need to reverse add as well
//assert!(t.children.contains(id))
if !t.children.contains(id) {
warn!("\"{}\" is not properly referencing child \"{}\"", t.get_title(), self.tasks.get(id).map_or(id.to_string(), |cht| cht.get_title()))
}
});
self.prev = self.current;
self.current = t.parent_id().cloned(); self.current = t.parent_id().cloned();
t t
}) })
@ -1502,9 +1495,11 @@ mod tasks_test {
tasks.make_task_and_enter("proc: tags", State::Procedure); tasks.make_task_and_enter("proc: tags", State::Procedure);
assert_eq!(tasks.get_own_events_history().count(), 1); assert_eq!(tasks.get_own_events_history().count(), 1);
let side = tasks.submit(build_task("side", vec![tasks.make_event_tag(&tasks.get_current_task().unwrap().event, MARKER_DEPENDS)], None)); let side = tasks.submit(build_task("side", vec![tasks.make_event_tag(&tasks.get_current_task().unwrap().event, MARKER_DEPENDS)], None));
assert_eq!(tasks.get_current_task().unwrap().children, HashSet::<EventId>::new()); assert_eq!(tasks.visible_tasks(),
Vec::<&Task>::new());
let sub_id = tasks.make_task("sub"); let sub_id = tasks.make_task("sub");
assert_eq!(tasks.get_current_task().unwrap().children, HashSet::from([sub_id])); assert_eq!(tasks.visible_tasks().iter().map(|t| t.event.id).collect_vec(),
Vec::from([sub_id]));
assert_eq!(tasks.len(), 3); assert_eq!(tasks.len(), 3);
let sub = tasks.get_by_id(&sub_id).unwrap(); let sub = tasks.get_by_id(&sub_id).unwrap();
assert_eq!(sub.get_dependendees(), Vec::<&EventId>::new()); assert_eq!(sub.get_dependendees(), Vec::<&EventId>::new());