diff --git a/util/context.go b/util/context.go new file mode 100644 index 000000000..6826ac225 --- /dev/null +++ b/util/context.go @@ -0,0 +1,35 @@ +package util + +import ( + context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context" +) + +// privateChanType protects the channel. Since this is a package-private type, +// only methods defined in this package can get the error value from the +// context. +type privateChanType chan error + +const errLogKey = "the key used to extract the error log from the context" + +// ContextWithErrorLog returns a copy of parent and an error channel that can +// be used to receive errors sent with the LogError method. +func ContextWithErrorLog(parent context.Context) (context.Context, <-chan error) { + errs := make(privateChanType) + ctx := context.WithValue(parent, errLogKey, errs) + return ctx, errs +} + +// LogError logs the error to the owner of the context. +// +// If this context was created with ContextWithErrorLog, then this method +// passes the error to context creator over an unbuffered channel. +// +// If this context was created by other means, this method is a no-op. +func LogError(ctx context.Context, err error) { + v := ctx.Value(errLogKey) + errs, ok := v.(privateChanType) + if !ok { + return + } + errs <- err +} diff --git a/util/context_test.go b/util/context_test.go new file mode 100644 index 000000000..a7249ab09 --- /dev/null +++ b/util/context_test.go @@ -0,0 +1,28 @@ +package util + +import ( + "errors" + "testing" + + context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context" +) + +func TestLogErrorDoesNotBlockWhenCtxIsNotSetUpForLogging(t *testing.T) { + ctx := context.Background() + LogError(ctx, errors.New("ignore me")) +} + +func TestLogErrorReceivedByParent(t *testing.T) { + + expected := errors.New("From child to parent") + + ctx, errs := ContextWithErrorLog(context.Background()) + + go func() { + LogError(ctx, expected) + }() + + if err := <-errs; err != expected { + t.Fatal("didn't receive the expected error") + } +}