Skip to content

Commit

Permalink
Unify restate.Service and restate.Object into restate.Reflect
Browse files Browse the repository at this point in the history
These names pollute the namespace a bit and they have similar signatures
anyway. Reflect is more descriptive of what they do.
  • Loading branch information
jackkleeman committed Aug 13, 2024
1 parent 7e3afc4 commit 8471325
Show file tree
Hide file tree
Showing 8 changed files with 152 additions and 253 deletions.
8 changes: 4 additions & 4 deletions examples/codegen/proto/helloworld_restate.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions examples/ticketreservation/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ import (
func main() {
server := server.NewRestate().
// Handlers can be inferred from object methods
Bind(restate.Object(&userSession{})).
Bind(restate.Object(&ticketService{})).
Bind(restate.Service(&checkout{}))
Bind(restate.Reflect(&userSession{})).
Bind(restate.Reflect(&ticketService{})).
Bind(restate.Reflect(&checkout{}))

if err := server.Start(context.Background(), ":9080"); err != nil {
slog.Error("application exited unexpectedly", "err", err.Error())
Expand Down
34 changes: 14 additions & 20 deletions handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,18 @@ type Void = encoding.Void
// ObjectHandler is the required set of methods for a Virtual Object handler.
type ObjectHandler interface {
Call(ctx ObjectContext, request []byte) (output []byte, err error)
getOptions() *options.ObjectHandlerOptions
Handler
}

// ServiceHandler is the required set of methods for a Service handler.
type ServiceHandler interface {
Call(ctx Context, request []byte) (output []byte, err error)
getOptions() *options.ServiceHandlerOptions
Handler
}

// Handler is implemented by all Restate handlers
type Handler interface {
sealed()
getOptions() *options.HandlerOptions
InputPayload() *encoding.InputPayload
OutputPayload() *encoding.OutputPayload
HandlerType() *internal.ServiceHandlerType
Expand All @@ -51,16 +49,16 @@ type ObjectSharedHandlerFn[I any, O any] func(ctx ObjectSharedContext, input I)

type serviceHandler[I any, O any] struct {
fn ServiceHandlerFn[I, O]
options options.ServiceHandlerOptions
options options.HandlerOptions
}

var _ ServiceHandler = (*serviceHandler[struct{}, struct{}])(nil)

// NewServiceHandler converts a function of signature [ServiceHandlerFn] into a handler on a Restate service.
func NewServiceHandler[I any, O any](fn ServiceHandlerFn[I, O], opts ...options.ServiceHandlerOption) *serviceHandler[I, O] {
o := options.ServiceHandlerOptions{}
func NewServiceHandler[I any, O any](fn ServiceHandlerFn[I, O], opts ...options.HandlerOption) *serviceHandler[I, O] {
o := options.HandlerOptions{}
for _, opt := range opts {
opt.BeforeServiceHandler(&o)
opt.BeforeHandler(&o)
}
return &serviceHandler[I, O]{
fn: fn,
Expand Down Expand Up @@ -104,28 +102,26 @@ func (h *serviceHandler[I, O]) HandlerType() *internal.ServiceHandlerType {
return nil
}

func (h *serviceHandler[I, O]) getOptions() *options.ServiceHandlerOptions {
func (h *serviceHandler[I, O]) getOptions() *options.HandlerOptions {
return &h.options
}

func (h *serviceHandler[I, O]) sealed() {}

type objectHandler[I any, O any] struct {
// only one of exclusiveFn or sharedFn should be set, as indicated by handlerType
exclusiveFn ObjectHandlerFn[I, O]
sharedFn ObjectSharedHandlerFn[I, O]
options options.ObjectHandlerOptions
options options.HandlerOptions
handlerType internal.ServiceHandlerType
}

var _ ObjectHandler = (*objectHandler[struct{}, struct{}])(nil)

// NewObjectHandler converts a function of signature [ObjectHandlerFn] into an exclusive-mode handler on a Virtual Object.
// The handler will have access to a full [ObjectContext] which may mutate state.
func NewObjectHandler[I any, O any](fn ObjectHandlerFn[I, O], opts ...options.ObjectHandlerOption) *objectHandler[I, O] {
o := options.ObjectHandlerOptions{}
func NewObjectHandler[I any, O any](fn ObjectHandlerFn[I, O], opts ...options.HandlerOption) *objectHandler[I, O] {
o := options.HandlerOptions{}
for _, opt := range opts {
opt.BeforeObjectHandler(&o)
opt.BeforeHandler(&o)
}
return &objectHandler[I, O]{
exclusiveFn: fn,
Expand All @@ -136,10 +132,10 @@ func NewObjectHandler[I any, O any](fn ObjectHandlerFn[I, O], opts ...options.Ob

// NewObjectSharedHandler converts a function of signature [ObjectSharedHandlerFn] into a shared-mode handler on a Virtual Object.
// The handler will only have access to a [ObjectSharedContext] which can only read a snapshot of state.
func NewObjectSharedHandler[I any, O any](fn ObjectSharedHandlerFn[I, O], opts ...options.ObjectHandlerOption) *objectHandler[I, O] {
o := options.ObjectHandlerOptions{}
func NewObjectSharedHandler[I any, O any](fn ObjectSharedHandlerFn[I, O], opts ...options.HandlerOption) *objectHandler[I, O] {
o := options.HandlerOptions{}
for _, opt := range opts {
opt.BeforeObjectHandler(&o)
opt.BeforeHandler(&o)
}
return &objectHandler[I, O]{
sharedFn: fn,
Expand Down Expand Up @@ -190,12 +186,10 @@ func (h *objectHandler[I, O]) OutputPayload() *encoding.OutputPayload {
return encoding.OutputPayloadFor(h.options.Codec, o)
}

func (h *objectHandler[I, O]) getOptions() *options.ObjectHandlerOptions {
func (h *objectHandler[I, O]) getOptions() *options.HandlerOptions {
return &h.options
}

func (h *objectHandler[I, O]) HandlerType() *internal.ServiceHandlerType {
return &h.handlerType
}

func (h *objectHandler[I, O]) sealed() {}
28 changes: 6 additions & 22 deletions internal/options/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,34 +51,18 @@ type RunOption interface {
BeforeRun(*RunOptions)
}

type ServiceHandlerOptions struct {
type HandlerOptions struct {
Codec encoding.PayloadCodec
}

type ServiceHandlerOption interface {
BeforeServiceHandler(*ServiceHandlerOptions)
type HandlerOption interface {
BeforeHandler(*HandlerOptions)
}

type ObjectHandlerOptions struct {
Codec encoding.PayloadCodec
}

type ObjectHandlerOption interface {
BeforeObjectHandler(*ObjectHandlerOptions)
}

type ServiceOptions struct {
DefaultCodec encoding.PayloadCodec
}

type ServiceOption interface {
BeforeService(*ServiceOptions)
}

type ObjectOptions struct {
type ServiceDefinitionOptions struct {
DefaultCodec encoding.PayloadCodec
}

type ObjectOption interface {
BeforeObject(*ObjectOptions)
type ServiceDefinitionOption interface {
BeforeServiceDefinition(*ServiceDefinitionOptions)
}
19 changes: 5 additions & 14 deletions options.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ import (

// re-export for use in generated code
type CallOption = options.CallOption
type ServiceOption = options.ServiceOption
type ObjectOption = options.ObjectOption
type ServiceDefinitionOption = options.ServiceDefinitionOption

type withCodec struct {
codec encoding.Codec
Expand Down Expand Up @@ -43,21 +42,13 @@ type withPayloadCodec struct {
codec encoding.PayloadCodec
}

var _ options.ServiceHandlerOption = withPayloadCodec{}
var _ options.ServiceOption = withPayloadCodec{}
var _ options.ObjectHandlerOption = withPayloadCodec{}
var _ options.ObjectOption = withPayloadCodec{}
var _ options.HandlerOption = withPayloadCodec{}
var _ options.ServiceDefinitionOption = withPayloadCodec{}

func (w withPayloadCodec) BeforeServiceHandler(opts *options.ServiceHandlerOptions) {
func (w withPayloadCodec) BeforeHandler(opts *options.HandlerOptions) {
opts.Codec = w.codec
}
func (w withPayloadCodec) BeforeObjectHandler(opts *options.ObjectHandlerOptions) {
opts.Codec = w.codec
}
func (w withPayloadCodec) BeforeService(opts *options.ServiceOptions) {
opts.DefaultCodec = w.codec
}
func (w withPayloadCodec) BeforeObject(opts *options.ObjectOptions) {
func (w withPayloadCodec) BeforeServiceDefinition(opts *options.ServiceDefinitionOptions) {
opts.DefaultCodec = w.codec
}

Expand Down
17 changes: 2 additions & 15 deletions protoc-gen-go-restate/restate.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,15 +241,15 @@ func genService(gen *protogen.Plugin, g *protogen.GeneratedFile, service *protog
g.P(deprecationComment)
}

g.P("func New", service.GoName, "Server(srv ", serverType, ", opts ...", routerOptionType(gen, g, service), ") ", sdkPackage.Ident("ServiceDefinition"), " {")
g.P("func New", service.GoName, "Server(srv ", serverType, ", opts ...", sdkPackage.Ident("ServiceDefinitionOption"), ") ", sdkPackage.Ident("ServiceDefinition"), " {")
g.P("// If the following call panics, it indicates Unimplemented", serverType, " was")
g.P("// embedded by pointer and is nil. This will cause panics if an")
g.P("// unimplemented method is ever invoked, so we test this at initialization")
g.P("// time to prevent it from happening at runtime later due to I/O.")
g.P("if t, ok := srv.(interface { testEmbeddedByValue() }); ok {")
g.P("t.testEmbeddedByValue()")
g.P("}")
g.P("sOpts := append([]", routerOptionType(gen, g, service), "{", sdkPackage.Ident("WithProtoJSON"), "}, opts...)")
g.P("sOpts := append([]", sdkPackage.Ident("ServiceDefinitionOption"), "{", sdkPackage.Ident("WithProtoJSON"), "}, opts...)")
g.P("router := ", newRouterType(gen, g, service), `("`, service.GoName, `", sOpts...)`)
for _, method := range service.Methods {
g.P(`router = router.Handler("`, method.GoName, `",`, newHandlerType(gen, g, method), "(srv.", method.GoName, "))")
Expand Down Expand Up @@ -347,19 +347,6 @@ func newRouterType(gen *protogen.Plugin, g *protogen.GeneratedFile, service *pro
}
}

func routerOptionType(gen *protogen.Plugin, g *protogen.GeneratedFile, service *protogen.Service) string {
serviceType := proto.GetExtension(service.Desc.Options().(*descriptorpb.ServiceOptions), sdk.E_ServiceType).(sdk.ServiceType)
switch serviceType {
case sdk.ServiceType_SERVICE:
return g.QualifiedGoIdent(sdkPackage.Ident("ServiceOption"))
case sdk.ServiceType_VIRTUAL_OBJECT:
return g.QualifiedGoIdent(sdkPackage.Ident("ObjectOption"))
default:
gen.Error(fmt.Errorf("Unexpected service type: %s", serviceType.String()))
return ""
}
}

func newHandlerType(gen *protogen.Plugin, g *protogen.GeneratedFile, method *protogen.Method) string {
serviceType := proto.GetExtension(method.Parent.Desc.Options().(*descriptorpb.ServiceOptions), sdk.E_ServiceType).(sdk.ServiceType)
handlerType := proto.GetExtension(method.Desc.Options().(*descriptorpb.MethodOptions), sdk.E_HandlerType).(sdk.HandlerType)
Expand Down
Loading

0 comments on commit 8471325

Please sign in to comment.