1
0
Fork 0
mirror of https://github.com/anyproto/any-sync.git synced 2025-06-08 05:57:03 +09:00
any-sync/commonspace/headsync/remotediff.go
Mikhail Rakhmanov 55bd460282
Remove snappy
2025-04-01 13:25:56 +02:00

146 lines
3.7 KiB
Go

package headsync
import (
"bytes"
"context"
"encoding/hex"
"math"
"github.com/anyproto/any-sync/app/ldiff"
"github.com/anyproto/any-sync/commonspace/spacesyncproto"
)
type Client interface {
HeadSync(ctx context.Context, in *spacesyncproto.HeadSyncRequest) (*spacesyncproto.HeadSyncResponse, error)
}
type RemoteDiff interface {
ldiff.RemoteTypeChecker
ldiff.Remote
}
func NewRemoteDiff(spaceId string, client Client) RemoteDiff {
return &remote{
spaceId: spaceId,
client: client,
}
}
type remote struct {
spaceId string
client Client
diffType spacesyncproto.DiffType
}
func (r *remote) Ranges(ctx context.Context, ranges []ldiff.Range, resBuf []ldiff.RangeResult) (results []ldiff.RangeResult, err error) {
results = resBuf[:0]
pbRanges := make([]*spacesyncproto.HeadSyncRange, 0, len(ranges))
for _, rg := range ranges {
pbRanges = append(pbRanges, &spacesyncproto.HeadSyncRange{
From: rg.From,
To: rg.To,
Elements: rg.Elements,
Limit: uint32(rg.Limit),
})
}
req := &spacesyncproto.HeadSyncRequest{
SpaceId: r.spaceId,
Ranges: pbRanges,
DiffType: r.diffType,
}
resp, err := r.client.HeadSync(ctx, req)
if err != nil {
return
}
for _, rr := range resp.Results {
var elms []ldiff.Element
if len(rr.Elements) > 0 {
elms = make([]ldiff.Element, 0, len(rr.Elements))
}
for _, e := range rr.Elements {
elms = append(elms, ldiff.Element{
Id: e.Id,
Head: e.Head,
})
}
results = append(results, ldiff.RangeResult{
Hash: rr.Hash,
Elements: elms,
Count: int(rr.Count),
})
}
return
}
func (r *remote) DiffTypeCheck(ctx context.Context, diffContainer ldiff.DiffContainer) (needsSync bool, diff ldiff.Diff, err error) {
req := &spacesyncproto.HeadSyncRequest{
SpaceId: r.spaceId,
DiffType: spacesyncproto.DiffType_V2,
Ranges: []*spacesyncproto.HeadSyncRange{{From: 0, To: math.MaxUint64}},
}
resp, err := r.client.HeadSync(ctx, req)
if err != nil {
return
}
needsSync = true
checkHash := func(diff ldiff.Diff) (bool, error) {
hashB, err := hex.DecodeString(diff.Hash())
if err != nil {
return false, err
}
if len(resp.Results) != 0 && bytes.Equal(hashB, resp.Results[0].Hash) {
return false, nil
}
return true, nil
}
r.diffType = resp.DiffType
switch resp.DiffType {
case spacesyncproto.DiffType_V2:
diff = diffContainer.NewDiff()
needsSync, err = checkHash(diff)
default:
diff = diffContainer.OldDiff()
needsSync, err = checkHash(diff)
}
return
}
func HandleRangeRequest(ctx context.Context, d ldiff.Diff, req *spacesyncproto.HeadSyncRequest) (resp *spacesyncproto.HeadSyncResponse, err error) {
ranges := make([]ldiff.Range, 0, len(req.Ranges))
// basically we gather data applicable for both diffs
for _, reqRange := range req.Ranges {
ranges = append(ranges, ldiff.Range{
From: reqRange.From,
To: reqRange.To,
Limit: int(reqRange.Limit),
Elements: reqRange.Elements,
})
}
res, err := d.Ranges(ctx, ranges, nil)
if err != nil {
return
}
resp = &spacesyncproto.HeadSyncResponse{
Results: make([]*spacesyncproto.HeadSyncResult, 0, len(res)),
}
for _, rangeRes := range res {
var elements []*spacesyncproto.HeadSyncResultElement
if len(rangeRes.Elements) > 0 {
elements = make([]*spacesyncproto.HeadSyncResultElement, 0, len(rangeRes.Elements))
for _, el := range rangeRes.Elements {
elements = append(elements, &spacesyncproto.HeadSyncResultElement{
Id: el.Id,
Head: el.Head,
})
}
}
resp.Results = append(resp.Results, &spacesyncproto.HeadSyncResult{
Hash: rangeRes.Hash,
Elements: elements,
Count: uint32(rangeRes.Count),
})
}
resp.DiffType = d.DiffType()
return
}