Add LastMessageAt field to conversation
Replaced `LatestConversationMessages` with `LoadConversationList`, which utilizes `LastMessageAt` for much faster conversation loading in the conversation listing TUI and `lmcli list` command.
This commit is contained in:
@@ -17,6 +17,7 @@ type Conversation struct {
|
||||
SelectedRootID *uint
|
||||
SelectedRoot *Message `gorm:"foreignKey:SelectedRootID"`
|
||||
RootMessages []Message `gorm:"-:all"`
|
||||
LastMessageAt time.Time
|
||||
}
|
||||
|
||||
type MessageMeta struct {
|
||||
|
||||
@@ -15,8 +15,7 @@ import (
|
||||
// Repo exposes low-level message and conversation management. See
|
||||
// Service for high-level helpers
|
||||
type Repo interface {
|
||||
// LatestConversationMessages returns a slice of all conversations ordered by when they were last updated (newest to oldest)
|
||||
LatestConversationMessages() ([]Message, error)
|
||||
LoadConversationList() (ConversationList, error)
|
||||
|
||||
FindConversationByShortName(shortName string) (*Conversation, error)
|
||||
ConversationShortNameCompletions(search string) []string
|
||||
@@ -72,25 +71,40 @@ func NewRepo(db *gorm.DB) (Repo, error) {
|
||||
return &repo{db, _sqids}, nil
|
||||
}
|
||||
|
||||
func (s *repo) LatestConversationMessages() ([]Message, error) {
|
||||
var latestMessages []Message
|
||||
type conversationListItem struct {
|
||||
ID uint
|
||||
ShortName string
|
||||
Title string
|
||||
LastMessageAt time.Time
|
||||
}
|
||||
|
||||
subQuery := s.db.Model(&Message{}).
|
||||
Select("MAX(created_at) as max_created_at, conversation_id").
|
||||
Group("conversation_id")
|
||||
type ConversationList struct {
|
||||
Total int
|
||||
Items []conversationListItem
|
||||
}
|
||||
|
||||
err := s.db.Model(&Message{}).
|
||||
Joins("JOIN (?) as sub on messages.conversation_id = sub.conversation_id AND messages.created_at = sub.max_created_at", subQuery).
|
||||
Group("messages.conversation_id").
|
||||
Order("created_at DESC").
|
||||
Preload("Conversation.SelectedRoot").
|
||||
Find(&latestMessages).Error
|
||||
// LoadConversationList loads existing conversations, ordered by the date
|
||||
// of their latest message, from most recent to oldest.
|
||||
func (s *repo) LoadConversationList() (ConversationList, error) {
|
||||
list := ConversationList{}
|
||||
|
||||
var convos []Conversation
|
||||
err := s.db.Order("last_message_at DESC").Find(&convos).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return list, err
|
||||
}
|
||||
|
||||
return latestMessages, nil
|
||||
for _, c := range convos {
|
||||
list.Items = append(list.Items, conversationListItem{
|
||||
ID: c.ID,
|
||||
ShortName: c.ShortName.String,
|
||||
Title: c.Title,
|
||||
LastMessageAt: c.LastMessageAt,
|
||||
})
|
||||
}
|
||||
|
||||
list.Total = len(list.Items)
|
||||
return list, nil
|
||||
}
|
||||
|
||||
func (s *repo) FindConversationByShortName(shortName string) (*Conversation, error) {
|
||||
@@ -220,6 +234,9 @@ func (s *repo) Reply(to *Message, messages ...Message) ([]Message, error) {
|
||||
savedMessages = append(savedMessages, message)
|
||||
currentParent = &message
|
||||
}
|
||||
|
||||
to.Conversation.LastMessageAt = savedMessages[len(savedMessages)-1].CreatedAt
|
||||
s.UpdateConversation(to.Conversation)
|
||||
return nil
|
||||
})
|
||||
|
||||
@@ -427,10 +444,7 @@ func (s *repo) StartConversation(messages ...Message) (*Conversation, []Message,
|
||||
// Update conversation's selected root message
|
||||
conversation.RootMessages = []Message{messages[0]}
|
||||
conversation.SelectedRoot = &messages[0]
|
||||
err = s.UpdateConversation(conversation)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
conversation.LastMessageAt = messages[0].CreatedAt
|
||||
|
||||
// Add additional replies to conversation
|
||||
if len(messages) > 1 {
|
||||
@@ -439,10 +453,12 @@ func (s *repo) StartConversation(messages ...Message) (*Conversation, []Message,
|
||||
return nil, nil, err
|
||||
}
|
||||
messages = append([]Message{messages[0]}, newMessages...)
|
||||
conversation.LastMessageAt = messages[len(messages)-1].CreatedAt
|
||||
}
|
||||
return conversation, messages, nil
|
||||
}
|
||||
|
||||
err = s.UpdateConversation(conversation)
|
||||
return conversation, messages, err
|
||||
}
|
||||
|
||||
// CloneConversation clones the given conversation and all of its meesages
|
||||
func (s *repo) CloneConversation(toClone Conversation) (*Conversation, uint, error) {
|
||||
|
||||
Reference in New Issue
Block a user