package service import ( "context" "github.com/gochat/gochat/internal/model" "github.com/gochat/gochat/internal/search" applogger "github.com/gochat/gochat/pkg/logger" ) // SearchIndexer is the service-layer boundary for search synchronization. // Implementations may index synchronously or enqueue durable jobs later. type SearchIndexer interface { IndexConversation(ctx context.Context, conversation *model.Conversation) error DeleteConversation(ctx context.Context, accountID uint, id uint) error IndexMessage(ctx context.Context, message *model.Message) error DeleteMessage(ctx context.Context, accountID uint, id uint) error IndexContact(ctx context.Context, contact *model.Contact) error DeleteContact(ctx context.Context, accountID uint, id uint) error IndexCompany(ctx context.Context, company *model.Company) error DeleteCompany(ctx context.Context, accountID uint, id uint) error IndexArticle(ctx context.Context, article *model.Article) error DeleteArticle(ctx context.Context, accountID uint, id uint) error } type ContactSearchReader interface { SearchContacts(ctx context.Context, accountID uint, query string, filter *search.SearchFilter) ([]search.SearchResult, int64, error) } type CompanySearchReader interface { SearchCompanies(ctx context.Context, accountID uint, query string, filter *search.SearchFilter) ([]search.SearchResult, int64, error) } func serviceSearchFilter(offset, limit int, sort string, searchMode search.SearchMode, resultType search.SearchResultType) *search.SearchFilter { if limit <= 0 { limit = search.DefaultPerPage } page := 1 if offset > 0 { page = offset/limit + 1 } sortBy := sort if sortBy == "" { sortBy = search.DefaultSortBy } return &search.SearchFilter{ SearchMode: searchMode, Types: []search.SearchResultType{resultType}, SortBy: sortBy, SortOrder: search.DefaultSortOrder, Page: page, PerPage: limit, } } func logSearchIndexError(entity string, id uint, err error) { if err != nil { applogger.L().Warnf("search index sync failed for %s %d: %v", entity, id, err) } }