veyron2/vdl,ipc: Enable reflection to capture stream types.
Before this CL, the ReflectInvoker would require the following
style for each server method:
type impl struct{}
func (*impl) Method(call ipc.ServerCall, ...)
This is nice for simplicity, but makes it impossible for the
ReflectInvoker to capture the stream types through reflection.
In fact we'd never know whether Method performs streaming at all.
The new ReflectInvoker implemented in this CL requires the
following:
type impl struct{}
func (*impl) NonStreamMethod(ctx ipc.ServerContext, ...)
func (*impl) StreamMethod(ctx *StreamMethodContext, ...)
type StreamMethodContext struct {
ipc.ServerCall
}
// Init function is required.
func (s *StreamMethodContext) Init(call ipc.ServerCall) {
s.ServerCall = call
}
// RecvStream is required for in-streaming.
func (s *StreamMethodContext) RecvStream() interface {
Advance() bool
Value() InStreamType
Err() error
}
// SendStream is required for out-streaming.
func (s *StreamMethodContext) SendStream() interface {
Send(OutStreamType) error
}
Basically the first in-arg to the server method must be a
context. For non-streaming methods, you use ipc.ServerContext.
For streaming methods, you must pass a pointer to a struct that
implements our streaming API. In the example above, StreamMethod
passes in *StreamMethodContext, which is a thin typesafe shim
built on top of ipc.ServerCall.
Doing this allows ReflectInvoker to capture the streaming in and
out types. This improves the Signature that we return, and also
makes it easier for developers to specify their stream types when
they're not use a VDL; rather than needing to specify the
streaming types in a meta-description somehow (which can get out
of sync with the actual code), they simply adhere to our stream
API.
In order to make this work, I've also added a special
ipc.GlobContext and ipc.GlobContextStub. Glob is a special
concept that our framework code needs to handle, and the vdl
compiler has been updated to treat these as special-cases.
I've also updated the VDL generated Go stubs to export the
concrete context stubs, for use by the server stubs. I also
simplified the context and call stubs to truly be lightweight
typesafe wrappers over the underlying ipc.Call and ipc.ServerCall
respectively.
Finally I've updated a bunch of existing non-streaming methods to
specify ipc.ServerContext as the first argument. This isn't
required (yet); I still allow ipc.ServerCall to be passed in. I
plan to eradicate that support in a subsequent CL; this CL was
getting too large as it is.
Change-Id: I36cdde67d0ee5cb67536d8267878c6ba1a19447c
35 files changed