Initial commit: Open sourcing all of the Maple Open Technologies code.
This commit is contained in:
commit
755d54a99d
2010 changed files with 448675 additions and 0 deletions
143
cloud/maplepress-backend/internal/service/page/sync.go
Normal file
143
cloud/maplepress-backend/internal/service/page/sync.go
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
package page
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/gocql/gocql"
|
||||
"go.uber.org/zap"
|
||||
|
||||
domainpage "codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/domain/page"
|
||||
pageusecase "codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/usecase/page"
|
||||
)
|
||||
|
||||
// SyncPagesService handles page synchronization operations
|
||||
type SyncPagesService interface {
|
||||
SyncPages(ctx context.Context, tenantID, siteID gocql.UUID, input *pageusecase.SyncPagesInput) (*pageusecase.SyncPagesOutput, error)
|
||||
}
|
||||
|
||||
type syncPagesService struct {
|
||||
// Focused usecases
|
||||
validateSiteUC *pageusecase.ValidateSiteUseCase
|
||||
ensureIndexUC *pageusecase.EnsureSearchIndexUseCase
|
||||
createPageUC *pageusecase.CreatePageEntityUseCase
|
||||
upsertPageUC *pageusecase.UpsertPageUseCase
|
||||
indexPageUC *pageusecase.IndexPageToSearchUseCase
|
||||
updateUsageUC *pageusecase.UpdateSiteUsageUseCase
|
||||
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
// NewSyncPagesService creates a new SyncPagesService
|
||||
func NewSyncPagesService(
|
||||
validateSiteUC *pageusecase.ValidateSiteUseCase,
|
||||
ensureIndexUC *pageusecase.EnsureSearchIndexUseCase,
|
||||
createPageUC *pageusecase.CreatePageEntityUseCase,
|
||||
upsertPageUC *pageusecase.UpsertPageUseCase,
|
||||
indexPageUC *pageusecase.IndexPageToSearchUseCase,
|
||||
updateUsageUC *pageusecase.UpdateSiteUsageUseCase,
|
||||
logger *zap.Logger,
|
||||
) SyncPagesService {
|
||||
return &syncPagesService{
|
||||
validateSiteUC: validateSiteUC,
|
||||
ensureIndexUC: ensureIndexUC,
|
||||
createPageUC: createPageUC,
|
||||
upsertPageUC: upsertPageUC,
|
||||
indexPageUC: indexPageUC,
|
||||
updateUsageUC: updateUsageUC,
|
||||
logger: logger.Named("sync-pages-service"),
|
||||
}
|
||||
}
|
||||
|
||||
// SyncPages orchestrates the page synchronization workflow
|
||||
func (s *syncPagesService) SyncPages(ctx context.Context, tenantID, siteID gocql.UUID, input *pageusecase.SyncPagesInput) (*pageusecase.SyncPagesOutput, error) {
|
||||
s.logger.Info("syncing pages",
|
||||
zap.String("tenant_id", tenantID.String()),
|
||||
zap.String("site_id", siteID.String()),
|
||||
zap.Int("page_count", len(input.Pages)))
|
||||
|
||||
// Step 1: Validate site (no quota check - usage-based billing)
|
||||
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: Ensure search index exists
|
||||
if err := s.ensureIndexUC.Execute(ctx, siteID); err != nil {
|
||||
s.logger.Error("failed to ensure search index", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Step 3: Process pages (create, save, prepare for indexing)
|
||||
syncedCount, failedPages, pagesToIndex := s.processPages(ctx, siteID, site.TenantID, input.Pages)
|
||||
|
||||
// Step 4: Bulk index pages to search
|
||||
indexedCount, err := s.indexPageUC.Execute(ctx, siteID, pagesToIndex)
|
||||
if err != nil {
|
||||
s.logger.Error("failed to index pages", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Step 5: Update site usage tracking (for billing)
|
||||
if indexedCount > 0 {
|
||||
if err := s.updateUsageUC.Execute(ctx, site, indexedCount); err != nil {
|
||||
s.logger.Warn("failed to update usage (non-fatal)", zap.Error(err))
|
||||
// Don't fail the whole operation
|
||||
}
|
||||
}
|
||||
|
||||
// Step 6: Build output
|
||||
message := fmt.Sprintf("Successfully synced %d pages, indexed %d pages", syncedCount, indexedCount)
|
||||
if len(failedPages) > 0 {
|
||||
message += fmt.Sprintf(", failed %d pages", len(failedPages))
|
||||
}
|
||||
|
||||
s.logger.Info("pages synced successfully",
|
||||
zap.String("site_id", siteID.String()),
|
||||
zap.Int("synced", syncedCount),
|
||||
zap.Int("indexed", indexedCount),
|
||||
zap.Int("failed", len(failedPages)))
|
||||
|
||||
return &pageusecase.SyncPagesOutput{
|
||||
SyncedCount: syncedCount,
|
||||
IndexedCount: indexedCount,
|
||||
FailedPages: failedPages,
|
||||
Message: message,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Helper: Process pages - create entities, save to DB, collect pages to index
|
||||
func (s *syncPagesService) processPages(
|
||||
ctx context.Context,
|
||||
siteID, tenantID gocql.UUID,
|
||||
pages []pageusecase.SyncPageInput,
|
||||
) (int, []string, []*domainpage.Page) {
|
||||
syncedCount := 0
|
||||
var failedPages []string
|
||||
var pagesToIndex []*domainpage.Page
|
||||
|
||||
for _, pageInput := range pages {
|
||||
// Create page entity (usecase)
|
||||
page, err := s.createPageUC.Execute(siteID, tenantID, pageInput)
|
||||
if err != nil {
|
||||
failedPages = append(failedPages, pageInput.PageID)
|
||||
continue
|
||||
}
|
||||
|
||||
// Save to database (usecase)
|
||||
if err := s.upsertPageUC.Execute(ctx, page); err != nil {
|
||||
failedPages = append(failedPages, pageInput.PageID)
|
||||
continue
|
||||
}
|
||||
|
||||
syncedCount++
|
||||
|
||||
// Collect pages that should be indexed
|
||||
if page.ShouldIndex() {
|
||||
pagesToIndex = append(pagesToIndex, page)
|
||||
}
|
||||
}
|
||||
|
||||
return syncedCount, failedPages, pagesToIndex
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue