Fix actors added during initialization process being run twice

Also broke out the emergency halt process into a new function,
which is also now ALWAYS called 16 minutes after sigint has been
pressed, regardless if the shutdown even began in the first place.
This commit is contained in:
2025-11-26 11:46:53 -05:00
parent 5d25b3fb9a
commit a58b5932e7
3 changed files with 81 additions and 29 deletions
+26 -17
View File
@@ -35,6 +35,8 @@ type actorInfo struct {
// incremented automatically for each actor that is added. It is never
// less than one.
order int
// initial is true if this actor was added as an argument to [Run].
initial bool
}
// actorSetIface holds only the add/del/clear methods of actorSet.
@@ -60,23 +62,12 @@ func (sets *actorSets) All() iter.Seq[actorSetIface] {
// add adds an actor under the given parent context. This is a write operation.
func (this *actorSets) add(ctx context.Context, actor Actor) {
if this.inf == nil { this.inf = make(map[Actor] actorInfo)}
actorCtx, done := context.WithCancel(ctx)
this.nextOrder ++
info := actorInfo {
ctx: actorCtx,
done: done,
order: this.nextOrder,
}
_, isRunnable := actor.(Runnable)
_, isRunShutdownable := actor.(RunShutdownable)
if isRunnable || isRunShutdownable {
info.stopped = make(chan struct { })
}
this.inf[actor] = info
for set := range this.All() {
set.add(actor)
}
this.addInternal(actorInfo { }, ctx, actor)
}
// addInitial is like add, but marks the actor as initial. This is a write operation.
func (this *actorSets) addInitial(ctx context.Context, actor Actor) {
this.addInternal(actorInfo { initial: true }, ctx, actor)
}
// del removes an actor. This is a write operation.
@@ -101,6 +92,24 @@ func (this *actorSets) info(actor Actor) actorInfo {
return this.inf[actor]
}
func (this *actorSets) addInternal(inf actorInfo, ctx context.Context, actor Actor) {
if this.inf == nil { this.inf = make(map[Actor] actorInfo)}
actorCtx, done := context.WithCancel(ctx)
this.nextOrder ++
inf.ctx = actorCtx
inf.done = done
inf.order = this.nextOrder
_, isRunnable := actor.(Runnable)
_, isRunShutdownable := actor.(RunShutdownable)
if isRunnable || isRunShutdownable {
inf.stopped = make(chan struct { })
}
this.inf[actor] = inf
for set := range this.All() {
set.add(actor)
}
}
// sortActors sorts actors according to the order in which they were added.
func sortActors[T comparable] (sets *actorSets, actors []T) []T {
slices.SortFunc(actors, func (left, right T) int {