samber / mo

🦄 Monads and popular FP abstractions, powered by Go 1.18+ Generics (Option, Result, Either...)
https://pkg.go.dev/github.com/samber/mo
MIT License
2.61k stars 85 forks source link

Future[T] implementation discussion #14

Closed yougahu closed 1 year ago

yougahu commented 1 year ago

If we call (*Future[T]).Then after Future[T] has completed, the Than-callback will never been called. And if we try to Collect a completed Future[T], it could cause deadlock.

for example:

func Test_Future(t *testing.T) {
    completed := make(chan struct{})
    fut := mo.NewFuture(func(resolve func(int), reject func(error)) {
        resolve(1)
        close(completed)
    })

    <-completed
    fut.Then(func(in int) (int, error) {
            fmt.Println(in) // will never been print
        return in, nil
    }).Collect() // deadlock
}

Futures call next future once they have finished, so if we chain a callback on a finished future, the call chain would be broken.

And here is my commit to fix this commit.

yoavsv commented 1 year ago

commit

+1 It also happens if we collect after resolve was called:

func Test_Future(t *testing.T) {
    completed := make(chan struct{})
    fut := mo.NewFuture(func(resolve func(int), reject func(error)) {
        resolve(1)
        close(completed)
    })

    <-completed
    fut.Collect() // deadlock
}
samber commented 1 year ago

Hi there

Thanks for inspecting this. @yougahu I gonna merge your commit and create a new release of mo.