}
// addMessage builds the leaf of message when it needs no model call, or else
-// adds the leaf to the queue. Then it appends the leaf to the views.
+// adds the leaf to the queue. Then it appends the leaf to the views. A crash can
+// stop an append after the leaf build and before the view save, so a leaf that
+// is built already stays as it is, and restoreQueue settles its parent.
func (m *Memory) addMessage(message Message) error {
+ built, err := m.tree.Built(0, message.ID)
+ if err != nil {
+ return err
+ }
+
leaf, free := freeLeaf(message)
- if free {
- err := m.build(leaf)
+ switch {
+ case built:
+ case free:
+ err = m.build(leaf)
if err != nil {
return err
}
- } else {
+ default:
m.queue.AddLeaf(message.ID)
}
return m.cview.Context(end)
}
-
-// writeFileAtomic replaces the file at path with data through a temporary file
-// and a rename. A reader or a crash of the process sees the old file or the new
-// file, never a part of one.
-func writeFileAtomic(path string, data []byte) error {
- file, err := os.CreateTemp(filepath.Dir(path), "."+filepath.Base(path)+".*")
- if err != nil {
- return fmt.Errorf("create temporary file: %w", err)
- }
-
- _, err = file.Write(data)
- err = errors.Join(err, file.Close())
- if err == nil {
- err = os.Rename(file.Name(), path)
- }
-
- if err != nil {
- return errors.Join(fmt.Errorf("replace file: %w", err), os.Remove(file.Name()))
- }
-
- return nil
-}