X-Git-Url: https://git.giacomolli.uk/onechat/blobdiff_plain/baf7a940be8927278e3b4b87e7366cebfc16532f..0018014ab36f3de61a4b8a5515009dab803d6c38:/memory.go?ds=inline diff --git a/memory.go b/memory.go index 9846c98..0fd7d83 100644 --- 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)