From 63a2855a49df0492090416004f8a56fa05845405 Mon Sep 17 00:00:00 2001 From: Brian Tiger Chow Date: Tue, 23 Sep 2014 16:41:58 -0400 Subject: [PATCH] feat(util:context) add error logging to context This commit... is a second attempt at: https://github.com/jbenet/go-ipfs/pull/68 partially addresses: https://github.com/jbenet/go-ipfs/issues/66 is the result of discussion at: https://gist.github.com/perfmode/f2951c1ed3a02c484d0b --- util/context.go | 35 +++++++++++++++++++++++++++++++++++ util/context_test.go | 28 ++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 util/context.go create mode 100644 util/context_test.go 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") + } +}