github.com/asynkron/protoactor-go@v0.0.0-20240308120642-ef91a6abee75/actor/guardian.go (about) 1 package actor 2 3 import ( 4 "errors" 5 "log/slog" 6 "sync" 7 ) 8 9 type guardiansValue struct { 10 actorSystem *ActorSystem 11 guardians *sync.Map 12 } 13 14 func NewGuardians(actorSystem *ActorSystem) *guardiansValue { 15 return &guardiansValue{ 16 actorSystem: actorSystem, 17 guardians: &sync.Map{}, 18 } 19 } 20 21 func (gs *guardiansValue) getGuardianPid(s SupervisorStrategy) *PID { 22 if g, ok := gs.guardians.Load(s); ok { 23 return g.(*guardianProcess).pid 24 } 25 g := gs.newGuardian(s) 26 gs.guardians.Store(s, g) 27 return g.pid 28 } 29 30 // newGuardian creates and returns a new actor.guardianProcess with a timeout of duration d 31 func (gs *guardiansValue) newGuardian(s SupervisorStrategy) *guardianProcess { 32 ref := &guardianProcess{ 33 strategy: s, 34 guardians: gs, 35 } 36 id := gs.actorSystem.ProcessRegistry.NextId() 37 38 pid, ok := gs.actorSystem.ProcessRegistry.Add(ref, "guardian"+id) 39 if !ok { 40 gs.actorSystem.Logger().Error("failed to register guardian process", slog.Any("pid", pid)) 41 } 42 43 ref.pid = pid 44 return ref 45 } 46 47 type guardianProcess struct { 48 guardians *guardiansValue 49 pid *PID 50 strategy SupervisorStrategy 51 } 52 53 var _ Process = &guardianProcess{} 54 55 func (g *guardianProcess) SendUserMessage(_ *PID, _ interface{}) { 56 panic(errors.New("guardian actor cannot receive any user messages")) 57 } 58 59 func (g *guardianProcess) SendSystemMessage(_ *PID, message interface{}) { 60 if msg, ok := message.(*Failure); ok { 61 g.strategy.HandleFailure(g.guardians.actorSystem, g, msg.Who, msg.RestartStats, msg.Reason, msg.Message) 62 } 63 } 64 65 func (g *guardianProcess) Stop(_ *PID) { 66 // Ignore 67 } 68 69 func (g *guardianProcess) Children() []*PID { 70 panic(errors.New("guardian does not hold its children PIDs")) 71 } 72 73 func (g *guardianProcess) EscalateFailure(_ interface{}, _ interface{}) { 74 panic(errors.New("guardian cannot escalate failure")) 75 } 76 77 func (g *guardianProcess) RestartChildren(pids ...*PID) { 78 for _, pid := range pids { 79 pid.sendSystemMessage(g.guardians.actorSystem, restartMessage) 80 } 81 } 82 83 func (g *guardianProcess) StopChildren(pids ...*PID) { 84 for _, pid := range pids { 85 pid.sendSystemMessage(g.guardians.actorSystem, stopMessage) 86 } 87 } 88 89 func (g *guardianProcess) ResumeChildren(pids ...*PID) { 90 for _, pid := range pids { 91 pid.sendSystemMessage(g.guardians.actorSystem, resumeMailboxMessage) 92 } 93 }