]> git.giacomolli.uk - onechat/blobdiff - memory.go
Document private backups and a daily user timer
[onechat] / memory.go
index 7cbcce68c40f4b06382e3c8f3e71dfcbb3388d26..c9fe1c567504c11f0a94be48fdb581298cde510c 100644 (file)
--- a/memory.go
+++ b/memory.go
@@ -5,7 +5,7 @@ import (
        "encoding/json"
        "errors"
        "fmt"
-       "log"
+       "log/slog"
        "os"
        "path/filepath"
        "strings"
@@ -25,7 +25,7 @@ var (
 // 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. logger gets
 // one line for each failed build. The builds stop when ctx ends or at Close.
-func openMemory(ctx context.Context, root string, clock func() time.Time, summarizer Summarizer, logger *log.Logger) (*Memory, error) {
+func openMemory(ctx context.Context, root string, clock func() time.Time, summarizer Summarizer, logger *slog.Logger) (*Memory, error) {
        log, err := openLog(ctx, root, clock)
        if err != nil {
                return nil, err
@@ -108,7 +108,7 @@ type Memory struct {
        cview      *View
        queue      *BuildQueue
        summarizer Summarizer
-       logger     *log.Logger
+       logger     *slog.Logger
        ctx        context.Context
        cancel     context.CancelFunc
        workers    sync.WaitGroup
@@ -247,6 +247,26 @@ func (m *Memory) Flush(ctx context.Context) error {
        return m.syncer.Flush(ctx)
 }
 
+// Snapshot flushes all memory writes and runs snapshot while no append or
+// summary write can change the log, indexes, tree, or views. snapshot must not
+// call Memory.
+func (m *Memory) Snapshot(ctx context.Context, snapshot func() error) error {
+       m.mutex.Lock()
+       defer m.mutex.Unlock()
+
+       err := m.Flush(ctx)
+       if err != nil {
+               return fmt.Errorf("flush memory snapshot: %w", err)
+       }
+
+       err = snapshot()
+       if err != nil {
+               return fmt.Errorf("copy memory snapshot: %w", err)
+       }
+
+       return nil
+}
+
 // ViewLines returns the lines of the chat view, each with its newline, without
 // the leaf lines of the messages in skip.
 func (m *Memory) ViewLines(skip map[int]bool) []string {
@@ -598,7 +618,7 @@ func (m *Memory) run(key NodeKey, task Task) {
 
 // failed logs the failed build of the node key with its cause err.
 func (m *Memory) failed(key NodeKey, err error) {
-       m.logger.Printf("summary failed, retry at next message: node (%d, %d): %v", key.level, key.index, err)
+       m.logger.Warn("summary failed", "level", key.level, "index", key.index, "err", err)
 }
 
 // ready tells if both children of the node key are built and the node is not.