1
0
Fork 0
mirror of https://github.com/anyproto/any-sync.git synced 2025-06-08 05:57:03 +09:00
any-sync/client/filestorage/proxystore.go
2023-01-03 15:08:07 +03:00

137 lines
3.6 KiB
Go

package filestorage
import (
"context"
"github.com/anytypeio/go-anytype-infrastructure-experiments/client/filestorage/badgerfilestore"
"github.com/anytypeio/go-anytype-infrastructure-experiments/client/filestorage/rpcstore"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonfile/fileblockstore"
blocks "github.com/ipfs/go-block-format"
"github.com/ipfs/go-cid"
format "github.com/ipfs/go-ipld-format"
"go.uber.org/zap"
"io"
)
type proxyStore struct {
cache fileblockstore.BlockStoreLocal
origin rpcstore.RpcStore
index *badgerfilestore.FileBadgerIndex
}
func (c *proxyStore) Get(ctx context.Context, k cid.Cid) (b blocks.Block, err error) {
log.Debug("get cid", zap.String("cid", k.String()))
if b, err = c.cache.Get(ctx, k); err != nil {
if format.IsNotFound(err) {
err = nil
log.Debug("proxyStore local cid not found", zap.String("cid", k.String()))
} else {
return
}
} else {
return
}
if b, err = c.origin.Get(ctx, k); err != nil {
log.Debug("proxyStore remote cid error", zap.String("cid", k.String()), zap.Error(err))
return
}
if addErr := c.cache.Add(ctx, []blocks.Block{b}); addErr != nil {
log.Error("block fetched from origin but got error for add to cache", zap.Error(addErr))
}
return
}
func (c *proxyStore) GetMany(ctx context.Context, ks []cid.Cid) <-chan blocks.Block {
cachedCids, localErr := c.cache.ExistsCids(ctx, ks)
var originCids []cid.Cid
if localErr != nil {
log.Error("proxy store hasCIDs error", zap.Error(localErr))
originCids = ks
} else {
if len(cachedCids) != len(ks) {
set := cid.NewSet()
for _, cCid := range cachedCids {
set.Add(cCid)
}
originCids = ks[:0]
for _, k := range ks {
if !set.Has(k) {
originCids = append(originCids, k)
}
}
}
}
log.Debug("get many cids", zap.Int("cached", len(cachedCids)), zap.Int("origin", len(originCids)))
if len(originCids) == 0 {
return c.cache.GetMany(ctx, cachedCids)
}
var results = make(chan blocks.Block)
go func() {
defer close(results)
localResults := c.cache.GetMany(ctx, cachedCids)
originResults := c.origin.GetMany(ctx, originCids)
oOk, cOk := true, true
for {
var cb, ob blocks.Block
select {
case cb, cOk = <-localResults:
if cOk {
results <- cb
}
case ob, oOk = <-originResults:
if oOk {
if addErr := c.cache.Add(ctx, []blocks.Block{ob}); addErr != nil {
log.Error("add block to cache error", zap.Error(addErr))
}
results <- ob
}
case <-ctx.Done():
return
}
if !oOk && !cOk {
return
}
}
}()
return results
}
func (c *proxyStore) Add(ctx context.Context, bs []blocks.Block) (err error) {
if bs, err = c.cache.NotExistsBlocks(ctx, bs); err != nil {
return
}
if len(bs) == 0 {
return nil
}
if err = c.cache.Add(ctx, bs); err != nil {
return
}
indexCids := badgerfilestore.NewCids()
defer indexCids.Release()
for _, b := range bs {
indexCids.Add(fileblockstore.CtxGetSpaceId(ctx), badgerfilestore.OpAdd, b.Cid())
}
return c.index.Add(indexCids)
}
func (c *proxyStore) Delete(ctx context.Context, k cid.Cid) error {
if err := c.cache.Delete(ctx, k); err != nil {
return err
}
indexCids := badgerfilestore.NewCids()
defer indexCids.Release()
indexCids.Add(fileblockstore.CtxGetSpaceId(ctx), badgerfilestore.OpDelete, k)
return c.index.Add(indexCids)
}
func (c *proxyStore) Close() (err error) {
if closer, ok := c.cache.(io.Closer); ok {
if localErr := closer.Close(); localErr != nil {
log.Error("error while closing cache store", zap.Error(localErr))
}
}
if closer, ok := c.origin.(io.Closer); ok {
return closer.Close()
}
return nil
}