protoactor-go icon indicating copy to clipboard operation
protoactor-go copied to clipboard

Consider make RequestFuture more elegent?

Open jidibinlin opened this issue 2 years ago • 5 comments

Is your feature request related to a problem? Please describe. I`m using protoactor-go for our project.

But I found We can make RequestFuture more elegant. consider this code snippet

// request
roomPidRes, err := System.Root.RequestFuture(roomMgrPid, info, 1*time.Second).Result()

// respond
context.Respond(&FooRoomPid)

err`s type is only time out error. I think we have a chance to reuse it. Describe the solution you'd like We can Define a response struct

type struct Response {
RetValue interface{}
Err error
}

When we use Response struct as a response value. Requester won't wait until timeOut, and when err occurred Requester will know exactly what happened.

jidibinlin avatar Jan 03 '23 07:01 jidibinlin

> err's type is only time out error.
Nope, some errors defined in remote/errors.go and actor/future.go.

> when err occurred Requester will know exactly what happened. Sure, I agree with you. We can just use error which is a built-in interface type in Go.

> We can Define a response struct Do you mean a struct wrapper of Response and Error? It looks like the Optional in Java or Option in rust. That's cool, but it's not zero-cost abstract in Go, and doesn't follow the default Go style right now. Maybe Go will make a change in the future or maybe not.

> When we use Response struct as a response value. Requester won't wait until timeOut Response struct isn't necessary with that case. For example: The ErrTimeout is meant that no response in a certain amount of time.
The ErrDeadLetter is meant that you request to a unreachable actor. ... The ErrBlahblah is meant that blahblah... ... So we can define a lot errors with different cases.

cupen avatar Jan 04 '23 07:01 cupen

> Do you mean a struct wrapper of Response and Error?

Yes! But not like Option in rust. Request won't receive a wrapped Response. It should work in this way。

  1. Requester send a request
// request
res:= System.Root.RequestFuture(roomMgrPid, info, 1*time.Second)
  1. responser return Response
// respond
resp := &Response{
    Err: fooErr
    RetVAlue: fooRetValue
}
context.Respond(resp)
  1. requester call result()
// fooRetValue is resp.fooRetValue fooErr may be protoactor-go`s error type or resp.fooErr
fooRetValue, fooErr := res.Result()

jidibinlin avatar Jan 05 '23 03:01 jidibinlin

> Response struct isn't necessary with that case.

Yes! we can use type switch to distinguish error and return value. But personally I like protoactor-go help me do this so we can.

// fooRetValue is resp.fooRetValue fooErr may be protoactor-go`s error type or resp.fooErr
fooRetValue, fooErr := res.Result()
if fooErr != nil {
// Log this error
}

// do something normal

jidibinlin avatar Jan 05 '23 03:01 jidibinlin

I'm all for investigating this further. There are also an opportunity to make this Generic if needed

rogeralsing avatar Jan 21 '23 14:01 rogeralsing

I also encountered this problem when I ported pubsub from csharp. Check out how I implemented a future-like structure at that time.

https://github.com/asynkron/protoactor-go/blob/8801eff88ab0fc0a6f6948f01c9846ddfbf8b299/cluster/pubsub_producer.go#L120-L146

The logic to wait for the completion of future and determine if there are any errors is like this ⬇️

https://github.com/asynkron/protoactor-go/blob/8801eff88ab0fc0a6f6948f01c9846ddfbf8b299/cluster/pubsub_producer_test.go#L85-L88

May be helpful for the design of future.

Kunduin avatar Jan 30 '23 02:01 Kunduin