runtraversal.go 1.16 KB
Newer Older
1 2 3 4 5 6 7
package runtraversal

import (
	"bytes"
	"io"

	ipld "github.com/ipld/go-ipld-prime"
8
	"github.com/ipld/go-ipld-prime/traversal"
Hannah Howard's avatar
Hannah Howard committed
9 10

	"github.com/ipfs/go-graphsync/ipldutil"
11 12 13 14 15 16 17 18 19 20 21
)

// ResponseSender sends responses over the network
type ResponseSender func(
	link ipld.Link,
	data []byte,
) error

// RunTraversal wraps a given loader with an interceptor that sends loaded
// blocks out to the network with the given response sender.
func RunTraversal(
Hannah Howard's avatar
Hannah Howard committed
22
	loader ipld.BlockReadOpener,
23 24 25 26 27 28 29 30
	traverser ipldutil.Traverser,
	sendResponse ResponseSender) error {
	for {
		isComplete, err := traverser.IsComplete()
		if isComplete {
			return err
		}
		lnk, lnkCtx := traverser.CurrentRequest()
Hannah Howard's avatar
Hannah Howard committed
31
		result, err := loader(lnkCtx, lnk)
32 33
		var data []byte
		if err != nil {
34
			traverser.Error(traversal.SkipMe{})
35
		} else {
36 37 38 39 40
			blockBuffer, ok := result.(*bytes.Buffer)
			if !ok {
				blockBuffer = new(bytes.Buffer)
				_, err = io.Copy(blockBuffer, result)
			}
41 42 43 44
			if err != nil {
				traverser.Error(err)
			} else {
				data = blockBuffer.Bytes()
45
				err = traverser.Advance(blockBuffer)
46 47 48 49 50 51 52 53 54 55 56
				if err != nil {
					return err
				}
			}
		}
		err = sendResponse(lnk, data)
		if err != nil {
			return err
		}
	}
}