Skip to content

Commit f77a835

Browse files
authored
chore(blockstore): add an LRU cache to the API blockstore wrapper (#12878)
1 parent b1376cf commit f77a835

File tree

1 file changed

+25
-5
lines changed

1 file changed

+25
-5
lines changed

blockstore/api.go

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package blockstore
33
import (
44
"context"
55

6+
lru "github.com/hashicorp/golang-lru/v2"
67
blocks "github.com/ipfs/go-block-format"
78
"github.com/ipfs/go-cid"
89
"golang.org/x/xerrors"
@@ -15,14 +16,22 @@ type ChainIO interface {
1516
}
1617

1718
type apiBlockstore struct {
18-
api ChainIO
19+
api ChainIO
20+
cache *lru.Cache[cid.Cid, []byte]
1921
}
2022

2123
// This blockstore is adapted in the constructor.
2224
var _ BasicBlockstore = (*apiBlockstore)(nil)
2325

2426
func NewAPIBlockstore(cio ChainIO) Blockstore {
25-
bs := &apiBlockstore{api: cio}
27+
lc, err := lru.New[cid.Cid, []byte](1024) // we mostly come here for short-lived CLI applications so 1024 is a compromise size
28+
if err != nil {
29+
panic(err) // should never happen, only errors if size is <= 0
30+
}
31+
bs := &apiBlockstore{
32+
api: cio,
33+
cache: lc,
34+
}
2635
return Adapt(bs) // return an adapted blockstore.
2736
}
2837

@@ -31,31 +40,44 @@ func (a *apiBlockstore) DeleteBlock(context.Context, cid.Cid) error {
3140
}
3241

3342
func (a *apiBlockstore) Has(ctx context.Context, c cid.Cid) (bool, error) {
43+
if a.cache.Contains(c) {
44+
return true, nil
45+
}
3446
return a.api.ChainHasObj(ctx, c)
3547
}
3648

3749
func (a *apiBlockstore) Get(ctx context.Context, c cid.Cid) (blocks.Block, error) {
50+
if bb, ok := a.cache.Get(c); ok {
51+
return blocks.NewBlockWithCid(bb, c)
52+
}
3853
bb, err := a.api.ChainReadObj(ctx, c)
3954
if err != nil {
4055
return nil, err
4156
}
57+
a.cache.ContainsOrAdd(c, bb)
4258
return blocks.NewBlockWithCid(bb, c)
4359
}
4460

4561
func (a *apiBlockstore) GetSize(ctx context.Context, c cid.Cid) (int, error) {
62+
if bb, ok := a.cache.Peek(c); ok {
63+
return len(bb), nil
64+
}
4665
bb, err := a.api.ChainReadObj(ctx, c)
4766
if err != nil {
4867
return 0, err
4968
}
69+
a.cache.ContainsOrAdd(c, bb)
5070
return len(bb), nil
5171
}
5272

5373
func (a *apiBlockstore) Put(ctx context.Context, block blocks.Block) error {
74+
a.cache.Add(block.Cid(), block.RawData())
5475
return a.api.ChainPutObj(ctx, block)
5576
}
5677

5778
func (a *apiBlockstore) PutMany(ctx context.Context, blocks []blocks.Block) error {
5879
for _, block := range blocks {
80+
a.cache.Add(block.Cid(), block.RawData())
5981
err := a.api.ChainPutObj(ctx, block)
6082
if err != nil {
6183
return err
@@ -68,6 +90,4 @@ func (a *apiBlockstore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error)
6890
return nil, xerrors.New("not supported")
6991
}
7092

71-
func (a *apiBlockstore) HashOnRead(enabled bool) {
72-
return
73-
}
93+
func (a *apiBlockstore) HashOnRead(bool) {}

0 commit comments

Comments
 (0)