Skip to content

bug: PostStop runs multiple times #788

Closed
@mattjohnsonpint

Description

@mattjohnsonpint

Bug description
The PostStop function is being executed an indeterminate number of times.

How to reproduce it?
Run the following code a few times:

Reproduction Code (click to expand)
package main

import (
	"context"
	"fmt"
	"os"

	"github.com/tochemey/goakt/v3/actor"
	"github.com/tochemey/goakt/v3/goaktpb"
)

const numActors = 1

func main() {
	ctx := context.Background()
	actorSystem := startActorSystem(ctx)

	for i := range numActors {
		spawnActor(ctx, actorSystem, fmt.Sprintf("actor%d", i+1))
	}

	stopActorSystem(ctx, actorSystem)
}

func startActorSystem(ctx context.Context) actor.ActorSystem {
	actorSystem, err := actor.NewActorSystem("test-system")
	if err != nil {
		fmt.Printf("Error creating actor system: %v\n", err)
		os.Exit(1)
	}
	if err := actorSystem.Start(ctx); err != nil {
		fmt.Printf("Error starting actor system: %v\n", err)
		os.Exit(1)
	}
	return actorSystem
}

func stopActorSystem(ctx context.Context, actorSystem actor.ActorSystem) {
	if err := actorSystem.Stop(ctx); err != nil {
		fmt.Printf("Error stopping actor system: %v\n", err)
		os.Exit(1)
	}
}

func spawnActor(ctx context.Context, actorSystem actor.ActorSystem, actorName string) {
	if _, err := actorSystem.Spawn(ctx, actorName, &MyActor{}); err != nil {
		fmt.Printf("Error spawning actor %s: %v\n", actorName, err)
		os.Exit(1)
	}
}

type MyActor struct{}

func (x *MyActor) PreStart(ctx *actor.Context) error {
	fmt.Printf("%s PreStart\n", ctx.ActorName())
	return nil
}

func (x *MyActor) Receive(ctx *actor.ReceiveContext) {
	switch ctx.Message().(type) {
	case *goaktpb.PostStart:
		fmt.Printf("%s PostStart\n", ctx.Self().Name())
	default:
		ctx.Unhandled()
	}
}

func (x *MyActor) PostStop(ctx *actor.Context) error {
	fmt.Printf("%s PostStop\n", ctx.ActorName())
	return nil
}

With numActors = 1, sometimes you will see actor1 PostStop once, but sometimes you will see it twice.

With a larger number of actors, it's more evident. For example, with numActors = 5, in one attempt I got:

actor1 PreStart
actor2 PreStart
actor1 PostStart
actor2 PostStart
actor3 PreStart
actor3 PostStart
actor4 PreStart
actor4 PostStart
actor5 PreStart
actor5 PostStart
actor1 PostStop
actor1 PostStop
actor5 PostStop
actor3 PostStop
actor4 PostStop
actor2 PostStop
actor4 PostStop

Adding some time.Sleep delays did not seem to help, but I would hope I wouldn't need them anyway.

Expected behavior
I expect PostStop to run once and only once for each actor.

Library Version:

  • Go-Akt version: v3.6.3
  • Go version: 1.24.4

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions