Open DustOak opened 2 months ago
I would rather wrap all that in a helper function that handles all of this. e.g. if your code fails to initialize, set some state of the actor to failed. then add a message request+response where you can query that state.
func NewSomeActor() {
props := actor.PropsFromProducer(......)
pid := system.Root.Spawn(props)
res := system.Root.RequestFuture(pid, &SomeRequest {}).Result
if res == .... {
//actor started successfully
}
else {
//actor failed to initialize
}
}
Or if possible, you could do it even before proto.actor is involved at all. You can set state in the actor upon producing it.
func() actor.Actor { return &helloActor{
.....set state here
} }
you could create a function that resolves all deps and returns a Props if successful, or err if failed. That way, you could catch this error before the actor is spawned.
我宁愿将所有这些包装在一个处理所有这些的帮助程序函数中。例如,如果您的代码无法初始化,请将 actor 的某些状态设置为 failed。然后添加消息 request+response,您可以在其中查询该状态。
func NewSomeActor() { props := actor.PropsFromProducer(......) pid := system.Root.Spawn(props) res := system.Root.RequestFuture(pid, &SomeRequest {}).Result if res == .... { //actor started successfully } else { //actor failed to initialize } }
或者,如果可能的话,你甚至可以在 proto.actor 参与之前就这样做。您可以在生成 actor 时在 actor 中设置状态。
func() actor.Actor { return &helloActor{ .....set state here } }
您可以创建一个函数来解析所有 deps,如果成功,则返回 Props,如果失败,则返回 err。这样,您就可以在生成 actor 之前捕获此错误。
I have considered and tried the first method, but I am unable to determine how long the timeout for synchronous requests should be set. If the time is too long, it may affect the overall performance.
新一期参
For the second approach, I might need to do some things using actor.Context during initialization, so it may not work as well.
Currently, I am not sure if there will be any issues with the way I am doing it. The code is as follows:
func makeHook(factory BehaviorFactory, args ...any) actor.SpawnFunc {
return func(actorSystem *actor.ActorSystem, id string, props *actor.Props, parentContext actor.SpawnerContext) (pid *actor.PID, err error) {
hook := &hook{Behavior: factory(args...), Actor: makeActor(), factory: factory, args: args}
wait := make(chan error)
defer close(wait)
fun := func(ctx actor.Context) {
hook.update(ctx)
hook.Errorf("--------------------------------> %s", ctx.Parent())
hook.Do(func() {
if err := hook.Init(hook); err != nil {
hook.Debugf("behavior init failed: %s", err)
hook.Exit()
wait <- err
return
}
hook.Debugf("behavior init ok.")
wait <- nil
})
hook.Receive(ctx)
}
props = actor.PropsFromFunc(fun, actor.WithSupervisor(actor.DefaultSupervisorStrategy()))
if pid, err = actor.DefaultSpawner(actorSystem, id, props, parentContext); err != nil {
return nil, err
}
err = <-wait
return
}
}
func Spawn(alias Alias, factory BehaviorFactory, args ...any) (pid Pid, err error) {
props := (&actor.Props{}).Configure(actor.WithSpawnFunc(makeHook(factory, args...)))
if pid, err = root.ActorSystem.Root.SpawnNamed(props, string(alias)); err != nil {
return
}
root.Children = append(root.Children, pid)
return
}
When I spawn an actor, if I need to initialize the actor upon receiving 'Started', and if initialization fails, the actor should not start successfully. How should I write this code? I noticed that after I receive 'Started', the spawn has already returned the Pid. However, I do not want this because I need the actor to stop when initialization fails and have the spawn return an error