From c48a155e78af8fcd707ea3fdc86f250dfe2c2d36 Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Tue, 23 Jan 2024 10:48:31 +0800 Subject: [PATCH] :art: Improve data sync to prevent an old snapshot to overwrite the new one https://github.com/siyuan-note/siyuan/issues/10229 --- entity/index.go | 12 ++++++++++++ sync.go | 18 +++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/entity/index.go b/entity/index.go index 6f5ef5b..d9b1108 100644 --- a/entity/index.go +++ b/entity/index.go @@ -16,6 +16,13 @@ package entity +import ( + "fmt" + "time" + + "github.com/dustin/go-humanize" +) + // Index 描述了快照索引。 type Index struct { ID string `json:"id"` // Hash @@ -30,6 +37,11 @@ type Index struct { CheckIndexID string `json:"checkIndexID"` // Check Index ID } +func (index *Index) String() string { + return fmt.Sprintf("device=%s/%s, id=%s, files=%d, size=%s, created=%s", + index.SystemID, index.SystemOS, index.ID, len(index.Files), humanize.Bytes(uint64(index.Size)), time.UnixMilli(index.Created).Format("2006-01-02 15:04:05")) +} + // CheckIndex 描述了一个 Index 对应的数据 ID,包括 File ID 和 Chunk ID。 // // 该结构体在数据同步云端时根据本地 Latest Index 生成,在云端服务上用于校验数据完整性。 diff --git a/sync.go b/sync.go index b717c4c..5082d3b 100644 --- a/sync.go +++ b/sync.go @@ -506,10 +506,10 @@ func (repo *Repo) updateCloudIndexes(latest, cloudLatest *entity.Index, trafficS latestRef, downloadErr := repo.downloadCloudObject("refs/latest") if nil == downloadErr { if cloudLatest.ID != string(latestRef) { + logging.LogWarnf("cloud latest changed [old=%s, new=%s]", cloudLatest.ID, latestRef) errLock.Lock() errs = append(errs, cloud.ErrCloudIndexChanged) errLock.Unlock() - logging.LogWarnf("cloud latest changed [old=%s, new=%s]", cloudLatest.ID, latestRef) return } } @@ -563,6 +563,22 @@ func (repo *Repo) updateCloudIndexes(latest, cloudLatest *entity.Index, trafficS } if !bytes.Equal(latestData, downloadedData) { logging.LogWarnf("confirm [%d] uploaded cloud [refs/latest] failed [local=%s, downloaded=%s]", i, latestData, downloadedData) + + // 如果是不同设备上传的,则判定为数据已经改变 https://github.com/siyuan-note/siyuan/issues/10229 + _, latestCloudIndex, downloadIdxErr := repo.downloadCloudIndex(string(downloadedData), context) + if nil != downloadIdxErr { + logging.LogWarnf("download [refs/latest] failed: %s", downloadIdxErr) + continue + } + + if nil != latestCloudIndex && latestCloudIndex.SystemID != latest.SystemID { + logging.LogWarnf("cloud latest changed, current [%s], cloud [%s]", latest.String(), latestCloudIndex.String()) + errLock.Lock() + errs = append(errs, cloud.ErrCloudIndexChanged) + errLock.Unlock() + return + } + latestData, length, uploadErr = repo.updateCloudRef("refs/latest", context) if nil != uploadErr { logging.LogWarnf("fix [%d] uploaded cloud [refs/latest, %s] failed: %s", i, latestData, uploadErr)