feat(search): align conversation identity search
This commit is contained in:
@@ -41,7 +41,14 @@ func (i *DurableSearchIndexer) IndexConversation(ctx context.Context, conversati
|
||||
return nil
|
||||
}
|
||||
return i.enqueueOrIndex(ctx, "conversation", conversation.AccountID, conversation.ID, func() error {
|
||||
return i.delegate.IndexConversation(ctx, conversation)
|
||||
enriched, err := i.loadConversation(ctx, conversation.AccountID, conversation.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if enriched == nil {
|
||||
return nil
|
||||
}
|
||||
return i.delegate.IndexConversation(ctx, enriched)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -144,11 +151,14 @@ func (i *DurableSearchIndexer) perform(ctx context.Context, job *model.Backgroun
|
||||
func (i *DurableSearchIndexer) performIndex(ctx context.Context, payload searchIndexJob) error {
|
||||
switch payload.Entity {
|
||||
case "conversation":
|
||||
var item model.Conversation
|
||||
if err := i.load(ctx, payload, &item); err != nil {
|
||||
item, err := i.loadConversation(ctx, payload.AccountID, payload.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return i.delegate.IndexConversation(ctx, &item)
|
||||
if item == nil {
|
||||
return nil
|
||||
}
|
||||
return i.delegate.IndexConversation(ctx, item)
|
||||
case "message":
|
||||
var item model.Message
|
||||
if err := i.load(ctx, payload, &item); err != nil {
|
||||
@@ -178,6 +188,21 @@ func (i *DurableSearchIndexer) performIndex(ctx context.Context, payload searchI
|
||||
}
|
||||
}
|
||||
|
||||
func (i *DurableSearchIndexer) loadConversation(ctx context.Context, accountID, id uint) (*model.Conversation, error) {
|
||||
var item model.Conversation
|
||||
err := i.db.WithContext(ctx).
|
||||
Preload("Contact").
|
||||
Where("id = ? AND account_id = ?", id, accountID).
|
||||
First(&item).Error
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, i.performDelete(ctx, searchIndexJob{Operation: "delete", Entity: "conversation", AccountID: accountID, ID: id})
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &item, nil
|
||||
}
|
||||
|
||||
func (i *DurableSearchIndexer) load(ctx context.Context, payload searchIndexJob, dest any) error {
|
||||
err := i.db.WithContext(ctx).Where("id = ? AND account_id = ?", payload.ID, payload.AccountID).First(dest).Error
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
|
||||
@@ -11,12 +11,16 @@ import (
|
||||
)
|
||||
|
||||
type recordingDurableSearchIndexer struct {
|
||||
indexedContacts []uint
|
||||
deletedContacts []uint
|
||||
err error
|
||||
indexedConversations []model.Conversation
|
||||
indexedContacts []uint
|
||||
deletedContacts []uint
|
||||
err error
|
||||
}
|
||||
|
||||
func (r *recordingDurableSearchIndexer) IndexConversation(ctx context.Context, conversation *model.Conversation) error {
|
||||
if conversation != nil {
|
||||
r.indexedConversations = append(r.indexedConversations, *conversation)
|
||||
}
|
||||
return r.err
|
||||
}
|
||||
|
||||
@@ -91,6 +95,33 @@ func TestDurableSearchIndexerQueuesAndReplaysContactIndex(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestDurableSearchIndexerPreloadsConversationContact(t *testing.T) {
|
||||
db := setupServiceTestDB(t)
|
||||
account := createTestAccount(t, db)
|
||||
contact := &model.Contact{AccountID: account.ID, Name: "Ada Lovelace", Email: "ada@example.com"}
|
||||
if err := db.Create(contact).Error; err != nil {
|
||||
t.Fatalf("create contact: %v", err)
|
||||
}
|
||||
conversation := &model.Conversation{AccountID: account.ID, ContactID: contact.ID, InboxID: 1, ChannelType: "web_widget", Channel: "web_widget", Status: "open"}
|
||||
if err := db.Create(conversation).Error; err != nil {
|
||||
t.Fatalf("create conversation: %v", err)
|
||||
}
|
||||
delegate := &recordingDurableSearchIndexer{}
|
||||
indexer := NewDurableSearchIndexer(db, nil, delegate)
|
||||
|
||||
if err := indexer.IndexConversation(context.Background(), conversation); err != nil {
|
||||
t.Fatalf("index conversation: %v", err)
|
||||
}
|
||||
|
||||
if len(delegate.indexedConversations) != 1 {
|
||||
t.Fatalf("expected one indexed conversation, got %#v", delegate.indexedConversations)
|
||||
}
|
||||
indexed := delegate.indexedConversations[0]
|
||||
if indexed.Contact == nil || indexed.Contact.Name != "Ada Lovelace" || indexed.Contact.Email != "ada@example.com" {
|
||||
t.Fatalf("expected preloaded contact in indexed conversation, got %#v", indexed.Contact)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDurableSearchIndexerRetriesDelegateFailure(t *testing.T) {
|
||||
db := setupServiceTestDB(t)
|
||||
account := createTestAccount(t, db)
|
||||
|
||||
Reference in New Issue
Block a user