score:1

Accepted answer

In Akka Typed's functional API (which this example uses), the typical way to do this would be along these lines:

object TestActor {
  final case class Command()

  def apply(): Behavior[Command] =
    fromMap(mutable.Map.empty)

  private def fromMap(mmap: mutable.Map[Int, Map[Int, Int]]): Behavior[Command] =
    Behaviors.receive {
      case (context, Command()) =>
        mmap += (1 -> Map(2 -> 3))
        context.log.info(mmap)
        Behaviors.same
    }
}

Here, the object is basically serving as just a module and the fields of that object are better thought of as globals.

Note that there is also an object-oriented API for defining typed actors, which in Scala would be:

object TestActor {
  final case class Command()

  def apply(): Behavior[TestActor.Command] =
    Behaviors.setup { context =>
      new TestActor(context)
    }
}

class TestActor(context: ActorContext[TestActor.Command]) extends AbstractBehavior[TestActor.Command](context) {
  val mmap: mutable.Map[Int, Map[Int, Int]] = mutable.Map.empty

  def onMessage(msg: TestActor.Command): Behavior[TestActor.Command] = {
    mmap += (1 -> Map(2, 3))
    context.log.info(mmap)
    this
  }
}

It's worth noting that in Akka, it's generally better to have vars of immutable data (i.e. mutable containers holding immutable values) than vals of mutable data (i.e. immutable containers holding mutable values), as that can expose a channel for something outside the actor (including another actor) to "pull the rug out from under" an actor.

In the functional API, this would typically take a form like:

object TestActor {
  final case class Command()

  def apply(): Behavior[Command] =
    fromMap(Map.empty)

  private def fromMap(map: Map[Int, Map[Int, Int]]): Behavior[Command] =
    Behaviors.receive {
      case (context, Command()) =>
        val nextMap = map + (1 -> Map(2 -> 3))
        context.log.info(nextMap)
        withMap(nextMap)
    }
}

And in the OO Scala API:

// TestActor companion object is as before

class TestActor(context: ActorContext[TestActor.Command]) extends AbstractBehavior[TestActor.Command](context) {
  var map: Map[Int, Map[Int, Int]] = Map.empty

  def onMessage(msg: TestActor.Command): Behavior[TestActor.Command] = {
    map = map + (1 -> Map(2 -> 3))
    context.log.info(map)
    this
  }
}

Related Query