Skip to content

Commit

Permalink
feat: recover panic and return as error
Browse files Browse the repository at this point in the history
  • Loading branch information
jizhuozhi committed Jul 19, 2024
1 parent 6544ef0 commit 12fad19
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 2 deletions.
14 changes: 12 additions & 2 deletions api.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,25 @@ package future
import (
"context"
"errors"
"fmt"
"runtime/debug"
"sync/atomic"
"time"
)

var ErrPanic = errors.New("async panic")
var ErrTimeout = errors.New("future timeout")

func Async[T any](f func() (T, error)) *Future[T] {
s := &state[T]{}
go func() {
defer func() {
if r := recover(); r != nil {
err := fmt.Errorf("%w, err=%s, stack=%s", ErrPanic, r, debug.Stack())
var zero T
s.set(zero, err)
}
}()
val, err := f()
s.set(val, err)
}()
Expand Down Expand Up @@ -72,8 +84,6 @@ func AllOf[T any](fs ...*Future[T]) *Future[struct{}] {
return &Future[struct{}]{state: s}
}

var ErrTimeout = errors.New("future timeout")

func Timeout[T any](f *Future[T], d time.Duration) *Future[T] {
ch := make(chan struct{}, 1)
var val T
Expand Down
9 changes: 9 additions & 0 deletions api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@ func TestAsync(t *testing.T) {
assert.Equal(t, nil, err)
}

func TestAsyncPanic(t *testing.T) {
f := Async(func() (int, error) {
panic("panic")
})
val, err := f.Get()
assert.Equal(t, 0, val)
assert.ErrorIs(t, err, ErrPanic)
}

func TestLazy(t *testing.T) {
f := Lazy(func() (int, error) {
return 1, nil
Expand Down

0 comments on commit 12fad19

Please sign in to comment.