149 lines
4.4 KiB
Go
149 lines
4.4 KiB
Go
package sync
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"go.uber.org/zap"
|
|
|
|
"codeberg.org/mapleopentech/monorepo/native/desktop/maplefile/internal/domain/syncstate"
|
|
)
|
|
|
|
// Service provides unified sync operations
|
|
type Service interface {
|
|
// SyncAll synchronizes both collections and files
|
|
SyncAll(ctx context.Context, input *SyncInput) (*SyncResult, error)
|
|
|
|
// SyncCollections synchronizes collections only
|
|
SyncCollections(ctx context.Context, input *SyncInput) (*SyncResult, error)
|
|
|
|
// SyncFiles synchronizes files only
|
|
SyncFiles(ctx context.Context, input *SyncInput) (*SyncResult, error)
|
|
|
|
// GetSyncStatus returns the current sync status
|
|
GetSyncStatus(ctx context.Context) (*SyncStatus, error)
|
|
|
|
// ResetSync resets all sync state for a fresh sync
|
|
ResetSync(ctx context.Context) error
|
|
}
|
|
|
|
type service struct {
|
|
logger *zap.Logger
|
|
collectionSync CollectionSyncService
|
|
fileSync FileSyncService
|
|
repoProvider RepositoryProvider
|
|
}
|
|
|
|
// ProvideService creates a new unified sync service for Wire
|
|
func ProvideService(
|
|
logger *zap.Logger,
|
|
collectionSync CollectionSyncService,
|
|
fileSync FileSyncService,
|
|
repoProvider RepositoryProvider,
|
|
) Service {
|
|
return &service{
|
|
logger: logger.Named("SyncService"),
|
|
collectionSync: collectionSync,
|
|
fileSync: fileSync,
|
|
repoProvider: repoProvider,
|
|
}
|
|
}
|
|
|
|
// getSyncStateRepo returns the sync state repository, or an error if not initialized
|
|
func (s *service) getSyncStateRepo() (syncstate.Repository, error) {
|
|
if !s.repoProvider.IsInitialized() {
|
|
return nil, fmt.Errorf("storage not initialized - user must be logged in")
|
|
}
|
|
repo := s.repoProvider.GetSyncStateRepository()
|
|
if repo == nil {
|
|
return nil, fmt.Errorf("sync state repository not available")
|
|
}
|
|
return repo, nil
|
|
}
|
|
|
|
// SyncAll synchronizes both collections and files
|
|
func (s *service) SyncAll(ctx context.Context, input *SyncInput) (*SyncResult, error) {
|
|
s.logger.Info("Starting full sync (collections + files)")
|
|
|
|
// Sync collections first
|
|
colResult, err := s.collectionSync.Execute(ctx, input)
|
|
if err != nil {
|
|
s.logger.Error("Collection sync failed during full sync", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
|
|
// Sync files
|
|
fileResult, err := s.fileSync.Execute(ctx, input)
|
|
if err != nil {
|
|
s.logger.Error("File sync failed during full sync", zap.Error(err))
|
|
// Return partial result with collection data
|
|
return &SyncResult{
|
|
CollectionsProcessed: colResult.CollectionsProcessed,
|
|
CollectionsAdded: colResult.CollectionsAdded,
|
|
CollectionsUpdated: colResult.CollectionsUpdated,
|
|
CollectionsDeleted: colResult.CollectionsDeleted,
|
|
Errors: append(colResult.Errors, "file sync failed: "+err.Error()),
|
|
}, err
|
|
}
|
|
|
|
// Merge results
|
|
result := &SyncResult{
|
|
CollectionsProcessed: colResult.CollectionsProcessed,
|
|
CollectionsAdded: colResult.CollectionsAdded,
|
|
CollectionsUpdated: colResult.CollectionsUpdated,
|
|
CollectionsDeleted: colResult.CollectionsDeleted,
|
|
FilesProcessed: fileResult.FilesProcessed,
|
|
FilesAdded: fileResult.FilesAdded,
|
|
FilesUpdated: fileResult.FilesUpdated,
|
|
FilesDeleted: fileResult.FilesDeleted,
|
|
Errors: append(colResult.Errors, fileResult.Errors...),
|
|
}
|
|
|
|
s.logger.Info("Full sync completed",
|
|
zap.Int("collections_processed", result.CollectionsProcessed),
|
|
zap.Int("files_processed", result.FilesProcessed),
|
|
zap.Int("errors", len(result.Errors)))
|
|
|
|
return result, nil
|
|
}
|
|
|
|
// SyncCollections synchronizes collections only
|
|
func (s *service) SyncCollections(ctx context.Context, input *SyncInput) (*SyncResult, error) {
|
|
return s.collectionSync.Execute(ctx, input)
|
|
}
|
|
|
|
// SyncFiles synchronizes files only
|
|
func (s *service) SyncFiles(ctx context.Context, input *SyncInput) (*SyncResult, error) {
|
|
return s.fileSync.Execute(ctx, input)
|
|
}
|
|
|
|
// GetSyncStatus returns the current sync status
|
|
func (s *service) GetSyncStatus(ctx context.Context) (*SyncStatus, error) {
|
|
syncStateRepo, err := s.getSyncStateRepo()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
state, err := syncStateRepo.Get()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &SyncStatus{
|
|
CollectionsSynced: state.IsCollectionSyncComplete(),
|
|
FilesSynced: state.IsFileSyncComplete(),
|
|
FullySynced: state.IsFullySynced(),
|
|
}, nil
|
|
}
|
|
|
|
// ResetSync resets all sync state for a fresh sync
|
|
func (s *service) ResetSync(ctx context.Context) error {
|
|
s.logger.Info("Resetting sync state")
|
|
|
|
syncStateRepo, err := s.getSyncStateRepo()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return syncStateRepo.Reset()
|
|
}
|