Skip to content

Commit bca3ea7

Browse files
committed
feat: defer car writing until after first block
Ref: ipld/go-car#493 Ref: ipfs/boxo#458
1 parent 413c421 commit bca3ea7

File tree

5 files changed

+25
-14
lines changed

5 files changed

+25
-14
lines changed

carstream.go

+3-8
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package frisbii
33
import (
44
"bytes"
55
"context"
6-
"fmt"
76
"io"
87

98
// codecs we care about
@@ -17,7 +16,7 @@ import (
1716

1817
"github.com/ipfs/go-cid"
1918
"github.com/ipld/go-car/v2"
20-
carstorage "github.com/ipld/go-car/v2/storage"
19+
"github.com/ipld/go-car/v2/storage/deferred"
2120
"github.com/ipld/go-ipld-prime/datamodel"
2221
"github.com/ipld/go-ipld-prime/linking"
2322
cidlink "github.com/ipld/go-ipld-prime/linking/cid"
@@ -32,11 +31,7 @@ func StreamCar(
3231
out io.Writer,
3332
request trustlessutils.Request,
3433
) error {
35-
carWriter, err := carstorage.NewWritable(out, []cid.Cid{request.Root}, car.WriteAsCarV1(true), car.AllowDuplicatePuts(request.Duplicates))
36-
if err != nil {
37-
return fmt.Errorf("failed to create car writer: %w", err)
38-
}
39-
34+
carWriter := deferred.NewDeferredCarWriterForStream(out, []cid.Cid{request.Root}, car.AllowDuplicatePuts(request.Duplicates))
4035
requestLsys.StorageReadOpener = carPipe(requestLsys.StorageReadOpener, carWriter)
4136

4237
cfg := traversal.Config{Root: request.Root, Selector: request.Selector()}
@@ -52,7 +47,7 @@ func StreamCar(
5247
return nil
5348
}
5449

55-
func carPipe(orig linking.BlockReadOpener, car carstorage.WritableCar) linking.BlockReadOpener {
50+
func carPipe(orig linking.BlockReadOpener, car *deferred.DeferredCarWriter) linking.BlockReadOpener {
5651
return func(lc linking.LinkContext, lnk datamodel.Link) (io.Reader, error) {
5752
r, err := orig(lc, lnk)
5853
if err != nil {

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ require (
1010
github.com/ipfs/go-ipld-format v0.6.0
1111
github.com/ipfs/go-log/v2 v2.5.1
1212
github.com/ipfs/go-unixfsnode v1.8.0
13-
github.com/ipld/go-car/v2 v2.12.0
13+
github.com/ipld/go-car/v2 v2.12.1-0.20230902103537-b12674b3b055
1414
github.com/ipld/go-ipld-prime v0.21.0
1515
github.com/ipld/go-trustless-utils v0.0.0
1616
github.com/ipld/ipld/specs v0.0.0-20230826120441-91918996e8eb

go.sum

+2-2
Original file line numberDiff line numberDiff line change
@@ -271,8 +271,8 @@ github.com/ipfs/go-unixfs v0.4.4 h1:D/dLBOJgny5ZLIur2vIXVQVW0EyDHdOMBDEhgHrt6rY=
271271
github.com/ipfs/go-unixfsnode v1.8.0 h1:yCkakzuE365glu+YkgzZt6p38CSVEBPgngL9ZkfnyQU=
272272
github.com/ipfs/go-unixfsnode v1.8.0/go.mod h1:HxRu9HYHOjK6HUqFBAi++7DVoWAHn0o4v/nZ/VA+0g8=
273273
github.com/ipfs/go-verifcid v0.0.2 h1:XPnUv0XmdH+ZIhLGKg6U2vaPaRDXb9urMyNVCE7uvTs=
274-
github.com/ipld/go-car/v2 v2.12.0 h1:4wpZwCEK2Th7lrVhkAio7fnxZb6COrSHxSz9xCR6FOo=
275-
github.com/ipld/go-car/v2 v2.12.0/go.mod h1:QkdjjFNGit2GIkpQ953KBwowuoukoM75nP/JI1iDJdo=
274+
github.com/ipld/go-car/v2 v2.12.1-0.20230902103537-b12674b3b055 h1:XU67HCQO3g/l/f3aey6LdqlE93ALRe/sbGj0T5yviXU=
275+
github.com/ipld/go-car/v2 v2.12.1-0.20230902103537-b12674b3b055/go.mod h1:QkdjjFNGit2GIkpQ953KBwowuoukoM75nP/JI1iDJdo=
276276
github.com/ipld/go-codec-dagpb v1.6.0 h1:9nYazfyu9B1p3NAgfVdpRco3Fs2nFC72DqVsMj6rOcc=
277277
github.com/ipld/go-codec-dagpb v1.6.0/go.mod h1:ANzFhfP2uMJxRBr8CE+WQWs5UsNa0pYtmKZ+agnUw9s=
278278
github.com/ipld/go-ipld-adl-hamt v0.0.0-20220616142416-9004dbd839e0 h1:QAI/Ridj0+foHD6epbxmB4ugxz9B4vmNdYSmQLGa05E=

httpipfs_test.go

+15-1
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,16 @@ import (
1212
"github.com/ipld/frisbii"
1313
"github.com/ipld/go-car/v2"
1414
cidlink "github.com/ipld/go-ipld-prime/linking/cid"
15+
"github.com/ipld/go-ipld-prime/storage/memstore"
1516
trustlesshttp "github.com/ipld/go-trustless-utils/http"
1617
trustlesspathing "github.com/ipld/ipld/specs/pkg-go/trustless-pathing"
1718
"github.com/stretchr/testify/require"
1819
)
1920

2021
func TestHttpIpfsHandler(t *testing.T) {
21-
handler := frisbii.NewHttpIpfs(context.Background(), cidlink.DefaultLinkSystem())
22+
lsys := cidlink.DefaultLinkSystem()
23+
lsys.SetReadStorage(&CorrectedMemStore{Store: &memstore.Store{}})
24+
handler := frisbii.NewHttpIpfs(context.Background(), lsys)
2225
testServer := httptest.NewServer(handler)
2326
defer testServer.Close()
2427

@@ -63,6 +66,17 @@ func TestHttpIpfsHandler(t *testing.T) {
6366
expectedStatusCode: http.StatusBadRequest,
6467
expectedBody: "invalid Accept header; unsupported: \"applicaiton/json\"",
6568
},
69+
{
70+
// special case where we get to start the request because everything
71+
// is valid, but the block isn't in our blockstore; passing this
72+
// depends on deferring writing the CAR output until after we've
73+
// at least loaded the first block.
74+
name: "block not found",
75+
path: "/ipfs/bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi",
76+
accept: trustlesshttp.RequestAcceptHeader(true),
77+
expectedStatusCode: http.StatusInternalServerError,
78+
expectedBody: "failed to load root node: failed to load root CID: ipld: could not find bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi",
79+
},
6680
} {
6781
t.Run(testCase.name, func(t *testing.T) {
6882
req := require.New(t)

multireadablestorage_test.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -86,16 +86,18 @@ type CorrectedMemStore struct {
8686

8787
func (cms *CorrectedMemStore) Get(ctx context.Context, key string) ([]byte, error) {
8888
data, err := cms.Store.Get(ctx, key)
89+
cid, _ := cid.Cast([]byte(key))
8990
if err != nil && err.Error() == "404" {
90-
err = format.ErrNotFound{}
91+
err = format.ErrNotFound{Cid: cid}
9192
}
9293
return data, err
9394
}
9495

9596
func (cms *CorrectedMemStore) GetStream(ctx context.Context, key string) (io.ReadCloser, error) {
9697
rc, err := cms.Store.GetStream(ctx, key)
98+
cid, _ := cid.Cast([]byte(key))
9799
if err != nil && err.Error() == "404" {
98-
err = format.ErrNotFound{}
100+
err = format.ErrNotFound{Cid: cid}
99101
}
100102
return rc, err
101103
}

0 commit comments

Comments
 (0)