monorepo/cloud/maplepress-backend/internal/service/page/delete.go

148 lines
4.9 KiB
Go

package page
import (
"context"
"fmt"
"github.com/gocql/gocql"
"go.uber.org/zap"
pageusecase "codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/usecase/page"
)
// DeletePagesService handles page deletion operations
type DeletePagesService interface {
DeletePages(ctx context.Context, tenantID, siteID gocql.UUID, input *pageusecase.DeletePagesInput) (*pageusecase.DeletePagesOutput, error)
DeleteAllPages(ctx context.Context, tenantID, siteID gocql.UUID) (*pageusecase.DeletePagesOutput, error)
}
type deletePagesService struct {
// Focused usecases
validateSiteUC *pageusecase.ValidateSiteForDeletionUseCase
deletePagesRepoUC *pageusecase.DeletePagesFromRepoUseCase
deletePagesSearchUC *pageusecase.DeletePagesFromSearchUseCase
logger *zap.Logger
}
// NewDeletePagesService creates a new DeletePagesService
func NewDeletePagesService(
validateSiteUC *pageusecase.ValidateSiteForDeletionUseCase,
deletePagesRepoUC *pageusecase.DeletePagesFromRepoUseCase,
deletePagesSearchUC *pageusecase.DeletePagesFromSearchUseCase,
logger *zap.Logger,
) DeletePagesService {
return &deletePagesService{
validateSiteUC: validateSiteUC,
deletePagesRepoUC: deletePagesRepoUC,
deletePagesSearchUC: deletePagesSearchUC,
logger: logger.Named("delete-pages-service"),
}
}
// DeletePages orchestrates the deletion of specific pages
func (s *deletePagesService) DeletePages(ctx context.Context, tenantID, siteID gocql.UUID, input *pageusecase.DeletePagesInput) (*pageusecase.DeletePagesOutput, error) {
s.logger.Info("deleting pages",
zap.String("tenant_id", tenantID.String()),
zap.String("site_id", siteID.String()),
zap.Int("page_count", len(input.PageIDs)))
// Step 1: Validate site
_, err := s.validateSiteUC.Execute(ctx, tenantID, siteID)
if err != nil {
s.logger.Error("failed to validate site", zap.Error(err))
return nil, err
}
// Step 2: Delete pages from database
deleteResult, err := s.deletePagesRepoUC.Execute(ctx, siteID, input.PageIDs)
if err != nil {
s.logger.Error("failed to delete pages from database", zap.Error(err))
return nil, err
}
// Step 3: Delete pages from search index (only if database delete succeeded)
deindexedCount := 0
if deleteResult.DeletedCount > 0 {
// Only delete pages that were successfully deleted from database
successfulPageIDs := s.getSuccessfulPageIDs(input.PageIDs, deleteResult.FailedPages)
if len(successfulPageIDs) > 0 {
deindexedCount, _ = s.deletePagesSearchUC.Execute(ctx, siteID, successfulPageIDs)
}
}
// Step 4: Build output
message := fmt.Sprintf("Successfully deleted %d pages from database, removed %d from search index",
deleteResult.DeletedCount, deindexedCount)
if len(deleteResult.FailedPages) > 0 {
message += fmt.Sprintf(", failed %d pages", len(deleteResult.FailedPages))
}
s.logger.Info("pages deleted successfully",
zap.String("site_id", siteID.String()),
zap.Int("deleted", deleteResult.DeletedCount),
zap.Int("deindexed", deindexedCount),
zap.Int("failed", len(deleteResult.FailedPages)))
return &pageusecase.DeletePagesOutput{
DeletedCount: deleteResult.DeletedCount,
DeindexedCount: deindexedCount,
FailedPages: deleteResult.FailedPages,
Message: message,
}, nil
}
// DeleteAllPages orchestrates the deletion of all pages for a site
func (s *deletePagesService) DeleteAllPages(ctx context.Context, tenantID, siteID gocql.UUID) (*pageusecase.DeletePagesOutput, error) {
s.logger.Info("deleting all pages",
zap.String("tenant_id", tenantID.String()),
zap.String("site_id", siteID.String()))
// Step 1: Validate site
_, err := s.validateSiteUC.Execute(ctx, tenantID, siteID)
if err != nil {
s.logger.Error("failed to validate site", zap.Error(err))
return nil, err
}
// Step 2: Delete all pages from database
count, err := s.deletePagesRepoUC.ExecuteDeleteAll(ctx, siteID)
if err != nil {
s.logger.Error("failed to delete all pages from database", zap.Error(err))
return nil, err
}
// Step 3: Delete all documents from search index
_ = s.deletePagesSearchUC.ExecuteDeleteAll(ctx, siteID)
s.logger.Info("all pages deleted successfully",
zap.String("site_id", siteID.String()),
zap.Int64("count", count))
return &pageusecase.DeletePagesOutput{
DeletedCount: int(count),
DeindexedCount: int(count),
Message: fmt.Sprintf("Successfully deleted all %d pages", count),
}, nil
}
// Helper: Get list of page IDs that were successfully deleted (exclude failed ones)
func (s *deletePagesService) getSuccessfulPageIDs(allPageIDs, failedPageIDs []string) []string {
if len(failedPageIDs) == 0 {
return allPageIDs
}
failedMap := make(map[string]bool, len(failedPageIDs))
for _, id := range failedPageIDs {
failedMap[id] = true
}
successful := make([]string, 0, len(allPageIDs)-len(failedPageIDs))
for _, id := range allPageIDs {
if !failedMap[id] {
successful = append(successful, id)
}
}
return successful
}