I would like a gRPC server, written in Go, to be able to implement something 
like the following. My question is whether the "good thing" happens enough to 
provide a benefit. It is fine if sometimes the "good thing" does not happen.

The server is receiving updates from a large number of clients by an RPC, say 
"Update", and then forward each on one to a third agent. The forwarding-on is 
normally speedy, but might fail or be slow because it's just another RPC to a 
different system. Each update has an id which guarantees idempotency, so 
duplicated updates are not an issue, but lost ones must be prevented.

I would like to have the return from "Update" imply "I have taken possession of 
the update; it is or will be forwarded on", resulting in a trivial server stub 
which does this:

return msg.Forward(ctx)

This is fine and clearly correct; the if the Update RPC is canceled the error 
will indicate to the client that it cannot assume the update is or will be 
forwarded, and can retry appropriately.

But it would be nice to avoid that retry in the commonest case, which is simply 
that forwarding on took too long for some reason, but everything else is good. 
In that situation, I would like my server to notice that the Forward call was 
canceled, persist the update to disk, and then return success from the Update 
stub. I want that successful return to be propagated back to the client. (This 
is the "good thing.") This would be:

err := msg.Forward(ctx)
if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) 
{
  msg.PersistToDisk()
  return true
}
return err

If the success is occasionally not delivered to the client, that's fine; at 
least we tried to avoid the unnecessary retry. But if it's never delivered 
back, then there's no point in doing the persistence - the client will just 
always retry and so it doesn't matter. And we don't want to just write every 
update to disk, because in the normal case Forward proceeds quickly and there's 
no need to stick another I/O bottleneck in the way on the most common fast path.

So will the "good thing" happen, at least often? That is: if a Go gRPC server 
stub is canceled, and the stub implementation handles the context cancelation 
by returning success, will that (at least often) be reflected back to the RPC 
client?

[Note that in a non-gRPC context, in which these are just all local function 
calls, the answer is defined by the Go Language Specification - the return 
value is of course returned no matter what the state of the context may be.]

Thomas

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion visit 
https://groups.google.com/d/msgid/golang-nuts/de635afa0e28433cafa6c60ba0c10b80%40deshaw.com.

Reply via email to