runtraversal.go 1.15 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 22 23 24 25 26 27 28 29 30 31 32 33
)

// 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(
	loader ipld.Loader,
	traverser ipldutil.Traverser,
	sendResponse ResponseSender) error {
	for {
		isComplete, err := traverser.IsComplete()
		if isComplete {
			return err
		}
		lnk, lnkCtx := traverser.CurrentRequest()
		result, err := loader(lnk, lnkCtx)
		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
		}
	}
}