ente/cli/pkg/remote_sync.go

180 lines
4.9 KiB
Go
Raw Normal View History

2023-09-22 04:44:22 +00:00
package pkg
import (
2023-09-22 08:20:50 +00:00
"context"
2023-09-27 05:32:36 +00:00
"encoding/json"
2023-09-22 04:44:22 +00:00
"fmt"
2023-10-21 09:26:13 +00:00
"github.com/ente-io/cli/pkg/mapper"
"github.com/ente-io/cli/pkg/model"
"github.com/ente-io/cli/utils/encoding"
2023-09-22 04:44:22 +00:00
"log"
2023-09-27 05:32:36 +00:00
"strconv"
"time"
2023-09-22 04:44:22 +00:00
)
2023-09-27 05:32:36 +00:00
func (c *ClICtrl) fetchRemoteCollections(ctx context.Context) error {
lastSyncTime, err2 := c.GetInt64ConfigValue(ctx, model.CollectionsSyncKey)
if err2 != nil {
return err2
2023-09-22 16:15:01 +00:00
}
2023-09-27 05:32:36 +00:00
collections, err := c.Client.GetCollections(ctx, lastSyncTime)
2023-09-22 08:20:50 +00:00
if err != nil {
2023-09-27 05:32:36 +00:00
return fmt.Errorf("failed to get collections: %s", err)
2023-09-22 08:20:50 +00:00
}
2023-09-27 05:32:36 +00:00
maxUpdated := lastSyncTime
for _, collection := range collections {
if lastSyncTime == 0 && collection.IsDeleted {
continue
}
2023-09-27 08:43:42 +00:00
album, mapErr := mapper.MapCollectionToAlbum(ctx, collection, c.KeyHolder)
2023-09-27 05:32:36 +00:00
if mapErr != nil {
return mapErr
}
if album.LastUpdatedAt > maxUpdated {
maxUpdated = album.LastUpdatedAt
}
albumJson := encoding.MustMarshalJSON(album)
putErr := c.PutValue(ctx, model.RemoteAlbums, []byte(strconv.FormatInt(album.ID, 10)), albumJson)
if putErr != nil {
return putErr
}
}
if maxUpdated > lastSyncTime {
err = c.PutConfigValue(ctx, model.CollectionsSyncKey, []byte(strconv.FormatInt(maxUpdated, 10)))
if err != nil {
return fmt.Errorf("failed to update last sync time: %s", err)
}
2023-09-25 04:28:15 +00:00
}
2023-09-27 05:32:36 +00:00
return nil
}
func (c *ClICtrl) fetchRemoteFiles(ctx context.Context) error {
albums, err := c.getRemoteAlbums(ctx)
if err != nil {
2023-09-27 05:32:36 +00:00
return err
}
2023-09-27 05:32:36 +00:00
for _, album := range albums {
if album.IsDeleted {
continue
}
2023-10-04 06:22:34 +00:00
2023-09-27 05:32:36 +00:00
lastSyncTime, lastSyncTimeErr := c.GetInt64ConfigValue(ctx, fmt.Sprintf(model.CollectionsFileSyncKeyFmt, album.ID))
if lastSyncTimeErr != nil {
return lastSyncTimeErr
}
2023-10-04 06:22:34 +00:00
2023-09-27 05:32:36 +00:00
isFirstSync := lastSyncTime == 0
2023-10-04 06:22:34 +00:00
for {
2023-09-27 05:32:36 +00:00
if lastSyncTime == album.LastUpdatedAt {
break
}
2023-10-04 06:22:34 +00:00
if isFirstSync {
2023-11-01 04:38:26 +00:00
log.Printf("Sync files metadata for album %s\n", album.AlbumName)
2023-10-04 06:22:34 +00:00
} else {
2023-11-01 04:38:26 +00:00
log.Printf("Sync files metadata for album %s\n from %s", album.AlbumName, time.UnixMicro(lastSyncTime))
2023-10-04 06:22:34 +00:00
}
2023-09-27 05:32:36 +00:00
if !isFirstSync {
t := time.UnixMicro(lastSyncTime)
2023-11-01 04:38:26 +00:00
log.Printf("Fetching files metadata for album %s from %v\n", album.AlbumName, t)
2023-09-27 05:32:36 +00:00
}
files, hasMore, err := c.Client.GetFiles(ctx, album.ID, lastSyncTime)
if err != nil {
return err
}
maxUpdated := lastSyncTime
for _, file := range files {
if file.UpdationTime > maxUpdated {
maxUpdated = file.UpdationTime
}
if isFirstSync && file.IsRemovedFromAlbum() {
2023-09-27 05:32:36 +00:00
// on first sync, no need to sync delete markers
continue
}
albumEntry := model.AlbumFileEntry{AlbumID: album.ID, FileID: file.ID, IsDeleted: file.IsRemovedFromAlbum(), SyncedLocally: false}
2023-10-16 13:47:36 +00:00
putErr := c.UpsertAlbumEntry(ctx, &albumEntry)
2023-10-04 06:22:34 +00:00
if putErr != nil {
return putErr
}
if file.IsRemovedFromAlbum() {
2023-10-04 06:22:34 +00:00
continue
}
2023-09-27 08:43:42 +00:00
photoFile, err := mapper.MapApiFileToPhotoFile(ctx, album, file, c.KeyHolder)
2023-09-27 05:32:36 +00:00
if err != nil {
return err
}
fileJson := encoding.MustMarshalJSON(photoFile)
2023-10-04 06:22:34 +00:00
// todo: use batch put
putErr = c.PutValue(ctx, model.RemoteFiles, []byte(strconv.FormatInt(file.ID, 10)), fileJson)
2023-09-27 05:32:36 +00:00
if putErr != nil {
return putErr
}
}
if !hasMore {
maxUpdated = album.LastUpdatedAt
}
2023-10-04 06:22:34 +00:00
if (maxUpdated > lastSyncTime) || !hasMore {
log.Printf("Updating last sync time for album %s to %s\n", album.AlbumName, time.UnixMicro(maxUpdated))
2023-09-27 05:32:36 +00:00
err = c.PutConfigValue(ctx, fmt.Sprintf(model.CollectionsFileSyncKeyFmt, album.ID), []byte(strconv.FormatInt(maxUpdated, 10)))
if err != nil {
return fmt.Errorf("failed to update last sync time: %s", err)
} else {
lastSyncTime = maxUpdated
}
}
}
2023-09-25 13:40:36 +00:00
}
2023-09-25 04:28:15 +00:00
return nil
2023-09-22 08:20:50 +00:00
}
2023-09-27 05:32:36 +00:00
func (c *ClICtrl) getRemoteAlbums(ctx context.Context) ([]model.RemoteAlbum, error) {
albums := make([]model.RemoteAlbum, 0)
albumBytes, err := c.GetAllValues(ctx, model.RemoteAlbums)
if err != nil {
return nil, err
}
for _, albumJson := range albumBytes {
album := model.RemoteAlbum{}
err = json.Unmarshal(albumJson, &album)
if err != nil {
return nil, err
}
albums = append(albums, album)
}
return albums, nil
2023-09-22 04:44:22 +00:00
}
2023-09-27 05:32:36 +00:00
func (c *ClICtrl) getRemoteFiles(ctx context.Context) ([]model.RemoteFile, error) {
files := make([]model.RemoteFile, 0)
fileBytes, err := c.GetAllValues(ctx, model.RemoteFiles)
if err != nil {
return nil, err
}
for _, fileJson := range fileBytes {
file := model.RemoteFile{}
err = json.Unmarshal(fileJson, &file)
2023-09-22 04:44:22 +00:00
if err != nil {
2023-09-27 05:32:36 +00:00
return nil, err
2023-09-22 04:44:22 +00:00
}
2023-09-27 05:32:36 +00:00
files = append(files, file)
}
return files, nil
2023-09-22 04:44:22 +00:00
}
func (c *ClICtrl) getRemoteAlbumEntries(ctx context.Context) ([]*model.AlbumFileEntry, error) {
entries := make([]*model.AlbumFileEntry, 0)
entryBytes, err := c.GetAllValues(ctx, model.RemoteAlbumEntries)
if err != nil {
return nil, err
}
for _, entryJson := range entryBytes {
entry := &model.AlbumFileEntry{}
err = json.Unmarshal(entryJson, &entry)
if err != nil {
return nil, err
}
entries = append(entries, entry)
}
return entries, nil
}