Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

feat: Adds actor configuration to FSMBuilder #7

Merged

Conversation

PetrosPapapa
Copy link
Contributor

Extends FSMBuilder to expose additional custom options for the actor:

  1. preStart
  2. postStop
  3. onError (for debugging purposes)
  4. supervisorStrategy

Also:

  • Fixes the stop(reason: Reason) overload in the FSM state manager which defaulted to Normal instead of using the argument provided.
  • Rearranges FSMBuilder constructor to avoid default arguments in the case class.
  • Fixes missing onTerminationCallback in FSMBuilderSemigroupEvidence and extends it with new fields.

Example usage based on the example from the README:

object ExampleFSMApp extends IOApp {

  sealed trait Request
  case object Start extends Request
  case object Stop extends Request

  sealed trait State

  case object Idle extends State

  case object Active extends State

  case class Data(counter: Int)

  override def run(args: List[String]): IO[ExitCode] = {
    val fsm: IO[Actor[IO, Request]] = FSM[IO, State, Data, Request, Any]
      .withConfig(FSMConfig.withConsoleInformation[IO, State, Data, Request, Any])
      .when(Idle) { case (FSM.Event(Start, data), stateManager) =>
        for {
          newState <- stateManager.goto(Active)
        } yield newState.using(data.copy(counter = data.counter + 1))
      }
      .when(Active) { case (FSM.Event(Stop, data), stateManager) =>
        for {
          newState <- stateManager.goto(Idle)
        } yield newState.using(data.copy(counter = data.counter + 1))
      }
      .onTransition {
        case (Idle, Active) => IO.println("Transitioning from Idle to Active")
        case (Active, Idle) => IO.println("Transitioning from Active to Idle")
      }
      .withPreStart(IO.println("Custom pre-start!"))
      .withPostStop((IO.println("Custom post-stop!")))
      .startWith(Idle, Data(0), None)
      .initialize

    ActorSystem[IO]("example-fsm-system").use { system =>
      for {
        fsmActor <- system.actorOf[Request](fsm)
        _ <- fsmActor ! Start
        _ <- fsmActor ! Stop
        _ <- fsmActor ! Start
        _ <- fsmActor ! Stop
        _ <- fsmActor !* PoisonPill
        _ <- system.waitForTermination
      } yield ExitCode.Success
    }
  }
}

Output:

Custom pre-start!
[FSM] Transition ([CurrentState: Idle] -> [CurrentData: Data(0)]) ~> ([NextState: Idle] -> [NextData: Data(0)])
[FSM] Received [Event: Start] [Sender: None] [CurrentState: Idle] [CurrentData: Data(0)]
Transitioning from Idle to Active
[FSM] Transition ([CurrentState: Idle] -> [CurrentData: Data(0)]) ~> ([NextState: Active] -> [NextData: Data(1)])
[FSM] Received [Event: Stop] [Sender: None] [CurrentState: Active] [CurrentData: Data(1)]
Transitioning from Active to Idle
[FSM] Transition ([CurrentState: Active] -> [CurrentData: Data(1)]) ~> ([NextState: Idle] -> [NextData: Data(2)])
[FSM] Received [Event: Start] [Sender: None] [CurrentState: Idle] [CurrentData: Data(2)]
Transitioning from Idle to Active
[FSM] Transition ([CurrentState: Idle] -> [CurrentData: Data(2)]) ~> ([NextState: Active] -> [NextData: Data(3)])
[FSM] Received [Event: Stop] [Sender: None] [CurrentState: Active] [CurrentData: Data(3)]
Transitioning from Active to Idle
[FSM] Transition ([CurrentState: Active] -> [CurrentData: Data(3)]) ~> ([NextState: Idle] -> [NextData: Data(4)])
Custom post-stop!

@cloudmark
Copy link
Collaborator

Great work @PetrosPapapa , thanks for the contribution

@cloudmark cloudmark merged commit 315c14b into suprnation:main Aug 22, 2024
@PetrosPapapa PetrosPapapa deleted the feature/FSMBulder-config-actor branch August 22, 2024 16:12
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants