mirror of
https://github.com/anyproto/any-sync.git
synced 2025-06-08 05:57:03 +09:00
137 lines
3.6 KiB
Go
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
|
|
}
|