134 lines
4 KiB
Go
134 lines
4 KiB
Go
package page
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/gocql/gocql"
|
|
"go.uber.org/zap"
|
|
|
|
domainsite "codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/domain/site"
|
|
"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/pkg/search"
|
|
)
|
|
|
|
// SearchPagesUseCase handles page search functionality
|
|
type SearchPagesUseCase struct {
|
|
siteRepo domainsite.Repository
|
|
searchClient *search.Client
|
|
logger *zap.Logger
|
|
}
|
|
|
|
// ProvideSearchPagesUseCase creates a new SearchPagesUseCase
|
|
func ProvideSearchPagesUseCase(
|
|
siteRepo domainsite.Repository,
|
|
searchClient *search.Client,
|
|
logger *zap.Logger,
|
|
) *SearchPagesUseCase {
|
|
return &SearchPagesUseCase{
|
|
siteRepo: siteRepo,
|
|
searchClient: searchClient,
|
|
logger: logger,
|
|
}
|
|
}
|
|
|
|
// SearchPagesInput is the input for searching pages
|
|
type SearchPagesInput struct {
|
|
Query string `json:"query"`
|
|
Limit int64 `json:"limit"`
|
|
Offset int64 `json:"offset"`
|
|
Filter string `json:"filter,omitempty"` // e.g., "status = publish AND post_type = post"
|
|
}
|
|
|
|
// SearchPagesOutput is the output after searching pages
|
|
type SearchPagesOutput struct {
|
|
Hits interface{} `json:"hits"` // meilisearch.Hits
|
|
Query string `json:"query"`
|
|
ProcessingTimeMs int64 `json:"processing_time_ms"`
|
|
TotalHits int64 `json:"total_hits"`
|
|
Limit int64 `json:"limit"`
|
|
Offset int64 `json:"offset"`
|
|
}
|
|
|
|
// Execute performs a search on the site's indexed pages
|
|
func (uc *SearchPagesUseCase) Execute(ctx context.Context, tenantID, siteID gocql.UUID, input *SearchPagesInput) (*SearchPagesOutput, error) {
|
|
uc.logger.Info("executing search pages use case",
|
|
zap.String("tenant_id", tenantID.String()),
|
|
zap.String("site_id", siteID.String()),
|
|
zap.String("query", input.Query))
|
|
|
|
// Get site to validate and check quotas
|
|
site, err := uc.siteRepo.GetByID(ctx, tenantID, siteID)
|
|
if err != nil {
|
|
uc.logger.Error("failed to get site", zap.Error(err))
|
|
return nil, domainsite.ErrSiteNotFound
|
|
}
|
|
|
|
// Verify site is verified (skip for test mode)
|
|
if site.RequiresVerification() && !site.IsVerified {
|
|
uc.logger.Warn("site not verified", zap.String("site_id", siteID.String()))
|
|
return nil, domainsite.ErrSiteNotVerified
|
|
}
|
|
|
|
// No quota checking - usage-based billing (anti-abuse via rate limiting only)
|
|
|
|
// Set default limits if not provided
|
|
limit := input.Limit
|
|
if limit <= 0 || limit > 100 {
|
|
limit = 20 // Default to 20 results
|
|
}
|
|
|
|
offset := input.Offset
|
|
if offset < 0 {
|
|
offset = 0
|
|
}
|
|
|
|
// Build search request
|
|
searchReq := search.SearchRequest{
|
|
Query: input.Query,
|
|
Limit: limit,
|
|
Offset: offset,
|
|
Filter: input.Filter,
|
|
}
|
|
|
|
// If no filter provided, default to only published pages
|
|
if searchReq.Filter == "" {
|
|
searchReq.Filter = "status = publish"
|
|
}
|
|
|
|
// Perform search
|
|
result, err := uc.searchClient.Search(siteID.String(), searchReq)
|
|
if err != nil {
|
|
uc.logger.Error("failed to search pages", zap.Error(err))
|
|
return nil, fmt.Errorf("failed to search pages: %w", err)
|
|
}
|
|
|
|
// Increment search request count (for usage tracking/billing)
|
|
site.IncrementSearchCount()
|
|
uc.logger.Info("incremented search count",
|
|
zap.String("site_id", siteID.String()),
|
|
zap.Int64("new_count", site.SearchRequestsCount))
|
|
|
|
if err := uc.siteRepo.UpdateUsage(ctx, site); err != nil {
|
|
uc.logger.Error("failed to update search usage", zap.Error(err))
|
|
// Don't fail the search, just log the error
|
|
} else {
|
|
uc.logger.Info("search usage updated successfully",
|
|
zap.String("site_id", siteID.String()),
|
|
zap.Int64("search_count", site.SearchRequestsCount))
|
|
}
|
|
|
|
uc.logger.Info("search completed successfully",
|
|
zap.String("site_id", siteID.String()),
|
|
zap.String("query", input.Query),
|
|
zap.Int64("total_hits", result.TotalHits),
|
|
zap.Int64("processing_time_ms", result.ProcessingTimeMs))
|
|
|
|
return &SearchPagesOutput{
|
|
Hits: result.Hits,
|
|
Query: result.Query,
|
|
ProcessingTimeMs: result.ProcessingTimeMs,
|
|
TotalHits: result.TotalHits,
|
|
Limit: result.Limit,
|
|
Offset: result.Offset,
|
|
}, nil
|
|
}
|