@maxim and to be clear, would it be accurate to say that it is not possible to “drain” using a Selector
? i.e. even if you are not blocking while processing signals you still need to drain every channel with ReceiveAsync
before returning after Select
. So if you are using a selector like @yugandhar, then you need to something like this:
type channelConfig struct {
channel workflow.ReceiveChannel
val interface{}
handler func() // do something with val
}
channels := []*channelConfig{
{
channel: workflow.GetSignalChannel(...)
val: "",
handler func() {
// do something with val
},
},
// etc
}
s := workflow.NewSelector(ctx)
for _, cc := range channels {
s.AddReceive(cc.channel, func (c workflow.ReceiveChannel, _ bool) {
c.Receive(ctx, &cc.val)
cc.handler()
})
}
for keepGoing {
s.Select(ctx)
// not safe to return here
}
// Now I want to return but first I need to make sure that no signals are pending
canReturn := false
for !canReturn {
canReturn = true
for _, cc := range channels {
if ok := c.ReceiveAsync(&cc.val); ok {
canReturn = false
cc.handler()
}
}
}
This should work both with and without blocking calls in the handlers.
Is that right? It feels kind of awkward but I can’t think of a simpler way to express it.