refactor(tvix/nar-bridge): don't buffer blob in memory

Create a pipe, pass the read end, and have a goroutine write to the
write end.

Change-Id: I301c273355705e60113b018e7e84b76972200e8c
Reviewed-on: https://cl.tvl.fyi/c/depot/+/9361
Autosubmit: flokli <flokli@flokli.de>
Tested-by: BuildkiteCI
Reviewed-by: Connor Brewster <cbrewster@hey.com>
This commit is contained in:
Florian Klink 2023-09-18 12:26:03 +03:00 committed by flokli
parent 07af692ecb
commit a9c47ffc50

View file

@ -117,25 +117,34 @@ func renderNar(
}) })
if err != nil { if err != nil {
return nil, fmt.Errorf("unable to get blob: %w", err) return nil, fmt.Errorf("unable to get blob: %w", err)
} }
// TODO: spin up a goroutine producing this. // set up a pipe, let a goroutine write, return the reader.
data := &bytes.Buffer{} pR, pW := io.Pipe()
for {
chunk, err := resp.Recv() go func() {
if errors.Is(err, io.EOF) { for {
break chunk, err := resp.Recv()
if errors.Is(err, io.EOF) {
break
}
if err != nil {
pW.CloseWithError(fmt.Errorf("receiving chunk: %w", err))
return
}
// write the received chunk to the writer part of the pipe
if _, err := io.Copy(pW, bytes.NewReader(chunk.GetData())); err != nil {
log.WithError(err).Error("writing chunk to pipe")
pW.CloseWithError(fmt.Errorf("writing chunk to pipe: %w", err))
return
}
} }
if err != nil { pW.Close()
return nil, fmt.Errorf("read chunk: %w", err)
} }()
_, err = data.Write(chunk.GetData())
if err != nil { return io.NopCloser(pR), nil
return nil, fmt.Errorf("buffer chunk: %w", err)
}
}
return io.NopCloser(data), nil
}, },
) )
if err != nil { if err != nil {