runtraversal.go 1.03 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
package runtraversal

import (
	"bytes"
	"io"

	"github.com/ipfs/go-graphsync/ipldutil"
	ipld "github.com/ipld/go-ipld-prime"
)

// 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 {
			traverser.Error(err)
		} else {
			var blockBuffer bytes.Buffer
			_, err = io.Copy(&blockBuffer, result)
			if err != nil {
				traverser.Error(err)
			} else {
				data = blockBuffer.Bytes()
				err = traverser.Advance(&blockBuffer)
				if err != nil {
					return err
				}
			}
		}
		err = sendResponse(lnk, data)
		if err != nil {
			return err
		}
	}
}