Fixed a critical mistake

Erroneously used functional actor for mutable state.
Changed actor style to OO from functional.
Experimented with ask pattern to get final result
This commit is contained in:
Rohan Sircar 2020-08-19 13:17:23 +05:30
parent 260aa0fdc4
commit 1abc30070c
3 changed files with 45 additions and 28 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
.ammonite
.metals

View File

@ -13,35 +13,47 @@ import akka.util.Timeout
import scala.concurrent.duration._ import scala.concurrent.duration._
import akka.actor.typed.scaladsl.AskPattern._ import akka.actor.typed.scaladsl.AskPattern._
import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.ExecutionContext.Implicits.global
import akka.actor.typed.scaladsl.AbstractBehavior
import akka.actor.typed.scaladsl.ActorContext
import scala.util.Success
import scala.util.Failure
import scala.concurrent.Await
import scala.concurrent.Future
object CounterActor { object CounterActor {
final case class CounterResult(count: Int)
sealed trait Command sealed trait Command
final case object IncCount extends Command final case object IncCount extends Command
final case class CounterResult(count: Int) final case class GetResult(sender: ActorRef[CounterResult]) extends Command
final case class GetResult(sender: ActorRef[RootActor.Command])
extends Command
var counter = 0
def apply(): Behavior[Command] = def apply(): Behavior[Command] =
Behaviors.receive { (context, command) => Behaviors.setup(ctx => new CounterActor(ctx))
command match {
case IncCount => counter += 1 private class CounterActor(context: ActorContext[Command])
extends AbstractBehavior[Command](context) {
private var counter = 0 // encapsulated mutable state
override def onMessage(msg: Command): Behavior[Command] = {
msg match {
case IncCount =>
counter += 1
Behaviors.same
case GetResult(sender) => case GetResult(sender) =>
context.log.info(s"Value of counter is $counter"); context.log.info(s"Value of counter is $counter");
sender ! RootActor.Reply(counter) sender ! CounterResult(counter)
Behaviors.same
} }
Behaviors.same
} }
}
} }
object RootActor { object RootActor {
sealed trait Command sealed trait Command
case class Reply[T](reply: T) extends Command final case class Reply[T](reply: T) extends Command
case object Begin extends Command final case object Begin extends Command
case object GetResult extends Command final case class GetResult(repyTo: ActorRef[CounterActor.CounterResult])
extends Command
implicit val timeout: Timeout = 3.seconds implicit val timeout: Timeout = 3.seconds
@ -63,10 +75,11 @@ object RootActor {
counterActor ! CounterActor.IncCount counterActor ! CounterActor.IncCount
counterActor ! CounterActor.IncCount counterActor ! CounterActor.IncCount
case GetResult => case GetResult(replyTo) =>
counterActor ! CounterActor.GetResult( counterActor ! CounterActor.GetResult(
context.self replyTo
) )
} }
Behaviors.same Behaviors.same
@ -77,13 +90,15 @@ object RootActor {
@main @main
def main() = { def main() = {
implicit val rootActor = implicit val system =
ActorSystem(RootActor(), "TestActors") ActorSystem(RootActor(), "TestActors")
implicit val timeout: Timeout = 3.seconds implicit val timeout: Timeout = 3.seconds
rootActor ! RootActor.Begin system ! RootActor.Begin
rootActor ! RootActor.GetResult // system ! RootActor.GetResult
Thread.sleep(1000) val x: Future[CounterActor.CounterResult] =
system ? (ref => RootActor.GetResult(ref))
Await.result(x, 1.second)
} }

View File

@ -3,15 +3,15 @@
An experiment to see how the actor model can be used to synchronize / encapsulate mutable state without the use of locks. An experiment to see how the actor model can be used to synchronize / encapsulate mutable state without the use of locks.
## Usage ## Usage
``` bash
```bash
./ActorsDemo.sc ./ActorsDemo.sc
``` ```
Sample output: Sample output:
```
22:11:47.473 [TestActors-akka.actor.default-dispatcher-3] INFO ammonite.$file.ActorDemo$RootActor$ - --- Beginning ---
22:11:47.475 [TestActors-akka.actor.default-dispatcher-6] INFO ammonite.$file.ActorDemo$CounterActor$ - Value of counter is 5 ```
13:02:58.966 [TestActors-akka.actor.default-dispatcher-3] INFO ammonite.$file.AkkaActorsDemo.ActorDemo$RootActor$ - --- Beginning ---
22:11:47.475 [TestActors-akka.actor.default-dispatcher-3] INFO ammonite.$file.ActorDemo$RootActor$ - Received message Reply(5) 13:02:58.967 [TestActors-akka.actor.default-dispatcher-5] INFO ammonite.$file.AkkaActorsDemo.ActorDemo$CounterActor$CounterActor - Value of counter is 5
CounterResult(5)
``` ```