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  }