]> git.giacomolli.uk - onechat/blobdiff - memory.go
Run subagents in the background with spawn
[onechat] / memory.go
index 9846c9817458f77cc0c92febb0a037aa4ff86dfa..0fd7d835f584bdea877f09bc063aebe969ddf1fa 100644 (file)
--- a/memory.go
+++ b/memory.go
@@ -12,8 +12,14 @@ import (
        "time"
 )
 
-// errMemoryNoView tells that a chat has messages but no saved view.
-var errMemoryNoView = errors.New("the chat has messages but no saved view")
+var (
+       // errMemoryNoView tells that a chat has messages but no saved view.
+       errMemoryNoView = errors.New("the chat has messages but no saved view")
+
+       // errMemoryUnsettled tells that a line of the view stays pending,
+       // because its build failed.
+       errMemoryUnsettled = errors.New("a summary of the view failed, and it is tried again at the next message")
+)
 
 // openMemory opens the chat in root and starts the builds that are ready. The
 // clock gives the dates of new messages and the days of new nodes. The builds
@@ -195,6 +201,34 @@ func (m *Memory) Wait(ctx context.Context) error {
        }
 }
 
+// Settle returns when the chat view has no pending line, so that every message
+// so far is summarized. A pending line with no build that runs belongs to a
+// failed build, which waits for the next message, so Settle returns
+// errMemoryUnsettled in place of a wait that never ends.
+func (m *Memory) Settle(ctx context.Context) error {
+       for {
+               m.mutex.Lock()
+               pending := m.chat.Pending()
+               running := m.queue.Running()
+               changed := m.changed
+               m.mutex.Unlock()
+
+               if !pending {
+                       return nil
+               }
+
+               if running == 0 {
+                       return errMemoryUnsettled
+               }
+
+               select {
+               case <-changed:
+               case <-ctx.Done():
+                       return ctx.Err()
+               }
+       }
+}
+
 // Flush returns when every write before the call is durable.
 func (m *Memory) Flush(ctx context.Context) error {
        return m.syncer.Flush(ctx)