merr: refactor Wrap/WrapSkip/New to take multiple contexts rather than annotations
This commit is contained in:
parent
4303da03cc
commit
4536db8968
5
m/m.go
5
m/m.go
@ -6,7 +6,6 @@ package m
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"log"
|
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
|
||||||
@ -43,9 +42,9 @@ func ServiceContext() context.Context {
|
|||||||
ctx, logLevelStr := mcfg.WithString(ctx, "log-level", "info", "Maximum log level which will be printed.")
|
ctx, logLevelStr := mcfg.WithString(ctx, "log-level", "info", "Maximum log level which will be printed.")
|
||||||
ctx = mrun.WithStartHook(ctx, func(context.Context) error {
|
ctx = mrun.WithStartHook(ctx, func(context.Context) error {
|
||||||
logLevel := mlog.LevelFromString(*logLevelStr)
|
logLevel := mlog.LevelFromString(*logLevelStr)
|
||||||
log.Printf("setting log level to %v", logLevel)
|
|
||||||
if logLevel == nil {
|
if logLevel == nil {
|
||||||
return merr.New(ctx, "invalid log level", "log-level", *logLevelStr)
|
ctx := mctx.Annotate(ctx, "log-level", *logLevelStr)
|
||||||
|
return merr.New("invalid log level", ctx)
|
||||||
}
|
}
|
||||||
logger.SetMaxLevel(logLevel)
|
logger.SetMaxLevel(logLevel)
|
||||||
return nil
|
return nil
|
||||||
|
@ -90,7 +90,8 @@ func (cli SourceCLI) Parse(params []Param) ([]ParamValue, error) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
if !pvOk {
|
if !pvOk {
|
||||||
return nil, merr.New(context.Background(), "unexpected config parameter", "param", arg)
|
ctx := mctx.Annotate(context.Background(), "param", arg)
|
||||||
|
return nil, merr.New("unexpected config parameter", ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,7 +122,8 @@ func (cli SourceCLI) Parse(params []Param) ([]ParamValue, error) {
|
|||||||
pvStrValOk = false
|
pvStrValOk = false
|
||||||
}
|
}
|
||||||
if pvOk && !pvStrValOk {
|
if pvOk && !pvStrValOk {
|
||||||
return nil, merr.New(p.Context, "param expected a value", "param", key)
|
ctx := mctx.Annotate(p.Context, "param", key)
|
||||||
|
return nil, merr.New("param expected a value", ctx)
|
||||||
}
|
}
|
||||||
return pvs, nil
|
return pvs, nil
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,8 @@ func (env SourceEnv) Parse(params []Param) ([]ParamValue, error) {
|
|||||||
for _, kv := range kvs {
|
for _, kv := range kvs {
|
||||||
split := strings.SplitN(kv, "=", 2)
|
split := strings.SplitN(kv, "=", 2)
|
||||||
if len(split) != 2 {
|
if len(split) != 2 {
|
||||||
return nil, merr.New(context.Background(), "malformed environment key/value pair", "kv", kv)
|
ctx := mctx.Annotate(context.Background(), "kv", kv)
|
||||||
|
return nil, merr.New("malformed environment key/value pair", ctx)
|
||||||
}
|
}
|
||||||
k, v := split[0], split[1]
|
k, v := split[0], split[1]
|
||||||
if p, ok := pM[k]; ok {
|
if p, ok := pM[k]; ok {
|
||||||
|
@ -110,8 +110,9 @@ func populate(params []Param, src Source) error {
|
|||||||
if !p.Required {
|
if !p.Required {
|
||||||
continue
|
continue
|
||||||
} else if _, ok := pvM[hash]; !ok {
|
} else if _, ok := pvM[hash]; !ok {
|
||||||
return merr.New(p.Context, "required parameter is not set",
|
ctx := mctx.Annotate(p.Context,
|
||||||
"param", paramFullName(mctx.Path(p.Context), p.Name))
|
"param", paramFullName(mctx.Path(p.Context), p.Name))
|
||||||
|
return merr.New("required parameter is not set", ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,7 +134,7 @@ func populate(params []Param, src Source) error {
|
|||||||
// of the Params which were provided by the respective Source.
|
// of the Params which were provided by the respective Source.
|
||||||
//
|
//
|
||||||
// Source may be nil to indicate that no configuration is provided. Only default
|
// Source may be nil to indicate that no configuration is provided. Only default
|
||||||
// values will be used, and if any paramaters are required this will error.
|
// values will be used, and if any parameters are required this will error.
|
||||||
func Populate(ctx context.Context, src Source) error {
|
func Populate(ctx context.Context, src Source) error {
|
||||||
return populate(collectParams(ctx), src)
|
return populate(collectParams(ctx), src)
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ import (
|
|||||||
"math/big"
|
"math/big"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/mediocregopher/mediocre-go-lib/mctx"
|
||||||
"github.com/mediocregopher/mediocre-go-lib/merr"
|
"github.com/mediocregopher/mediocre-go-lib/merr"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -59,7 +60,8 @@ func (pk PublicKey) verify(s Signature, r io.Reader) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := rsa.VerifyPSS(&pk.PublicKey, crypto.SHA256, h.Sum(nil), s.sig, nil); err != nil {
|
if err := rsa.VerifyPSS(&pk.PublicKey, crypto.SHA256, h.Sum(nil), s.sig, nil); err != nil {
|
||||||
return merr.Wrap(context.Background(), ErrInvalidSig, "sig", s)
|
ctx := mctx.Annotate(context.Background(), "sig", s)
|
||||||
|
return merr.Wrap(ErrInvalidSig, ctx)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -89,12 +91,14 @@ func (pk *PublicKey) UnmarshalText(b []byte) error {
|
|||||||
str := string(b)
|
str := string(b)
|
||||||
strEnc, ok := stripPrefix(str, pubKeyV0)
|
strEnc, ok := stripPrefix(str, pubKeyV0)
|
||||||
if !ok || len(strEnc) <= hex.EncodedLen(8) {
|
if !ok || len(strEnc) <= hex.EncodedLen(8) {
|
||||||
return merr.Wrap(context.Background(), errMalformedPublicKey, "pubKeyStr", str)
|
ctx := mctx.Annotate(context.Background(), "pubKeyStr", str)
|
||||||
|
return merr.Wrap(errMalformedPublicKey, ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
b, err := hex.DecodeString(strEnc)
|
b, err := hex.DecodeString(strEnc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return merr.Wrap(context.Background(), err, "pubKeyStr", str)
|
ctx := mctx.Annotate(context.Background(), "pubKeyStr", str)
|
||||||
|
return merr.Wrap(err, ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
pk.E = int(binary.BigEndian.Uint64(b))
|
pk.E = int(binary.BigEndian.Uint64(b))
|
||||||
@ -185,17 +189,17 @@ func (pk *PrivateKey) UnmarshalText(b []byte) error {
|
|||||||
str := string(b)
|
str := string(b)
|
||||||
strEnc, ok := stripPrefix(str, privKeyV0)
|
strEnc, ok := stripPrefix(str, privKeyV0)
|
||||||
if !ok {
|
if !ok {
|
||||||
return merr.Wrap(context.Background(), errMalformedPrivateKey)
|
return merr.Wrap(errMalformedPrivateKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
b, err := hex.DecodeString(strEnc)
|
b, err := hex.DecodeString(strEnc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return merr.Wrap(context.Background(), errMalformedPrivateKey)
|
return merr.Wrap(errMalformedPrivateKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
e, n := binary.Uvarint(b)
|
e, n := binary.Uvarint(b)
|
||||||
if n <= 0 {
|
if n <= 0 {
|
||||||
return merr.Wrap(context.Background(), errMalformedPrivateKey)
|
return merr.Wrap(errMalformedPrivateKey)
|
||||||
}
|
}
|
||||||
pk.PublicKey.E = int(e)
|
pk.PublicKey.E = int(e)
|
||||||
b = b[n:]
|
b = b[n:]
|
||||||
@ -206,7 +210,7 @@ func (pk *PrivateKey) UnmarshalText(b []byte) error {
|
|||||||
}
|
}
|
||||||
l, n := binary.Uvarint(b)
|
l, n := binary.Uvarint(b)
|
||||||
if n <= 0 {
|
if n <= 0 {
|
||||||
err = merr.Wrap(context.Background(), errMalformedPrivateKey)
|
err = merr.Wrap(errMalformedPrivateKey)
|
||||||
}
|
}
|
||||||
b = b[n:]
|
b = b[n:]
|
||||||
i := new(big.Int)
|
i := new(big.Int)
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package mcrypto
|
package mcrypto
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"crypto/hmac"
|
"crypto/hmac"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
@ -77,9 +76,9 @@ func (s Secret) sign(r io.Reader) (Signature, error) {
|
|||||||
func (s Secret) verify(sig Signature, r io.Reader) error {
|
func (s Secret) verify(sig Signature, r io.Reader) error {
|
||||||
sigB, err := s.signRaw(r, uint8(len(sig.sig)), sig.salt, sig.t)
|
sigB, err := s.signRaw(r, uint8(len(sig.sig)), sig.salt, sig.t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return merr.Wrap(context.Background(), err, "sig", sig)
|
return merr.Wrap(err)
|
||||||
} else if !hmac.Equal(sigB, sig.sig) {
|
} else if !hmac.Equal(sigB, sig.sig) {
|
||||||
return merr.Wrap(context.Background(), ErrInvalidSig, "sig", sig)
|
return merr.Wrap(ErrInvalidSig)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package mcrypto
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
@ -67,12 +66,12 @@ func (s *Signature) UnmarshalText(b []byte) error {
|
|||||||
str := string(b)
|
str := string(b)
|
||||||
strEnc, ok := stripPrefix(str, sigV0)
|
strEnc, ok := stripPrefix(str, sigV0)
|
||||||
if !ok || len(strEnc) < hex.EncodedLen(10) {
|
if !ok || len(strEnc) < hex.EncodedLen(10) {
|
||||||
return merr.Wrap(context.Background(), errMalformedSig, "sigStr", str)
|
return merr.Wrap(errMalformedSig)
|
||||||
}
|
}
|
||||||
|
|
||||||
b, err := hex.DecodeString(strEnc)
|
b, err := hex.DecodeString(strEnc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return merr.Wrap(context.Background(), err, "sigStr", str)
|
return merr.Wrap(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
unixNano, b := int64(binary.BigEndian.Uint64(b[:8])), b[8:]
|
unixNano, b := int64(binary.BigEndian.Uint64(b[:8])), b[8:]
|
||||||
@ -82,7 +81,7 @@ func (s *Signature) UnmarshalText(b []byte) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
} else if len(b) < 1+int(b[0]) {
|
} else if len(b) < 1+int(b[0]) {
|
||||||
err = merr.Wrap(context.Background(), errMalformedSig, "sigStr", str)
|
err = merr.Wrap(errMalformedSig)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
out := b[1 : 1+b[0]]
|
out := b[1 : 1+b[0]]
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/mediocregopher/mediocre-go-lib/mctx"
|
||||||
"github.com/mediocregopher/mediocre-go-lib/merr"
|
"github.com/mediocregopher/mediocre-go-lib/merr"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -69,11 +70,13 @@ func (u *UUID) UnmarshalText(b []byte) error {
|
|||||||
str := string(b)
|
str := string(b)
|
||||||
strEnc, ok := stripPrefix(str, uuidV0)
|
strEnc, ok := stripPrefix(str, uuidV0)
|
||||||
if !ok || len(strEnc) != hex.EncodedLen(16) {
|
if !ok || len(strEnc) != hex.EncodedLen(16) {
|
||||||
return merr.Wrap(context.Background(), errMalformedUUID, "uuidStr", str)
|
ctx := mctx.Annotate(context.Background(), "uuidStr", str)
|
||||||
|
return merr.Wrap(errMalformedUUID, ctx)
|
||||||
}
|
}
|
||||||
b, err := hex.DecodeString(strEnc)
|
b, err := hex.DecodeString(strEnc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return merr.Wrap(context.Background(), err, "uuidStr", str)
|
ctx := mctx.Annotate(context.Background(), "uuidStr", str)
|
||||||
|
return merr.Wrap(errMalformedUUID, ctx)
|
||||||
}
|
}
|
||||||
u.b = b
|
u.b = b
|
||||||
return nil
|
return nil
|
||||||
|
@ -278,9 +278,14 @@ func mergeAnnotations(ctxA, ctxB context.Context) context.Context {
|
|||||||
//
|
//
|
||||||
// NOTE this will panic if no Contexts are passed in.
|
// NOTE this will panic if no Contexts are passed in.
|
||||||
func MergeAnnotations(ctxs ...context.Context) context.Context {
|
func MergeAnnotations(ctxs ...context.Context) context.Context {
|
||||||
ctxA := ctxs[0]
|
return MergeAnnotationsInto(ctxs[0], ctxs[1:]...)
|
||||||
for _, ctxB := range ctxs[1:] {
|
}
|
||||||
ctxA = mergeAnnotations(ctxA, ctxB)
|
|
||||||
}
|
// MergeAnnotationsInto is a convenience function which works like
|
||||||
return ctxA
|
// MergeAnnotations.
|
||||||
|
func MergeAnnotationsInto(ctx context.Context, ctxs ...context.Context) context.Context {
|
||||||
|
for _, ctxB := range ctxs {
|
||||||
|
ctx = mergeAnnotations(ctx, ctxB)
|
||||||
|
}
|
||||||
|
return ctx
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ func WithBigQuery(parent context.Context, gce *mdb.GCE) (context.Context, *BigQu
|
|||||||
mlog.Info("connecting to bigquery", bq.ctx)
|
mlog.Info("connecting to bigquery", bq.ctx)
|
||||||
var err error
|
var err error
|
||||||
bq.Client, err = bigquery.NewClient(innerCtx, bq.gce.Project, bq.gce.ClientOptions()...)
|
bq.Client, err = bigquery.NewClient(innerCtx, bq.gce.Project, bq.gce.ClientOptions()...)
|
||||||
return merr.Wrap(bq.ctx, err)
|
return merr.Wrap(err, bq.ctx)
|
||||||
})
|
})
|
||||||
ctx = mrun.WithStopHook(ctx, func(context.Context) error {
|
ctx = mrun.WithStopHook(ctx, func(context.Context) error {
|
||||||
return bq.Client.Close()
|
return bq.Client.Close()
|
||||||
@ -100,12 +100,12 @@ func (bq *BigQuery) Table(
|
|||||||
mlog.Debug("creating/grabbing table", bq.ctx)
|
mlog.Debug("creating/grabbing table", bq.ctx)
|
||||||
schema, err := bigquery.InferSchema(schemaObj)
|
schema, err := bigquery.InferSchema(schemaObj)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, merr.Wrap(ctx, err)
|
return nil, nil, merr.Wrap(err, ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
ds := bq.Dataset(dataset)
|
ds := bq.Dataset(dataset)
|
||||||
if err := ds.Create(ctx, nil); err != nil && !isErrAlreadyExists(err) {
|
if err := ds.Create(ctx, nil); err != nil && !isErrAlreadyExists(err) {
|
||||||
return nil, nil, merr.Wrap(ctx, err)
|
return nil, nil, merr.Wrap(err, ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
table := ds.Table(tableName)
|
table := ds.Table(tableName)
|
||||||
@ -114,7 +114,7 @@ func (bq *BigQuery) Table(
|
|||||||
Schema: schema,
|
Schema: schema,
|
||||||
}
|
}
|
||||||
if err := table.Create(ctx, meta); err != nil && !isErrAlreadyExists(err) {
|
if err := table.Create(ctx, meta); err != nil && !isErrAlreadyExists(err) {
|
||||||
return nil, nil, merr.Wrap(ctx, err)
|
return nil, nil, merr.Wrap(err, ctx)
|
||||||
}
|
}
|
||||||
uploader := table.Uploader()
|
uploader := table.Uploader()
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ func WithBigTable(parent context.Context, gce *mdb.GCE, defaultInstance string)
|
|||||||
bt.gce.Project, bt.Instance,
|
bt.gce.Project, bt.Instance,
|
||||||
bt.gce.ClientOptions()...,
|
bt.gce.ClientOptions()...,
|
||||||
)
|
)
|
||||||
return merr.Wrap(bt.ctx, err)
|
return merr.Wrap(err, bt.ctx)
|
||||||
})
|
})
|
||||||
ctx = mrun.WithStopHook(ctx, func(context.Context) error {
|
ctx = mrun.WithStopHook(ctx, func(context.Context) error {
|
||||||
return bt.Client.Close()
|
return bt.Client.Close()
|
||||||
@ -95,14 +95,14 @@ func (bt *Bigtable) EnsureTable(ctx context.Context, name string, colFams ...str
|
|||||||
mlog.Debug("creating admin client", ctx)
|
mlog.Debug("creating admin client", ctx)
|
||||||
adminClient, err := bigtable.NewAdminClient(ctx, bt.gce.Project, bt.Instance)
|
adminClient, err := bigtable.NewAdminClient(ctx, bt.gce.Project, bt.Instance)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return merr.Wrap(ctx, err)
|
return merr.Wrap(err, ctx)
|
||||||
}
|
}
|
||||||
defer adminClient.Close()
|
defer adminClient.Close()
|
||||||
|
|
||||||
mlog.Debug("creating bigtable table (if needed)", ctx)
|
mlog.Debug("creating bigtable table (if needed)", ctx)
|
||||||
err = adminClient.CreateTable(ctx, name)
|
err = adminClient.CreateTable(ctx, name)
|
||||||
if err != nil && !isErrAlreadyExists(err) {
|
if err != nil && !isErrAlreadyExists(err) {
|
||||||
return merr.Wrap(ctx, err)
|
return merr.Wrap(err, ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, colFam := range colFams {
|
for _, colFam := range colFams {
|
||||||
@ -110,7 +110,7 @@ func (bt *Bigtable) EnsureTable(ctx context.Context, name string, colFams ...str
|
|||||||
mlog.Debug("creating bigtable column family (if needed)", ctx)
|
mlog.Debug("creating bigtable column family (if needed)", ctx)
|
||||||
err := adminClient.CreateColumnFamily(ctx, name, colFam)
|
err := adminClient.CreateColumnFamily(ctx, name, colFam)
|
||||||
if err != nil && !isErrAlreadyExists(err) {
|
if err != nil && !isErrAlreadyExists(err) {
|
||||||
return merr.Wrap(ctx, err)
|
return merr.Wrap(err, ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ func WithDatastore(parent context.Context, gce *mdb.GCE) (context.Context, *Data
|
|||||||
mlog.Info("connecting to datastore", ds.ctx)
|
mlog.Info("connecting to datastore", ds.ctx)
|
||||||
var err error
|
var err error
|
||||||
ds.Client, err = datastore.NewClient(innerCtx, ds.gce.Project, ds.gce.ClientOptions()...)
|
ds.Client, err = datastore.NewClient(innerCtx, ds.gce.Project, ds.gce.ClientOptions()...)
|
||||||
return merr.Wrap(ds.ctx, err)
|
return merr.Wrap(err, ds.ctx)
|
||||||
})
|
})
|
||||||
ctx = mrun.WithStopHook(ctx, func(context.Context) error {
|
ctx = mrun.WithStopHook(ctx, func(context.Context) error {
|
||||||
return ds.Client.Close()
|
return ds.Client.Close()
|
||||||
|
@ -62,7 +62,7 @@ func WithPubSub(parent context.Context, gce *mdb.GCE) (context.Context, *PubSub)
|
|||||||
mlog.Info("connecting to pubsub", ps.ctx)
|
mlog.Info("connecting to pubsub", ps.ctx)
|
||||||
var err error
|
var err error
|
||||||
ps.Client, err = pubsub.NewClient(innerCtx, ps.gce.Project, ps.gce.ClientOptions()...)
|
ps.Client, err = pubsub.NewClient(innerCtx, ps.gce.Project, ps.gce.ClientOptions()...)
|
||||||
return merr.Wrap(ps.ctx, err)
|
return merr.Wrap(err, ps.ctx)
|
||||||
})
|
})
|
||||||
ctx = mrun.WithStopHook(ctx, func(context.Context) error {
|
ctx = mrun.WithStopHook(ctx, func(context.Context) error {
|
||||||
return ps.Client.Close()
|
return ps.Client.Close()
|
||||||
@ -93,14 +93,14 @@ func (ps *PubSub) Topic(ctx context.Context, name string, create bool) (*Topic,
|
|||||||
if isErrAlreadyExists(err) {
|
if isErrAlreadyExists(err) {
|
||||||
t.topic = ps.Client.Topic(name)
|
t.topic = ps.Client.Topic(name)
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return nil, merr.Wrap(ctx, merr.Wrap(t.ctx, err))
|
return nil, merr.Wrap(err, t.ctx, ctx)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
t.topic = ps.Client.Topic(name)
|
t.topic = ps.Client.Topic(name)
|
||||||
if exists, err := t.topic.Exists(t.ctx); err != nil {
|
if exists, err := t.topic.Exists(t.ctx); err != nil {
|
||||||
return nil, merr.Wrap(ctx, merr.Wrap(t.ctx, err))
|
return nil, merr.Wrap(err, t.ctx, ctx)
|
||||||
} else if !exists {
|
} else if !exists {
|
||||||
return nil, merr.Wrap(ctx, merr.New(t.ctx, "topic dne"))
|
return nil, merr.New("topic dne", t.ctx, ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return t, nil
|
return t, nil
|
||||||
@ -110,7 +110,7 @@ func (ps *PubSub) Topic(ctx context.Context, name string, create bool) (*Topic,
|
|||||||
func (t *Topic) Publish(ctx context.Context, data []byte) error {
|
func (t *Topic) Publish(ctx context.Context, data []byte) error {
|
||||||
_, err := t.topic.Publish(ctx, &Message{Data: data}).Get(ctx)
|
_, err := t.topic.Publish(ctx, &Message{Data: data}).Get(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return merr.Wrap(ctx, merr.Wrap(t.ctx, err))
|
return merr.Wrap(err, t.ctx, ctx)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -144,14 +144,14 @@ func (t *Topic) Subscription(ctx context.Context, name string, create bool) (*Su
|
|||||||
if isErrAlreadyExists(err) {
|
if isErrAlreadyExists(err) {
|
||||||
s.sub = t.ps.Subscription(name)
|
s.sub = t.ps.Subscription(name)
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return nil, merr.Wrap(ctx, merr.Wrap(s.ctx, err))
|
return nil, merr.Wrap(err, s.ctx, ctx)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
s.sub = t.ps.Subscription(name)
|
s.sub = t.ps.Subscription(name)
|
||||||
if exists, err := s.sub.Exists(ctx); err != nil {
|
if exists, err := s.sub.Exists(ctx); err != nil {
|
||||||
return nil, merr.Wrap(ctx, merr.Wrap(s.ctx, err))
|
return nil, merr.Wrap(err, s.ctx, ctx)
|
||||||
} else if !exists {
|
} else if !exists {
|
||||||
return nil, merr.Wrap(ctx, merr.New(s.ctx, "sub dne"))
|
return nil, merr.New("sub dne", s.ctx, ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return s, nil
|
return s, nil
|
||||||
@ -350,7 +350,7 @@ func (s *Subscription) BatchConsume(
|
|||||||
case ret := <-retCh:
|
case ret := <-retCh:
|
||||||
return ret, nil
|
return ret, nil
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return false, merr.Wrap(ctx, merr.New(s.ctx, "reading from batch grouping process timed out"))
|
return false, merr.New("reading from batch grouping process timed out", s.ctx, ctx)
|
||||||
}
|
}
|
||||||
}, opts)
|
}, opts)
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ func WithMySQL(parent context.Context, defaultDB string) (context.Context, *SQL)
|
|||||||
mlog.Info("connecting to mysql server", sql.ctx)
|
mlog.Info("connecting to mysql server", sql.ctx)
|
||||||
var err error
|
var err error
|
||||||
sql.DB, err = sqlx.ConnectContext(innerCtx, "mysql", dsn)
|
sql.DB, err = sqlx.ConnectContext(innerCtx, "mysql", dsn)
|
||||||
return merr.Wrap(sql.ctx, err)
|
return merr.Wrap(err, sql.ctx)
|
||||||
})
|
})
|
||||||
ctx = mrun.WithStopHook(ctx, func(innerCtx context.Context) error {
|
ctx = mrun.WithStopHook(ctx, func(innerCtx context.Context) error {
|
||||||
mlog.Info("closing connection to sql server", sql.ctx)
|
mlog.Info("closing connection to sql server", sql.ctx)
|
||||||
|
44
merr/merr.go
44
merr/merr.go
@ -57,7 +57,7 @@ func wrap(e error, cp bool) *err {
|
|||||||
|
|
||||||
er2 := &err{
|
er2 := &err{
|
||||||
err: er.err,
|
err: er.err,
|
||||||
attr: make(map[interface{}]interface{}, len(er.attr)),
|
attr: make(map[interface{}]interface{}, len(er.attr)+1),
|
||||||
}
|
}
|
||||||
for k, v := range er.attr {
|
for k, v := range er.attr {
|
||||||
er2.attr[k] = v
|
er2.attr[k] = v
|
||||||
@ -102,47 +102,47 @@ func Value(e error, k interface{}) interface{} {
|
|||||||
|
|
||||||
// WrapSkip is like Wrap but also allows for skipping extra stack frames when
|
// WrapSkip is like Wrap but also allows for skipping extra stack frames when
|
||||||
// embedding the stack into the error.
|
// embedding the stack into the error.
|
||||||
func WrapSkip(ctx context.Context, e error, skip int, kvs ...interface{}) error {
|
func WrapSkip(e error, skip int, ctxs ...context.Context) error {
|
||||||
|
if e == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
er := wrap(e, true)
|
er := wrap(e, true)
|
||||||
if _, ok := getStack(er); !ok {
|
if _, ok := getStack(er); !ok {
|
||||||
setStack(er, skip+1)
|
setStack(er, skip+1)
|
||||||
}
|
}
|
||||||
|
|
||||||
if prevCtx, _ := er.attr[attrKeyCtx].(context.Context); prevCtx != nil {
|
ctx, _ := er.attr[attrKeyCtx].(context.Context)
|
||||||
ctx = mctx.MergeAnnotations(prevCtx, ctx)
|
if ctx != nil {
|
||||||
}
|
ctx = mctx.MergeAnnotationsInto(ctx, ctxs...)
|
||||||
|
} else if len(ctxs) > 0 {
|
||||||
if len(kvs) > 0 {
|
ctx = mctx.MergeAnnotations(ctxs...)
|
||||||
ctx = mctx.Annotate(ctx, kvs...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
er.attr[attrKeyCtx] = ctx
|
er.attr[attrKeyCtx] = ctx
|
||||||
return er
|
return er
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrap takes in an error and returns one which wraps it in merr's inner type,
|
// Wrap returns a copy of the given error wrapped in merr's inner type. It will
|
||||||
// embedding the given Context (which can later be retrieved by Ctx) at the same
|
// perform an mctx.MergeAnnotations on the given Contexts to create a new
|
||||||
// time.
|
// Context, and embed that in the returned error. If the given error already has
|
||||||
//
|
// an embedded Context then ctxs will be merged into that.
|
||||||
// For convenience, extra annotation information can be passed in here as well
|
|
||||||
// via the kvs argument. See mctx.Annotate for more information.
|
|
||||||
//
|
//
|
||||||
// This function automatically embeds stack information into the error as it's
|
// This function automatically embeds stack information into the error as it's
|
||||||
// being stored, using WithStack, unless the error already has stack information
|
// being stored, using WithStack, unless the error already has stack information
|
||||||
// in it.
|
// in it.
|
||||||
func Wrap(ctx context.Context, e error, kvs ...interface{}) error {
|
//
|
||||||
return WrapSkip(ctx, e, 1, kvs...)
|
// Wrapping nil returns nil.
|
||||||
|
func Wrap(e error, ctx ...context.Context) error {
|
||||||
|
return WrapSkip(e, 1, ctx...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// New is a shortcut for:
|
// New is a shortcut for:
|
||||||
// merr.Wrap(ctx, errors.New(str), kvs...)
|
// merr.Wrap(errors.New(str), ctxs...)
|
||||||
func New(ctx context.Context, str string, kvs ...interface{}) error {
|
func New(str string, ctxs ...context.Context) error {
|
||||||
return WrapSkip(ctx, errors.New(str), 1, kvs...)
|
return WrapSkip(errors.New(str), 1, ctxs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO it would be more convenient in a lot of cases if New and Wrap took in a
|
|
||||||
// list of Contexts.
|
|
||||||
|
|
||||||
type annotateKey string
|
type annotateKey string
|
||||||
|
|
||||||
func ctx(e error) context.Context {
|
func ctx(e error) context.Context {
|
||||||
|
@ -10,24 +10,41 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestError(t *T) {
|
func TestError(t *T) {
|
||||||
e := New(context.Background(), "foo",
|
massert.Fatal(t, massert.Nil(Wrap(nil)))
|
||||||
|
|
||||||
|
ctx := mctx.Annotate(context.Background(),
|
||||||
"a", "aaa aaa\n",
|
"a", "aaa aaa\n",
|
||||||
"c", "ccc\nccc\n",
|
"c", "ccc\nccc\n",
|
||||||
"d\t", "weird key but ok",
|
"d\t", "weird key but ok")
|
||||||
)
|
|
||||||
|
{
|
||||||
|
e := New("foo", ctx)
|
||||||
exp := `foo
|
exp := `foo
|
||||||
* a: aaa aaa
|
* a: aaa aaa
|
||||||
* c:
|
* c:
|
||||||
ccc
|
ccc
|
||||||
ccc
|
ccc
|
||||||
* d: weird key but ok
|
* d: weird key but ok
|
||||||
* errLoc: merr/merr_test.go:13`
|
* errLoc: merr/merr_test.go:19`
|
||||||
massert.Fatal(t, massert.Equal(exp, e.Error()))
|
massert.Fatal(t, massert.Equal(exp, e.Error()))
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
e := Wrap(errors.New("foo"), ctx)
|
||||||
|
exp := `foo
|
||||||
|
* a: aaa aaa
|
||||||
|
* c:
|
||||||
|
ccc
|
||||||
|
ccc
|
||||||
|
* d: weird key but ok
|
||||||
|
* errLoc: merr/merr_test.go:31`
|
||||||
|
massert.Fatal(t, massert.Equal(exp, e.Error()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBase(t *T) {
|
func TestBase(t *T) {
|
||||||
errFoo, errBar := errors.New("foo"), errors.New("bar")
|
errFoo, errBar := errors.New("foo"), errors.New("bar")
|
||||||
erFoo := Wrap(context.Background(), errFoo)
|
erFoo := Wrap(errFoo)
|
||||||
massert.Fatal(t, massert.All(
|
massert.Fatal(t, massert.All(
|
||||||
massert.Nil(Base(nil)),
|
massert.Nil(Base(nil)),
|
||||||
massert.Equal(errFoo, Base(erFoo)),
|
massert.Equal(errFoo, Base(erFoo)),
|
||||||
@ -45,7 +62,7 @@ func TestValue(t *T) {
|
|||||||
massert.Nil(Value(nil, "foo")),
|
massert.Nil(Value(nil, "foo")),
|
||||||
))
|
))
|
||||||
|
|
||||||
e1 := New(context.Background(), "foo")
|
e1 := New("foo")
|
||||||
e1 = WithValue(e1, "a", "A")
|
e1 = WithValue(e1, "a", "A")
|
||||||
e2 := WithValue(errors.New("bar"), "a", "A")
|
e2 := WithValue(errors.New("bar"), "a", "A")
|
||||||
massert.Fatal(t, massert.All(
|
massert.Fatal(t, massert.All(
|
||||||
@ -62,7 +79,7 @@ func TestValue(t *T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func mkErr(ctx context.Context, err error) error {
|
func mkErr(ctx context.Context, err error) error {
|
||||||
return Wrap(ctx, err) // it's important that this is line 65
|
return Wrap(err, ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCtx(t *T) {
|
func TestCtx(t *T) {
|
||||||
@ -72,14 +89,14 @@ func TestCtx(t *T) {
|
|||||||
// use mkErr so that it's easy to test that the stack info isn't overwritten
|
// use mkErr so that it's easy to test that the stack info isn't overwritten
|
||||||
// when Wrap is called with ctxB.
|
// when Wrap is called with ctxB.
|
||||||
e := mkErr(ctxA, errors.New("hello"))
|
e := mkErr(ctxA, errors.New("hello"))
|
||||||
e = Wrap(ctxB, e)
|
e = Wrap(e, ctxB)
|
||||||
|
|
||||||
err := massert.Equal(map[string]string{
|
err := massert.Equal(map[string]string{
|
||||||
"0": "ZERO",
|
"0": "ZERO",
|
||||||
"1": "ONE",
|
"1": "ONE",
|
||||||
"2": "TWO",
|
"2": "TWO",
|
||||||
"err": "hello",
|
"err": "hello",
|
||||||
"errLoc": "merr/merr_test.go:65",
|
"errLoc": "merr/merr_test.go:80",
|
||||||
}, mctx.Annotations(Context(e)).StringMap()).Assert()
|
}, mctx.Annotations(Context(e)).StringMap()).Assert()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package merr
|
package merr
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"strings"
|
"strings"
|
||||||
. "testing"
|
. "testing"
|
||||||
|
|
||||||
@ -9,7 +8,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestStack(t *T) {
|
func TestStack(t *T) {
|
||||||
foo := New(context.Background(), "test")
|
foo := New("test")
|
||||||
fooStack, ok := Stack(foo)
|
fooStack, ok := Stack(foo)
|
||||||
massert.Fatal(t, massert.Equal(true, ok))
|
massert.Fatal(t, massert.Equal(true, ok))
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user