diff --git a/_examples/actor-autorespond/go.mod b/_examples/actor-autorespond/go.mod new file mode 100644 index 000000000..c2c76ea22 --- /dev/null +++ b/_examples/actor-autorespond/go.mod @@ -0,0 +1,9 @@ +module autorespond + +go 1.16 + +replace github.com/asynkron/protoactor-go => ../.. + +require ( + github.com/asynkron/protoactor-go v0.0.0-00010101000000-000000000000 +) diff --git a/_examples/actor-autorespond/main.go b/_examples/actor-autorespond/main.go new file mode 100644 index 000000000..9f1aa6429 --- /dev/null +++ b/_examples/actor-autorespond/main.go @@ -0,0 +1,43 @@ +package main + +import ( + "fmt" + "github.com/asynkron/protoactor-go/actor" + "time" +) + +//Auto Response in Proto.Actor is a special kind of message that can create its own response message +//it is received just like any other message by the actor +//but the actor context sees the AutoResponse interface and calls GetAutoReplyMessage() to get the response message +//this is useful if you want to guarantee some form of Ack from an actor. without forcing the developer of the actor to +//use context.Respond manually + +//e.g. ClusterPubSub feature uses this to Ack back to the Topic actor to let it know the message has been received + +type myAutoResponder struct { + name string +} + +func (m myAutoResponder) GetAutoResponse(context actor.Context) interface{} { + + //return some response-message + //you have full access to the actor context + + return &myAutoResponse{ + name: m.name + " " + context.Self().Id, + } +} + +type myAutoResponse struct { + name string +} + +func main() { + system := actor.NewActorSystem() + props := actor.PropsFromFunc(func(ctx actor.Context) {}) + pid := system.Root.Spawn(props) + + res, _ := system.Root.RequestFuture(pid, &myAutoResponder{name: "hello"}, 10*time.Second).Result() + + fmt.Printf("%v", res) +} diff --git a/_examples/actor-messagebatch/go.mod b/_examples/actor-messagebatch/go.mod new file mode 100644 index 000000000..aaad01788 --- /dev/null +++ b/_examples/actor-messagebatch/go.mod @@ -0,0 +1,10 @@ +module messagebatch + +go 1.16 + +replace github.com/asynkron/protoactor-go => ../.. + +require ( + github.com/asynkron/goconsole v0.0.0-20160504192649-bfa12eebf716 + github.com/asynkron/protoactor-go v0.0.0-00010101000000-000000000000 +) diff --git a/_examples/actor-messagebatch/main.go b/_examples/actor-messagebatch/main.go new file mode 100644 index 000000000..c44be2319 --- /dev/null +++ b/_examples/actor-messagebatch/main.go @@ -0,0 +1,45 @@ +package main + +import ( + "fmt" + console "github.com/asynkron/goconsole" + "github.com/asynkron/protoactor-go/actor" + "strconv" +) + +// MessageBatch is a message that is sent to the actor and unpacks its payload in the mailbox +// This allows you to group messages together and send them as a single message +// while processing them as individual messages +// this is used by the Cluster PubSub feature to send a batch of messages and then Ack to the entire batch +// In that specific case, both MessageBatch and AutoRespond are required + +type myMessageBatch struct { + messages []interface{} +} + +func (m myMessageBatch) GetMessages() []interface{} { + return m.messages +} + +func main() { + system := actor.NewActorSystem() + props := actor.PropsFromFunc(func(ctx actor.Context) { + if m, ok := ctx.Message().(string); ok { + fmt.Println(m) + } + }) + pid := system.Root.Spawn(props) + + messages := make([]interface{}, 0) + + for i := 0; i < 100; i++ { + messages = append(messages, "Hello"+strconv.Itoa(i)) + } + + batch := &myMessageBatch{ + messages: messages, + } + system.Root.Send(pid, batch) + + console.ReadLine() +} diff --git a/actor/root_context.go b/actor/root_context.go index 4a8acd137..f0c356afa 100644 --- a/actor/root_context.go +++ b/actor/root_context.go @@ -124,6 +124,7 @@ func (rc *RootContext) RequestFuture(pid *PID, message interface{}, timeout time Sender: future.PID(), } rc.sendUserMessage(pid, env) + return future } @@ -147,6 +148,7 @@ func (rc *RootContext) Spawn(props *Props) *PID { if err != nil { panic(err) } + return pid } @@ -156,6 +158,7 @@ func (rc *RootContext) SpawnPrefix(props *Props, prefix string) *PID { if err != nil { panic(err) } + return pid } @@ -169,9 +172,11 @@ func (rc *RootContext) SpawnNamed(props *Props, name string) (*PID, error) { if props.guardianStrategy != nil { rootContext = rc.Copy().WithGuardian(props.guardianStrategy) } + if rootContext.spawnMiddleware != nil { return rc.spawnMiddleware(rc.actorSystem, name, props, rootContext) } + return props.spawn(rc.actorSystem, name, rootContext) }