diff --git a/_examples/cluster-broadcast/shared/build.sh b/_examples/cluster-broadcast/shared/build.sh index f286ce653..653ecce2a 100755 --- a/_examples/cluster-broadcast/shared/build.sh +++ b/_examples/cluster-broadcast/shared/build.sh @@ -1,2 +1,2 @@ protoc --go_out=. --go_opt=paths=source_relative --proto_path=. protos.proto -protoc -I=. --gograinv2_out=. protos.proto \ No newline at end of file +protoc --go_out=. --go_opt=paths=source_relative --plugin=$GOPATH/bin/protoc-gen-go-grain --go-grain_out=. --go-grain_opt=paths=source_relative protos.proto \ No newline at end of file diff --git a/_examples/cluster-broadcast/shared/protos_protoactor.go b/_examples/cluster-broadcast/shared/protos_grain.pb.go similarity index 97% rename from _examples/cluster-broadcast/shared/protos_protoactor.go rename to _examples/cluster-broadcast/shared/protos_grain.pb.go index cac3f88e7..8f2bfacce 100644 --- a/_examples/cluster-broadcast/shared/protos_protoactor.go +++ b/_examples/cluster-broadcast/shared/protos_grain.pb.go @@ -1,22 +1,19 @@ -// Package shared is generated by protoactor-go/protoc-gen-gograin@0.1.0 +// Code generated by protoc-gen-grain. DO NOT EDIT. +// versions: +// protoc-gen-grain v0.1.0 +// protoc v4.24.3 +// source: protos.proto + package shared import ( - "errors" - "fmt" - "log/slog" - "math" - "time" - - "github.com/asynkron/protoactor-go/actor" - "github.com/asynkron/protoactor-go/cluster" - "google.golang.org/protobuf/proto" -) - -var ( - _ = proto.Marshal - _ = fmt.Errorf - _ = math.Inf + errors "errors" + fmt "fmt" + actor "github.com/asynkron/protoactor-go/actor" + cluster "github.com/asynkron/protoactor-go/cluster" + proto "google.golang.org/protobuf/proto" + slog "log/slog" + time "time" ) var xCalculatorFactory func() Calculator @@ -254,7 +251,6 @@ func (a *CalculatorActor) Receive(ctx actor.Context) { } resp := &cluster.GrainResponse{MessageData: bytes} ctx.Respond(resp) - } default: a.inner.ReceiveDefault(a.ctx) @@ -496,7 +492,6 @@ func (a *TrackerActor) Receive(ctx actor.Context) { } resp := &cluster.GrainResponse{MessageData: bytes} ctx.Respond(resp) - } default: a.inner.ReceiveDefault(a.ctx) diff --git a/_examples/cluster-grain/shared/build.sh b/_examples/cluster-grain/shared/build.sh index 09999ac18..653ecce2a 100755 --- a/_examples/cluster-grain/shared/build.sh +++ b/_examples/cluster-grain/shared/build.sh @@ -1,2 +1,2 @@ protoc --go_out=. --go_opt=paths=source_relative --proto_path=. protos.proto -protoc -I=. -I=$GOPATH/src --gograinv2_out=. protos.proto +protoc --go_out=. --go_opt=paths=source_relative --plugin=$GOPATH/bin/protoc-gen-go-grain --go-grain_out=. --go-grain_opt=paths=source_relative protos.proto \ No newline at end of file diff --git a/_examples/cluster-grain/shared/protos_protoactor.go b/_examples/cluster-grain/shared/protos_grain.pb.go similarity index 91% rename from _examples/cluster-grain/shared/protos_protoactor.go rename to _examples/cluster-grain/shared/protos_grain.pb.go index b21a0febc..ab35695d0 100644 --- a/_examples/cluster-grain/shared/protos_protoactor.go +++ b/_examples/cluster-grain/shared/protos_grain.pb.go @@ -1,22 +1,19 @@ -// Package shared is generated by protoactor-go/protoc-gen-gograin@0.1.0 +// Code generated by protoc-gen-grain. DO NOT EDIT. +// versions: +// protoc-gen-grain v0.1.0 +// protoc v4.24.3 +// source: protos.proto + package shared import ( - "errors" - "fmt" - "log/slog" - "math" - "time" - - "github.com/asynkron/protoactor-go/actor" - "github.com/asynkron/protoactor-go/cluster" - "google.golang.org/protobuf/proto" -) - -var ( - _ = proto.Marshal - _ = fmt.Errorf - _ = math.Inf + errors "errors" + fmt "fmt" + actor "github.com/asynkron/protoactor-go/actor" + cluster "github.com/asynkron/protoactor-go/cluster" + proto "google.golang.org/protobuf/proto" + slog "log/slog" + time "time" ) var xHelloFactory func() Hello @@ -152,7 +149,6 @@ func (a *HelloActor) Receive(ctx actor.Context) { } resp := &cluster.GrainResponse{MessageData: bytes} ctx.Respond(resp) - } default: a.inner.ReceiveDefault(a.ctx) diff --git a/_examples/cluster-metrics/shared/build.sh b/_examples/cluster-metrics/shared/build.sh index 2dc0b4e8b..61715cc81 100755 --- a/_examples/cluster-metrics/shared/build.sh +++ b/_examples/cluster-metrics/shared/build.sh @@ -1,2 +1,2 @@ protoc --go_out=. --go_opt=paths=source_relative --proto_path=. protos.proto -protoc -I=. --gograinv2_out=. protos.proto +protoc --go_out=. --go_opt=paths=source_relative --plugin=$GOPATH/bin/protoc-gen-go-grain --go-grain_out=. --go-grain_opt=paths=source_relative protos.proto diff --git a/_examples/cluster-metrics/shared/protos_protoactor.go b/_examples/cluster-metrics/shared/protos_grain.pb.go similarity index 95% rename from _examples/cluster-metrics/shared/protos_protoactor.go rename to _examples/cluster-metrics/shared/protos_grain.pb.go index 52203a27f..94ab81e4f 100644 --- a/_examples/cluster-metrics/shared/protos_protoactor.go +++ b/_examples/cluster-metrics/shared/protos_grain.pb.go @@ -1,22 +1,19 @@ -// Package shared is generated by protoactor-go/protoc-gen-gograin@0.1.0 +// Code generated by protoc-gen-grain. DO NOT EDIT. +// versions: +// protoc-gen-grain v0.1.0 +// protoc v4.24.3 +// source: protos.proto + package shared import ( - "errors" - "fmt" - "log/slog" - "math" - "time" - - "github.com/asynkron/protoactor-go/actor" - "github.com/asynkron/protoactor-go/cluster" - "google.golang.org/protobuf/proto" -) - -var ( - _ = proto.Marshal - _ = fmt.Errorf - _ = math.Inf + errors "errors" + fmt "fmt" + actor "github.com/asynkron/protoactor-go/actor" + cluster "github.com/asynkron/protoactor-go/cluster" + proto "google.golang.org/protobuf/proto" + slog "log/slog" + time "time" ) var xHelloFactory func() Hello @@ -254,7 +251,6 @@ func (a *HelloActor) Receive(ctx actor.Context) { } resp := &cluster.GrainResponse{MessageData: bytes} ctx.Respond(resp) - } default: a.inner.ReceiveDefault(a.ctx) diff --git a/_examples/cluster-pubsub/build.sh b/_examples/cluster-pubsub/build.sh index 2dc0b4e8b..61715cc81 100755 --- a/_examples/cluster-pubsub/build.sh +++ b/_examples/cluster-pubsub/build.sh @@ -1,2 +1,2 @@ protoc --go_out=. --go_opt=paths=source_relative --proto_path=. protos.proto -protoc -I=. --gograinv2_out=. protos.proto +protoc --go_out=. --go_opt=paths=source_relative --plugin=$GOPATH/bin/protoc-gen-go-grain --go-grain_out=. --go-grain_opt=paths=source_relative protos.proto diff --git a/_examples/cluster-pubsub/protos_protoactor.go b/_examples/cluster-pubsub/protos_protoactor.go deleted file mode 100644 index bed8262cb..000000000 --- a/_examples/cluster-pubsub/protos_protoactor.go +++ /dev/null @@ -1,160 +0,0 @@ -// Package main is generated by protoactor-go/protoc-gen-gograin@0.1.0 -package main - -import ( - "errors" - "fmt" - "log/slog" - "math" - "time" - - "github.com/asynkron/protoactor-go/actor" - "github.com/asynkron/protoactor-go/cluster" - "google.golang.org/protobuf/proto" -) - -var ( - _ = proto.Marshal - _ = fmt.Errorf - _ = math.Inf -) - -var xUserActorFactory func() UserActor - -// UserActorFactory produces a UserActor -func UserActorFactory(factory func() UserActor) { - xUserActorFactory = factory -} - -// GetUserActorGrainClient instantiates a new UserActorGrainClient with given Identity -func GetUserActorGrainClient(c *cluster.Cluster, id string) *UserActorGrainClient { - if c == nil { - panic(fmt.Errorf("nil cluster instance")) - } - if id == "" { - panic(fmt.Errorf("empty id")) - } - return &UserActorGrainClient{Identity: id, cluster: c} -} - -// GetUserActorKind instantiates a new cluster.Kind for UserActor -func GetUserActorKind(opts ...actor.PropsOption) *cluster.Kind { - props := actor.PropsFromProducer(func() actor.Actor { - return &UserActorActor{ - Timeout: 60 * time.Second, - } - }, opts...) - kind := cluster.NewKind("UserActor", props) - return kind -} - -// GetUserActorKind instantiates a new cluster.Kind for UserActor -func NewUserActorKind(factory func() UserActor, timeout time.Duration, opts ...actor.PropsOption) *cluster.Kind { - xUserActorFactory = factory - props := actor.PropsFromProducer(func() actor.Actor { - return &UserActorActor{ - Timeout: timeout, - } - }, opts...) - kind := cluster.NewKind("UserActor", props) - return kind -} - -// UserActor interfaces the services available to the UserActor -type UserActor interface { - Init(ctx cluster.GrainContext) - Terminate(ctx cluster.GrainContext) - ReceiveDefault(ctx cluster.GrainContext) - Connect(*Empty, cluster.GrainContext) (*Empty, error) -} - -// UserActorGrainClient holds the base data for the UserActorGrain -type UserActorGrainClient struct { - Identity string - cluster *cluster.Cluster -} - -// Connect requests the execution on to the cluster with CallOptions -func (g *UserActorGrainClient) Connect(r *Empty, opts ...cluster.GrainCallOption) (*Empty, error) { - bytes, err := proto.Marshal(r) - if err != nil { - return nil, err - } - reqMsg := &cluster.GrainRequest{MethodIndex: 0, MessageData: bytes} - resp, err := g.cluster.Request(g.Identity, "UserActor", reqMsg, opts...) - if err != nil { - return nil, err - } - switch msg := resp.(type) { - case *cluster.GrainResponse: - result := &Empty{} - err = proto.Unmarshal(msg.MessageData, result) - if err != nil { - return nil, err - } - return result, nil - case *cluster.GrainErrorResponse: - return nil, errors.New(msg.Err) - default: - return nil, errors.New("unknown response") - } -} - -// UserActorActor represents the actor structure -type UserActorActor struct { - ctx cluster.GrainContext - inner UserActor - Timeout time.Duration -} - -// Receive ensures the lifecycle of the actor for the received message -func (a *UserActorActor) Receive(ctx actor.Context) { - switch msg := ctx.Message().(type) { - case *actor.Started: //pass - case *cluster.ClusterInit: - a.ctx = cluster.NewGrainContext(ctx, msg.Identity, msg.Cluster) - a.inner = xUserActorFactory() - a.inner.Init(a.ctx) - - if a.Timeout > 0 { - ctx.SetReceiveTimeout(a.Timeout) - } - case *actor.ReceiveTimeout: - ctx.Poison(ctx.Self()) - case *actor.Stopped: - a.inner.Terminate(a.ctx) - case actor.AutoReceiveMessage: // pass - case actor.SystemMessage: // pass - - case *cluster.GrainRequest: - switch msg.MethodIndex { - case 0: - req := &Empty{} - err := proto.Unmarshal(msg.MessageData, req) - if err != nil { - ctx.Logger().Error("[Grain] Connect(Empty) proto.Unmarshal failed.", slog.Any("error", err)) - resp := &cluster.GrainErrorResponse{Err: err.Error()} - ctx.Respond(resp) - return - } - r0, err := a.inner.Connect(req, a.ctx) - if err != nil { - resp := &cluster.GrainErrorResponse{Err: err.Error()} - ctx.Respond(resp) - return - } - bytes, err := proto.Marshal(r0) - if err != nil { - ctx.Logger().Error("[Grain] Connect(Empty) proto.Marshal failed", slog.Any("error", err)) - resp := &cluster.GrainErrorResponse{Err: err.Error()} - ctx.Respond(resp) - return - } - resp := &cluster.GrainResponse{MessageData: bytes} - ctx.Respond(resp) - - } - default: - a.inner.ReceiveDefault(a.ctx) - } -} diff --git a/_examples/cluster-restartgracefully/shared/build.sh b/_examples/cluster-restartgracefully/shared/build.sh index 2dc0b4e8b..61715cc81 100755 --- a/_examples/cluster-restartgracefully/shared/build.sh +++ b/_examples/cluster-restartgracefully/shared/build.sh @@ -1,2 +1,2 @@ protoc --go_out=. --go_opt=paths=source_relative --proto_path=. protos.proto -protoc -I=. --gograinv2_out=. protos.proto +protoc --go_out=. --go_opt=paths=source_relative --plugin=$GOPATH/bin/protoc-gen-go-grain --go-grain_out=. --go-grain_opt=paths=source_relative protos.proto diff --git a/_examples/cluster-restartgracefully/shared/protos_protoactor.go b/_examples/cluster-restartgracefully/shared/protos_grain.pb.go similarity index 95% rename from _examples/cluster-restartgracefully/shared/protos_protoactor.go rename to _examples/cluster-restartgracefully/shared/protos_grain.pb.go index 3f80ebe2c..7387a7daa 100644 --- a/_examples/cluster-restartgracefully/shared/protos_protoactor.go +++ b/_examples/cluster-restartgracefully/shared/protos_grain.pb.go @@ -1,22 +1,19 @@ -// Package shared is generated by protoactor-go/protoc-gen-gograin@0.1.0 +// Code generated by protoc-gen-grain. DO NOT EDIT. +// versions: +// protoc-gen-grain v0.1.0 +// protoc v4.24.3 +// source: protos.proto + package shared import ( - "errors" - "fmt" - "log/slog" - "math" - "time" - - "github.com/asynkron/protoactor-go/actor" - "github.com/asynkron/protoactor-go/cluster" - "google.golang.org/protobuf/proto" -) - -var ( - _ = proto.Marshal - _ = fmt.Errorf - _ = math.Inf + errors "errors" + fmt "fmt" + actor "github.com/asynkron/protoactor-go/actor" + cluster "github.com/asynkron/protoactor-go/cluster" + proto "google.golang.org/protobuf/proto" + slog "log/slog" + time "time" ) var xCalculatorFactory func() Calculator @@ -254,7 +251,6 @@ func (a *CalculatorActor) Receive(ctx actor.Context) { } resp := &cluster.GrainResponse{MessageData: bytes} ctx.Respond(resp) - } default: a.inner.ReceiveDefault(a.ctx) diff --git a/actor/actor_context.go b/actor/actor_context.go index 4d2acc5cb..d1d20b722 100644 --- a/actor/actor_context.go +++ b/actor/actor_context.go @@ -648,7 +648,7 @@ func (ctx *actorContext) stopAllChildren() { return } - var pids = ctx.extras.children.pids + pids := ctx.extras.children.pids for i := len(pids) - 1; i >= 0; i-- { pids[i].sendSystemMessage(ctx.actorSystem, stopMessage) } @@ -706,7 +706,7 @@ func (ctx *actorContext) finalizeStop() { // func (ctx *actorContext) EscalateFailure(reason interface{}, message interface{}) { - //TODO: add callstack to log? + // TODO: add callstack to log? ctx.Logger().Info("[ACTOR] Recovering", slog.Any("self", ctx.self), slog.Any("reason", reason)) // debug setting, allows to output supervision failures in console/error level if ctx.actorSystem.Config.DeveloperSupervisionLogging { diff --git a/protobuf/protoc-gen-gograinv2/Makefile b/protobuf/protoc-gen-gograinv2/Makefile deleted file mode 100644 index a7109f2b3..000000000 --- a/protobuf/protoc-gen-gograinv2/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -install: - go build . - @echo installing to ~/go/bin/protoc-gen-gograinv2 - mv ./protoc-gen-gograinv2 ~/go/bin/ diff --git a/protobuf/protoc-gen-gograinv2/main.go b/protobuf/protoc-gen-gograinv2/main.go deleted file mode 100644 index 00c71fef6..000000000 --- a/protobuf/protoc-gen-gograinv2/main.go +++ /dev/null @@ -1,67 +0,0 @@ -package main - -import ( - "bytes" - "strings" - "text/template" - - google_protobuf "github.com/gogo/protobuf/protoc-gen-gogo/descriptor" - plugin "github.com/gogo/protobuf/protoc-gen-gogo/plugin" - "github.com/gogo/protobuf/vanity/command" -) - -func main() { - req := command.Read() - resp := generateCode(req, "_protoactor.go", true) - command.Write(resp) -} - -func removePackagePrefix(name string, pname string) string { - return strings.Replace(name, "."+pname+".", "", 1) -} - -func generateCode(req *plugin.CodeGeneratorRequest, filenameSuffix string, goFmt bool) *plugin.CodeGeneratorResponse { - response := &plugin.CodeGeneratorResponse{} - for _, f := range req.GetProtoFile() { - if !inStringSlice(f.GetName(), req.FileToGenerate) { - continue - } - - s := generate(f) - - // we only generate grains for proto files containing valid service definition - if len(f.GetService()) > 0 { - fileName := strings.Replace(f.GetName(), ".", "_", 1) + "actor.go" - r := &plugin.CodeGeneratorResponse_File{ - Content: &s, - Name: &fileName, - } - - response.File = append(response.File, r) - } - } - - return response -} - -func inStringSlice(val string, ss []string) bool { - for _, s := range ss { - if val == s { - return true - } - } - return false -} - -func generate(file *google_protobuf.FileDescriptorProto) string { - pkg := ProtoAst(file) - - t := template.New("grain") - t, _ = t.Parse(code) - - var doc bytes.Buffer - t.Execute(&doc, pkg) - s := doc.String() - - return s -} diff --git a/protobuf/protoc-gen-gograinv2/proto.go b/protobuf/protoc-gen-gograinv2/proto.go deleted file mode 100644 index 75ca75b9e..000000000 --- a/protobuf/protoc-gen-gograinv2/proto.go +++ /dev/null @@ -1,165 +0,0 @@ -package main - -import ( - "bytes" - "strings" - "unicode" - "unicode/utf8" - - gogo "github.com/gogo/protobuf/protoc-gen-gogo/descriptor" -) - -// code lifted from gogo proto -var isGoKeyword = map[string]bool{ - "break": true, - "case": true, - "chan": true, - "const": true, - "continue": true, - "default": true, - "else": true, - "defer": true, - "fallthrough": true, - "for": true, - "func": true, - "go": true, - "goto": true, - "if": true, - "import": true, - "interface": true, - "map": true, - "package": true, - "range": true, - "return": true, - "select": true, - "struct": true, - "switch": true, - "type": true, - "var": true, -} - -// ProtoFile reprpesents a parsed proto file -type ProtoFile struct { - PackageName string - Namespace string - Messages []*ProtoMessage - Services []*ProtoService -} - -// ProtoMessage represents a parsed message in a proto file -type ProtoMessage struct { - Name string - PascalName string -} - -// ProtoService represents a parsed service in a proto file -type ProtoService struct { - Name string - PascalName string - Methods []*ProtoMethod -} - -// ProtoMethod represents a parsed method in a proto service -type ProtoMethod struct { - Index int - Name string - PascalName string - Input *ProtoMessage - Output *ProtoMessage - InputStream bool - OutputStream bool -} - -// ProtoAst transforms a FileDescriptor to an AST that can be used for code generation -func ProtoAst(file *gogo.FileDescriptorProto) *ProtoFile { - pkg := &ProtoFile{} - pkg.Namespace = file.GetOptions().GetCsharpNamespace() - - // let us check the option go_package is defined in the file and use that one instead of the - // default one - var packageName string - if file.GetOptions().GetGoPackage() != "" { - packageName = cleanPackageName(file.GetOptions().GetGoPackage()) - } else { - packageName = cleanPackageName(file.GetPackage()) - } - - // let us the go package name - pkg.PackageName = packageName - - messages := make(map[string]*ProtoMessage) - for _, message := range file.GetMessageType() { - m := &ProtoMessage{} - m.Name = message.GetName() - m.PascalName = MakeFirstLowerCase(m.Name) - pkg.Messages = append(pkg.Messages, m) - messages[m.Name] = m - } - - for _, service := range file.GetService() { - s := &ProtoService{} - s.Name = service.GetName() - s.PascalName = MakeFirstLowerCase(s.Name) - pkg.Services = append(pkg.Services, s) - - for i, method := range service.GetMethod() { - m := &ProtoMethod{} - m.Index = i - m.Name = method.GetName() - m.PascalName = MakeFirstLowerCase(m.Name) - // m.InputStream = *method.ClientStreaming - // m.OutputStream = *method.ServerStreaming - input := removePackagePrefix(method.GetInputType(), file.GetPackage()) - output := removePackagePrefix(method.GetOutputType(), file.GetPackage()) - m.Input = messages[input] - m.Output = messages[output] - s.Methods = append(s.Methods, m) - } - } - return pkg -} - -func goPkgLastElement(full string) string { - pkgSplitted := strings.Split(full, "/") - return pkgSplitted[len(pkgSplitted)-1] -} - -// MakeFirstLowerCase makes the first character in a string lower case -func MakeFirstLowerCase(s string) string { - if len(s) < 2 { - return strings.ToLower(s) - } - - bts := []byte(s) - - lc := bytes.ToLower([]byte{bts[0]}) - rest := bts[1:] - - return string(bytes.Join([][]byte{lc, rest}, nil)) -} - -// cleanPackageName lifted from gogo generator -// https://github.com/gogo/protobuf/blob/master/protoc-gen-gogo/generator/generator.go#L695 -func cleanPackageName(name string) string { - parts := strings.Split(name, "/") - name = parts[len(parts)-1] - - name = strings.Map(badToUnderscore, name) - // Identifier must not be keyword: insert _. - if isGoKeyword[name] { - name = "_" + name - } - // Identifier must not begin with digit: insert _. - if r, _ := utf8.DecodeRuneInString(name); unicode.IsDigit(r) { - name = "_" + name - } - return name -} - -// badToUnderscore lifted from gogo generator -func badToUnderscore(r rune) rune { - if unicode.IsLetter(r) || unicode.IsDigit(r) || r == '_' { - return r - } - return '_' -} diff --git a/protobuf/protoc-gen-gograinv2/template.go b/protobuf/protoc-gen-gograinv2/template.go deleted file mode 100644 index b217bf1f8..000000000 --- a/protobuf/protoc-gen-gograinv2/template.go +++ /dev/null @@ -1,169 +0,0 @@ -package main - -const code = `{{ if .Services -}} -// Package {{.PackageName}} is generated by protoactor-go/protoc-gen-gograin@0.1.0 -package {{.PackageName}} - -import ( - "errors" - "fmt" - "log/slog" - "math" - "time" - - "github.com/asynkron/protoactor-go/actor" - "github.com/asynkron/protoactor-go/cluster" - "google.golang.org/protobuf/proto" -) - -var ( - _ = proto.Marshal - _ = fmt.Errorf - _ = math.Inf -) -{{ range $service := .Services }} -var x{{ $service.Name }}Factory func() {{ $service.Name }} - -// {{ $service.Name }}Factory produces a {{ $service.Name }} -func {{ $service.Name }}Factory(factory func() {{ $service.Name }}) { - x{{ $service.Name }}Factory = factory -} - -// Get{{ $service.Name }}GrainClient instantiates a new {{ $service.Name }}GrainClient with given Identity -func Get{{ $service.Name }}GrainClient(c *cluster.Cluster, id string) *{{ $service.Name }}GrainClient { - if c == nil { - panic(fmt.Errorf("nil cluster instance")) - } - if id == "" { - panic(fmt.Errorf("empty id")) - } - return &{{ $service.Name }}GrainClient{Identity: id, cluster: c} -} - -// Get{{ $service.Name }}Kind instantiates a new cluster.Kind for {{ $service.Name }} -func Get{{ $service.Name }}Kind(opts ...actor.PropsOption) *cluster.Kind { - props := actor.PropsFromProducer(func() actor.Actor { - return &{{ $service.Name }}Actor{ - Timeout: 60 * time.Second, - } - }, opts...) - kind := cluster.NewKind("{{ $service.Name }}", props) - return kind -} - -// Get{{ $service.Name }}Kind instantiates a new cluster.Kind for {{ $service.Name }} -func New{{ $service.Name }}Kind(factory func() {{ $service.Name }}, timeout time.Duration, opts ...actor.PropsOption) *cluster.Kind { - x{{ $service.Name }}Factory = factory - props := actor.PropsFromProducer(func() actor.Actor { - return &{{ $service.Name }}Actor{ - Timeout: timeout, - } - }, opts...) - kind := cluster.NewKind("{{ $service.Name }}", props) - return kind -} - -// {{ $service.Name }} interfaces the services available to the {{ $service.Name }} -type {{ $service.Name }} interface { - Init(ctx cluster.GrainContext) - Terminate(ctx cluster.GrainContext) - ReceiveDefault(ctx cluster.GrainContext) - {{- range $method := $service.Methods }} - {{ $method.Name }}(*{{ $method.Input.Name }}, cluster.GrainContext) (*{{ $method.Output.Name }}, error) - {{- end }} -} - -// {{ $service.Name }}GrainClient holds the base data for the {{ $service.Name }}Grain -type {{ $service.Name }}GrainClient struct { - Identity string - cluster *cluster.Cluster -} -{{ range $method := $service.Methods}} -// {{ $method.Name }} requests the execution on to the cluster with CallOptions -func (g *{{ $service.Name }}GrainClient) {{ $method.Name }}(r *{{ $method.Input.Name }}, opts ...cluster.GrainCallOption) (*{{ $method.Output.Name }}, error) { - bytes, err := proto.Marshal(r) - if err != nil { - return nil, err - } - reqMsg := &cluster.GrainRequest{MethodIndex: {{ $method.Index }}, MessageData: bytes} - resp, err := g.cluster.Request(g.Identity, "{{ $service.Name }}", reqMsg, opts...) - if err != nil { - return nil, err - } - switch msg := resp.(type) { - case *cluster.GrainResponse: - result := &{{ $method.Output.Name }}{} - err = proto.Unmarshal(msg.MessageData, result) - if err != nil { - return nil, err - } - return result, nil - case *cluster.GrainErrorResponse: - return nil, errors.New(msg.Err) - default: - return nil, errors.New("unknown response") - } -} -{{ end }} -// {{ $service.Name }}Actor represents the actor structure -type {{ $service.Name }}Actor struct { - ctx cluster.GrainContext - inner {{ $service.Name }} - Timeout time.Duration -} - -// Receive ensures the lifecycle of the actor for the received message -func (a *{{ $service.Name }}Actor) Receive(ctx actor.Context) { - switch msg := ctx.Message().(type) { - case *actor.Started: //pass - case *cluster.ClusterInit: - a.ctx = cluster.NewGrainContext(ctx, msg.Identity, msg.Cluster) - a.inner = x{{ $service.Name }}Factory() - a.inner.Init(a.ctx) - - if a.Timeout > 0 { - ctx.SetReceiveTimeout(a.Timeout) - } - case *actor.ReceiveTimeout: - ctx.Poison(ctx.Self()) - case *actor.Stopped: - a.inner.Terminate(a.ctx) - case actor.AutoReceiveMessage: // pass - case actor.SystemMessage: // pass - - case *cluster.GrainRequest: - switch msg.MethodIndex { - {{ range $method := $service.Methods -}} - case {{ $method.Index }}: - req := &{{ $method.Input.Name }}{} - err := proto.Unmarshal(msg.MessageData, req) - if err != nil { - ctx.Logger().Error("[Grain] {{ $method.Name }}({{ $method.Input.Name }}) proto.Unmarshal failed.", slog.Any("error", err)) - resp := &cluster.GrainErrorResponse{Err: err.Error()} - ctx.Respond(resp) - return - } - r0, err := a.inner.{{ $method.Name }}(req, a.ctx) - if err != nil { - resp := &cluster.GrainErrorResponse{Err: err.Error()} - ctx.Respond(resp) - return - } - bytes, err := proto.Marshal(r0) - if err != nil { - ctx.Logger().Error("[Grain] {{ $method.Name }}({{ $method.Input.Name }}) proto.Marshal failed", slog.Any("error", err)) - resp := &cluster.GrainErrorResponse{Err: err.Error()} - ctx.Respond(resp) - return - } - resp := &cluster.GrainResponse{MessageData: bytes} - ctx.Respond(resp) - {{ end -}} - } - default: - a.inner.ReceiveDefault(a.ctx) - } -} -{{ end -}} -{{ end -}} -`