Skip to content

Commit 2b1c552

Browse files
committed
blockservice: add session workaround to work with wrapped blockservices
1 parent e0d5341 commit 2b1c552

File tree

3 files changed

+96
-20
lines changed

3 files changed

+96
-20
lines changed

blockservice/blockservice.go

+15-8
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,11 @@ func New(bs blockstore.Blockstore, exchange exchange.Interface, opts ...Option)
140140

141141
// Blockstore returns the blockstore behind this blockservice.
142142
func (s *blockService) Blockstore() blockstore.Blockstore {
143+
if s.provider != nil {
144+
// FIXME: this is a hack remove once ipfs/boxo#567 is solved.
145+
return providingBlockstore{s.blockstore, s.provider}
146+
}
147+
143148
return s.blockstore
144149
}
145150

@@ -275,7 +280,7 @@ func getBlock(ctx context.Context, c cid.Cid, bs BlockService, fetchFactory func
275280
return nil, err
276281
}
277282

278-
blockstore := bs.Blockstore()
283+
provider, blockstore := grabProviderAndBlockstoreFromBlockservice(bs)
279284

280285
block, err := blockstore.Get(ctx, c)
281286
switch {
@@ -309,7 +314,7 @@ func getBlock(ctx context.Context, c cid.Cid, bs BlockService, fetchFactory func
309314
return nil, err
310315
}
311316
}
312-
if provider := grabProviderFromBlockservice(bs); provider != nil {
317+
if provider != nil {
313318
err = provider.Provide(blk.Cid())
314319
if err != nil {
315320
return nil, err
@@ -360,7 +365,7 @@ func getBlocks(ctx context.Context, ks []cid.Cid, blockservice BlockService, fet
360365
ks = ks2
361366
}
362367

363-
bs := blockservice.Blockstore()
368+
provider, bs := grabProviderAndBlockstoreFromBlockservice(blockservice)
364369

365370
var misses []cid.Cid
366371
for _, c := range ks {
@@ -388,7 +393,6 @@ func getBlocks(ctx context.Context, ks []cid.Cid, blockservice BlockService, fet
388393
}
389394

390395
ex := blockservice.Exchange()
391-
provider := grabProviderFromBlockservice(blockservice)
392396
var cache [1]blocks.Block // preallocate once for all iterations
393397
for {
394398
var b blocks.Block
@@ -515,10 +519,13 @@ func grabAllowlistFromBlockservice(bs BlockService) verifcid.Allowlist {
515519
return verifcid.DefaultAllowlist
516520
}
517521

518-
// grabProviderFromBlockservice can return nil if no provider is used.
519-
func grabProviderFromBlockservice(bs BlockService) provider.Provider {
522+
// grabProviderAndBlockstoreFromBlockservice can return nil if no provider is used.
523+
func grabProviderAndBlockstoreFromBlockservice(bs BlockService) (provider.Provider, blockstore.Blockstore) {
524+
if bbs, ok := bs.(*blockService); ok {
525+
return bbs.provider, bbs.blockstore
526+
}
520527
if bbs, ok := bs.(ProvidingBlockService); ok {
521-
return bbs.Provider()
528+
return bbs.Provider(), bbs.Blockstore()
522529
}
523-
return nil
530+
return nil, bs.Blockstore()
524531
}

blockservice/blockservice_test.go

+44-12
Original file line numberDiff line numberDiff line change
@@ -289,18 +289,26 @@ func TestAllowlist(t *testing.T) {
289289
check(NewSession(ctx, blockservice).GetBlock)
290290
}
291291

292+
type wrappedBlockservice struct {
293+
BlockService
294+
}
295+
292296
type mockProvider []cid.Cid
293297

294298
func (p *mockProvider) Provide(c cid.Cid) error {
295299
*p = append(*p, c)
296300
return nil
297301
}
302+
298303
func TestProviding(t *testing.T) {
299304
t.Parallel()
300305
a := assert.New(t)
301306

307+
ctx, cancel := context.WithCancel(context.Background())
308+
defer cancel()
309+
302310
bgen := butil.NewBlockGenerator()
303-
blocks := bgen.Blocks(9)
311+
blocks := bgen.Blocks(12)
304312

305313
exchange := blockstore.NewBlockstore(ds.NewMapDatastore())
306314

@@ -309,51 +317,75 @@ func TestProviding(t *testing.T) {
309317
var added []cid.Cid
310318

311319
// Adding one block provide it.
312-
a.NoError(blockservice.AddBlock(context.Background(), blocks[0]))
320+
a.NoError(blockservice.AddBlock(ctx, blocks[0]))
313321
added = append(added, blocks[0].Cid())
314322
blocks = blocks[1:]
315323

316324
// Adding multiple blocks provide them.
317-
a.NoError(blockservice.AddBlocks(context.Background(), blocks[0:2]))
325+
a.NoError(blockservice.AddBlocks(ctx, blocks[0:2]))
318326
added = append(added, blocks[0].Cid(), blocks[1].Cid())
319327
blocks = blocks[2:]
320328

321329
// Downloading one block provide it.
322-
a.NoError(exchange.Put(context.Background(), blocks[0]))
323-
_, err := blockservice.GetBlock(context.Background(), blocks[0].Cid())
330+
a.NoError(exchange.Put(ctx, blocks[0]))
331+
_, err := blockservice.GetBlock(ctx, blocks[0].Cid())
324332
a.NoError(err)
325333
added = append(added, blocks[0].Cid())
326334
blocks = blocks[1:]
327335

328336
// Downloading multiple blocks provide them.
329-
a.NoError(exchange.PutMany(context.Background(), blocks[0:2]))
337+
a.NoError(exchange.PutMany(ctx, blocks[0:2]))
330338
cids := []cid.Cid{blocks[0].Cid(), blocks[1].Cid()}
331339
var got []cid.Cid
332-
for b := range blockservice.GetBlocks(context.Background(), cids) {
340+
for b := range blockservice.GetBlocks(ctx, cids) {
333341
got = append(got, b.Cid())
334342
}
335343
added = append(added, cids...)
336344
a.ElementsMatch(cids, got)
337345
blocks = blocks[2:]
338346

339-
session := NewSession(context.Background(), blockservice)
347+
session := NewSession(ctx, blockservice)
340348

341349
// Downloading one block over a session provide it.
342-
a.NoError(exchange.Put(context.Background(), blocks[0]))
343-
_, err = session.GetBlock(context.Background(), blocks[0].Cid())
350+
a.NoError(exchange.Put(ctx, blocks[0]))
351+
_, err = session.GetBlock(ctx, blocks[0].Cid())
344352
a.NoError(err)
345353
added = append(added, blocks[0].Cid())
346354
blocks = blocks[1:]
347355

348356
// Downloading multiple blocks over a session provide them.
349-
a.NoError(exchange.PutMany(context.Background(), blocks[0:2]))
357+
a.NoError(exchange.PutMany(ctx, blocks[0:2]))
358+
cids = []cid.Cid{blocks[0].Cid(), blocks[1].Cid()}
359+
got = nil
360+
for b := range session.GetBlocks(ctx, cids) {
361+
got = append(got, b.Cid())
362+
}
363+
a.ElementsMatch(cids, got)
364+
added = append(added, cids...)
365+
blocks = blocks[2:]
366+
367+
// Test wrapping the blockservice like nopfs does.
368+
session = NewSession(ctx, wrappedBlockservice{blockservice})
369+
370+
// Downloading one block over a wrapped blockservice session provide it.
371+
a.NoError(exchange.Put(ctx, blocks[0]))
372+
_, err = session.GetBlock(ctx, blocks[0].Cid())
373+
a.NoError(err)
374+
added = append(added, blocks[0].Cid())
375+
blocks = blocks[1:]
376+
377+
// Downloading multiple blocks over a wrapped blockservice session provide them.
378+
a.NoError(exchange.PutMany(ctx, blocks[0:2]))
350379
cids = []cid.Cid{blocks[0].Cid(), blocks[1].Cid()}
351380
got = nil
352-
for b := range session.GetBlocks(context.Background(), cids) {
381+
for b := range session.GetBlocks(ctx, cids) {
353382
got = append(got, b.Cid())
354383
}
355384
a.ElementsMatch(cids, got)
356385
added = append(added, cids...)
386+
blocks = blocks[2:]
387+
388+
a.Empty(blocks)
357389

358390
a.ElementsMatch(added, []cid.Cid(prov))
359391
}

blockservice/providing_blockstore.go

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package blockservice
2+
3+
import (
4+
"context"
5+
6+
"github.com/ipfs/boxo/blockstore"
7+
"github.com/ipfs/boxo/provider"
8+
blocks "github.com/ipfs/go-block-format"
9+
)
10+
11+
var _ blockstore.Blockstore = providingBlockstore{}
12+
13+
type providingBlockstore struct {
14+
blockstore.Blockstore
15+
provider provider.Provider
16+
}
17+
18+
func (pbs providingBlockstore) Put(ctx context.Context, b blocks.Block) error {
19+
if err := pbs.Blockstore.Put(ctx, b); err != nil {
20+
return err
21+
}
22+
23+
return pbs.provider.Provide(b.Cid())
24+
}
25+
26+
func (pbs providingBlockstore) PutMany(ctx context.Context, b []blocks.Block) error {
27+
if err := pbs.Blockstore.PutMany(ctx, b); err != nil {
28+
return err // what are the semantics here, did some blocks were put ? assume PutMany is atomic
29+
}
30+
31+
for _, b := range b {
32+
if err := pbs.provider.Provide(b.Cid()); err != nil {
33+
return err // this can only error if the whole provider is done for
34+
}
35+
}
36+
return nil
37+
}

0 commit comments

Comments
 (0)