Skip to content

Commit

Permalink
Merge 24a9223 into de8e6a1
Browse files Browse the repository at this point in the history
  • Loading branch information
donutloop committed May 9, 2021
2 parents de8e6a1 + 24a9223 commit fd2a48c
Show file tree
Hide file tree
Showing 22 changed files with 197 additions and 141 deletions.
4 changes: 3 additions & 1 deletion bus/bus_test.go
Expand Up @@ -13,11 +13,13 @@ type msg struct {
body string
}

var handlerError error = errors.New("handler error")

func TestHandlerReturnsError(t *testing.T) {
b := bus.New()

err := b.AddHandler(func(m *msg) error {
return errors.New("handler error")
return handlerError
})
if err != nil {
t.Fatal(err)
Expand Down
12 changes: 11 additions & 1 deletion cmd/xcode/main.go
Expand Up @@ -15,15 +15,21 @@ func main() {
log.SetFlags(0)

fs := flag.NewFlagSet("xcode", flag.ExitOnError)

var (
in = fs.String("in", "", "input file")
out = fs.String("out", "", "output file")
pkg = fs.String("pkg", "", "package name")
typ = fs.String("type", "", "type")
mode = fs.String("mode", "", "activate mode")
)

fs.Usage = usageFor(fs, "xcode [flags]")
fs.Parse(os.Args[1:])

err := fs.Parse(os.Args[1:])
if err != nil {
log.Fatal(err)
}

if *in == "" {
log.Fatal("input file is missing")
Expand Down Expand Up @@ -61,11 +67,14 @@ func main() {

func usageFor(fs *flag.FlagSet, short string) func() {
return func() {

fmt.Fprintf(os.Stdout, "USAGE\n")
fmt.Fprintf(os.Stdout, " %s\n", short)
fmt.Fprintf(os.Stdout, "\n")
fmt.Fprintf(os.Stdout, "FLAGS\n")

tw := tabwriter.NewWriter(os.Stdout, 0, 2, 2, ' ', 0)

fs.VisitAll(func(f *flag.Flag) {
if f.Name == "debug" {
return
Expand All @@ -76,6 +85,7 @@ func usageFor(fs *flag.FlagSet, short string) func() {
}
fmt.Fprintf(tw, " -%s %s\t%s\n", f.Name, f.DefValue, f.Usage)
})

tw.Flush()
}
}
6 changes: 4 additions & 2 deletions concurrent/runner_test.go
Expand Up @@ -8,6 +8,8 @@ import (
"github.com/donutloop/toolkit/concurrent"
)

var StubErr error = errors.New("stub error")

func TestRun(t *testing.T) {
counter := int32(0)
errs := concurrent.Run(
Expand Down Expand Up @@ -38,7 +40,7 @@ func TestRunFail(t *testing.T) {
counter := int32(0)
errs := concurrent.Run(
func() error {
return errors.New("stub error")
return StubErr
},
func() error {
panic("check isolation of goroutine")
Expand All @@ -64,7 +66,7 @@ func BenchmarkRun(b *testing.B) {
for n := 0; n < b.N; n++ {
concurrent.Run(
func() error {
return errors.New("stub error")
return StubErr
},
func() error {
panic("check isolation of goroutine")
Expand Down
1 change: 1 addition & 0 deletions debugutil/http_log_round_tripper_test.go
Expand Up @@ -16,6 +16,7 @@ type logger struct{}
func (l logger) Errorf(format string, v ...interface{}) {
log.Println(fmt.Sprintf(format, v...))
}

func (l logger) Infof(format string, v ...interface{}) {
log.Println(fmt.Sprintf(format, v...))
}
Expand Down
5 changes: 2 additions & 3 deletions debugutil/prettysprint_test.go
Expand Up @@ -5,12 +5,11 @@
package debugutil_test

import (
"testing"

"github.com/donutloop/toolkit/debugutil"
"testing"
)

func Test(t *testing.T) {
func TestDebugger(t *testing.T){

strings := "dummy"

Expand Down
10 changes: 9 additions & 1 deletion event/hook.go
Expand Up @@ -2,6 +2,7 @@ package event

import (
"fmt"
"runtime/debug"
"sync"
)

Expand Down Expand Up @@ -43,10 +44,17 @@ func (h *Hooks) Fire() []error {
func hookWrapper(wg *sync.WaitGroup, hook func(), errc chan error) {
defer func() {
if v := recover(); v != nil {
errc <- fmt.Errorf("hook is panicked (%v)", v)
errc <- &RecoverError{Err: v, Stack: debug.Stack()}
}
wg.Done()
}()

hook()
}

type RecoverError struct {
Err interface{}
Stack []byte
}

func (e *RecoverError) Error() string { return fmt.Sprintf("Do panicked: %v", e.Err) }
2 changes: 1 addition & 1 deletion event/hook_test.go
Expand Up @@ -48,7 +48,7 @@ func TestHooksPanic(t *testing.T) {
t.Fatalf("error count is bad (%d)", len(errs))
}

expectedMessage := "hook is panicked (check isolation of goroutine)"
expectedMessage := "Do panicked: check isolation of goroutine"
if errs[0].Error() != expectedMessage {
t.Fatalf(`unexpected error message (actual: "%s", expected: "%s")`, errs[0].Error(), expectedMessage)
}
Expand Down
12 changes: 10 additions & 2 deletions internal/ast/ast.go
Expand Up @@ -37,7 +37,7 @@ func ChangeType(typeName string, newType string, debugMode string) func(file *as
for i := 0; i < len(x.Args); i++ {
v, ok := x.Args[i].(*ast.Ident)
if ok {
if strings.ToLower(typeName) == strings.ToLower(v.Name) {
if strings.EqualFold(typeName, v.Name) {
x.Args[i] = &ast.Ident{Name: fmt.Sprintf("%s.(%s)", v.Name, newType)}
}
}
Expand Down Expand Up @@ -73,8 +73,16 @@ func ModifyAst(dest []byte, fns ...func(*ast.File) *ast.File) ([]byte, error) {

var buf bytes.Buffer
if err := format.Node(&buf, destFset, destF); err != nil {
return nil, fmt.Errorf("couldn't format package code (%v)", err)
return nil, &BadFormattedCode{Err: err}
}

return buf.Bytes(), nil
}

type BadFormattedCode struct {
Err error
}

func (e BadFormattedCode) Error() string {
return fmt.Sprintf("couldn't format package code (%v)", e.Err)
}
2 changes: 1 addition & 1 deletion lease/doc_test.go
Expand Up @@ -10,7 +10,7 @@ import (
func ExampleLeaser_Lease() {

leaser := lease.NewLeaser()
leaser.Lease("cleanup-cache", time.Duration(1*time.Second), func() {
leaser.Lease("cleanup-cache", 1*time.Second, func() {
fmt.Println("cleaned up cache")
})

Expand Down
10 changes: 9 additions & 1 deletion loop/loop.go
Expand Up @@ -6,6 +6,7 @@ package loop

import (
"fmt"
"runtime/debug"
"time"
)

Expand Down Expand Up @@ -41,7 +42,7 @@ func (l *looper) doLoop() {
defer ticker.Stop()
defer func() {
if v := recover(); v != nil {
l.err <- fmt.Errorf("event is panicked (%v)", v)
l.err <- &RecoverError{Err: v, Stack: debug.Stack()}
}
}()

Expand All @@ -57,3 +58,10 @@ func (l *looper) doLoop() {
}
}
}

type RecoverError struct {
Err interface{}
Stack []byte
}

func (e *RecoverError) Error() string { return fmt.Sprintf("Do panicked: %v", e.Err) }
12 changes: 8 additions & 4 deletions loop/loop_test.go
Expand Up @@ -13,6 +13,8 @@ import (
"github.com/donutloop/toolkit/loop"
)

var StubErr error = errors.New("stub error")

func TestLoop(t *testing.T) {
var counter int
l := loop.NewLooper(1*time.Millisecond, func() error {
Expand All @@ -28,22 +30,24 @@ func TestLoop(t *testing.T) {
}
}

var GoroutineError error = fmt.Errorf("check isolation of goroutine")

func TestLoopFail(t *testing.T) {
l := loop.NewLooper(1*time.Millisecond, func() error {
panic(fmt.Errorf("check isolation of goroutine"))
panic(GoroutineError)
})

err := <-l.Error()
if err.Error() != "event is panicked (check isolation of goroutine)" {
if err.Error() != "Do panicked: check isolation of goroutine" {
t.Fatal(err)
}

l = loop.NewLooper(1*time.Millisecond, func() error {
return errors.New("stub error")
return StubErr
})

err = <-l.Error()
if err.Error() != "stub error" {
if !errors.Is(err, StubErr) {
t.Fatal(err)
}
}
Expand Down
8 changes: 3 additions & 5 deletions multierror/doc_test.go
Expand Up @@ -3,16 +3,14 @@ package multierror_test
import (
"fmt"

"errors"

"github.com/donutloop/toolkit/multierror"
)

func Example() {
errs := []error{
errors.New("error connect to db failed"),
errors.New("error marschaling json"),
connectionError,
marshalError,
}
fmt.Println(multierror.New(errs...))
// Output: multiple errors: error connect to db failed; error marschaling json
// Output: multiple errors: error connect to db failed; error marshal json
}
2 changes: 1 addition & 1 deletion promise/promise_test.go
Expand Up @@ -29,7 +29,7 @@ func TestDoPanic(t *testing.T) {
t.Fatal("unexpected nil error")
}

if !strings.Contains(err.Error(), "Do panicked") {
if !strings.Contains(err.Error(), "Do panicked ") {
t.Fatalf(`unexpected error message (actual: "%s", expected: "promise is panicked (*)")`, err.Error())
}
}
Expand Down
12 changes: 8 additions & 4 deletions retry/retry.go
Expand Up @@ -23,18 +23,18 @@ type Retrier interface {

type RetryableDo func() (bool, error)

func NewRetrier(InitialIntervalInSeconds, maxIntervalInSeconds float64, tries uint, strategy Strategy) Retrier {
func NewRetrier(initialIntervalInSeconds, maxIntervalInSeconds float64, tries uint, strategy Strategy) Retrier {

if strategy == nil {
panic("strategy is missing")
}

if InitialIntervalInSeconds > maxIntervalInSeconds {
panic(fmt.Sprintf("initial interval is greater than max (initial: %f, max: %f)", InitialIntervalInSeconds, maxIntervalInSeconds))
if initialIntervalInSeconds > maxIntervalInSeconds {
panic(fmt.Sprintf("initial interval is greater than max (initial: %f, max: %f)", initialIntervalInSeconds, maxIntervalInSeconds))
}

return &retrier{
InitialIntervalInSeconds: InitialIntervalInSeconds,
InitialIntervalInSeconds: initialIntervalInSeconds,
maxIntervalInSeconds: maxIntervalInSeconds,
strategy: strategy,
tries: tries,
Expand All @@ -54,8 +54,11 @@ func (r *retrier) Retry(ctx context.Context, do RetryableDo) error {
}

var err error

var done bool

for i := uint(0); !done && i < r.tries; i++ {

done, err = do()

if ctx.Err() != nil {
Expand All @@ -74,6 +77,7 @@ func (r *retrier) Retry(ctx context.Context, do RetryableDo) error {
if !done {
return new(ExhaustedError)
}

return nil
}

Expand Down
8 changes: 5 additions & 3 deletions retry/retry_test.go
Expand Up @@ -12,11 +12,14 @@ import (
"github.com/donutloop/toolkit/retry"
)

var StubErr error = errors.New("stub error")

func TestRetrierRetryContextDeadlineFail(t *testing.T) {
r := retry.NewRetrier(0.125, 0.25, 2, new(retry.Exp))

ctx, cancel := context.WithCancel(context.Background())
cancel()

err := r.Retry(ctx, func() (bool, error) {
return true, nil
})
Expand Down Expand Up @@ -45,15 +48,14 @@ func TestRetrierRetry(t *testing.T) {
func TestRetrierRetryTriggerError(t *testing.T) {
r := retry.NewRetrier(0.125, 0.25, 2, new(retry.Exp))
err := r.Retry(context.Background(), func() (bool, error) {
return false, errors.New("stub error")
return false, StubErr
})

if err == nil {
t.Fatal("unexpected nil error")
}

expectedErrorMessage := "stub error"
if err.Error() != expectedErrorMessage {
if !errors.Is(err, StubErr) {
t.Fatal(err)
}
}
Expand Down
8 changes: 8 additions & 0 deletions retry/roundtripper.go
Expand Up @@ -13,7 +13,9 @@ type RoundTripper struct {

// NewRoundTripper is constructing a new retry RoundTripper with given default values.
func NewRoundTripper(next http.RoundTripper, maxInterval, initialInterval float64, tries uint, blacklistStatusCodes []int, strategy Strategy) *RoundTripper {

retrier := NewRetrier(initialInterval, maxInterval, tries, strategy)

return &RoundTripper{
retrier: retrier,
next: next,
Expand All @@ -25,7 +27,9 @@ func NewRoundTripper(next http.RoundTripper, maxInterval, initialInterval float6
// if rt.next.RoundTrip(req) is return an error then it will abort the process retrying a request.
func (rt *RoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
var resp *http.Response

err := rt.retrier.Retry(context.Background(), func() (b bool, e error) {

var err error
resp, err = rt.next.RoundTrip(req)
if err != nil {
Expand All @@ -52,13 +56,17 @@ func (rt *RoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {

// isStatusCode iterates over list of black listed status code that it could abort the process of retrying a request
func (rt *RoundTripper) isStatusCode(statusCode int) bool {

if rt.blacklistStatusCodes == nil {
return false
}

for _, sc := range rt.blacklistStatusCodes {

if statusCode == sc {
return true
}
}

return false
}

0 comments on commit fd2a48c

Please sign in to comment.