diff options
author | Koni Marti <koni.marti@gmail.com> | 2022-11-02 22:26:48 +0100 |
---|---|---|
committer | Robin Jarry <robin@jarry.cc> | 2022-11-06 23:16:23 +0100 |
commit | 33ceb56680ba92406137ace7eee8139824446308 (patch) | |
tree | 19aa610efe7bbf643ef47525e8a296b4e45b9345 | |
parent | 6b0b5596dee5dda9fb367cbf8c82e52b9e6125a3 (diff) | |
download | aerc-33ceb56680ba92406137ace7eee8139824446308.tar.gz |
threadbuilder: streamline thread builder internals
Streamline the internals of the client-side thread builder. Handle the
jwz dummy threads explicitly and let jwz deal with message-id
collisions.
This should make the client-side threading more stable overall.
Duplicated message-ids will also be properly displayed now.
Signed-off-by: Koni Marti <koni.marti@gmail.com>
Acked-by: Tim Culverhouse <tim@timculverhouse.com>
-rw-r--r-- | lib/threadbuilder.go | 73 |
1 files changed, 30 insertions, 43 deletions
diff --git a/lib/threadbuilder.go b/lib/threadbuilder.go index b1609257..52484162 100644 --- a/lib/threadbuilder.go +++ b/lib/threadbuilder.go @@ -13,19 +13,15 @@ import ( type ThreadBuilder struct { sync.Mutex - threadBlocks map[uint32]jwz.Threadable - messageidToUid map[string]uint32 - seen map[uint32]bool - threadedUids []uint32 - iterFactory iterator.Factory + threadBlocks map[uint32]jwz.Threadable + threadedUids []uint32 + iterFactory iterator.Factory } func NewThreadBuilder(i iterator.Factory) *ThreadBuilder { tb := &ThreadBuilder{ - threadBlocks: make(map[uint32]jwz.Threadable), - messageidToUid: make(map[string]uint32), - seen: make(map[uint32]bool), - iterFactory: i, + threadBlocks: make(map[uint32]jwz.Threadable), + iterFactory: i, } return tb } @@ -48,7 +44,6 @@ func (builder *ThreadBuilder) Update(msg *models.MessageInfo) { if msg != nil { if threadable := newThreadable(msg); threadable != nil { - builder.messageidToUid[threadable.MessageThreadID()] = msg.Uid builder.threadBlocks[msg.Uid] = threadable } } @@ -70,7 +65,8 @@ func (builder *ThreadBuilder) Threads(uids []uint32, inverse bool) []*types.Thre builder.RebuildUids(threads, inverse) elapsed := time.Since(start) - logging.Infof("%d threads created in %s", len(threads), elapsed) + logging.Infof("%d threads from %d uids created in %s", len(threads), + len(uids), elapsed) return threads } @@ -98,56 +94,47 @@ func (builder *ThreadBuilder) buildAercThreads(structure jwz.Threadable, uids [] threads = append(threads, &types.Thread{Uid: uid}) } } else { - // fill threads with nil messages + // add uids for the unfetched messages for _, uid := range uids { if _, ok := builder.threadBlocks[uid]; !ok { threads = append(threads, &types.Thread{Uid: uid}) } } - // append the on-the-fly created aerc threads + + // build thread tree root := &types.Thread{Uid: 0} - builder.seen = make(map[uint32]bool) builder.buildTree(structure, root) - for iter := root.FirstChild; iter != nil; iter = iter.NextSibling { - iter.Parent = nil - threads = append(threads, iter) + + // copy top-level threads to thread slice + for thread := root.FirstChild; thread != nil; thread = thread.NextSibling { + thread.Parent = nil + threads = append(threads, thread) } + } return threads } // buildTree recursively translates the jwz threads structure into aerc threads -// builder.seen is used to avoid potential double-counting and should be empty -// on first call of this function -func (builder *ThreadBuilder) buildTree(treeNode jwz.Threadable, target *types.Thread) { - if treeNode == nil { +func (builder *ThreadBuilder) buildTree(c jwz.Threadable, parent *types.Thread) { + if c == nil || parent == nil { return } - - // deal with child - uid, ok := builder.messageidToUid[treeNode.MessageThreadID()] - if _, seen := builder.seen[uid]; ok && !seen { - builder.seen[uid] = true - childNode := &types.Thread{Uid: uid, Parent: target} - target.OrderedInsert(childNode) - builder.buildTree(treeNode.GetChild(), childNode) - } else { - builder.buildTree(treeNode.GetChild(), target) + for node := c; node != nil; node = node.GetNext() { + thread := parent + if !node.IsDummy() { + thread = builder.newThread(node, parent) + parent.OrderedInsert(thread) + } + builder.buildTree(node.GetChild(), thread) } +} - // deal with siblings - for next := treeNode.GetNext(); next != nil; next = next.GetNext() { - - uid, ok := builder.messageidToUid[next.MessageThreadID()] - if _, seen := builder.seen[uid]; ok && !seen { - builder.seen[uid] = true - nn := &types.Thread{Uid: uid, Parent: target} - target.OrderedInsert(nn) - builder.buildTree(next.GetChild(), nn) - } else { - builder.buildTree(next.GetChild(), target) - } +func (builder *ThreadBuilder) newThread(c jwz.Threadable, parent *types.Thread) *types.Thread { + if threadable, ok := c.(*threadable); ok { + return &types.Thread{Uid: threadable.MsgInfo.Uid, Parent: parent} } + return nil } func (builder *ThreadBuilder) sortThreads(threads []*types.Thread, orderedUids []uint32) { |