Skip to content

Commit

Permalink
Cleaned up Demos
Browse files Browse the repository at this point in the history
  • Loading branch information
devlaam committed May 23, 2023
1 parent fb27534 commit 5ee6d1f
Show file tree
Hide file tree
Showing 11 changed files with 39 additions and 36 deletions.
11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,14 @@ Leucine is typed actor system, with the following properties:
* It runs on JVM, JS and Native, and isolates you from their differences in treading implementation.

### Getting started
The four actor base types you can choose from are:
* `AcceptActor`: Accepts letters from all other actors in the system
* `SelectActor`: Accepts letters only from a selected list of actors (enforced at compile time)
* `RestrictActor`: Accepts letters only from a selected list of actors where per letter the sender actor may be restricted (enforced at compile time)
The five actor base types you can choose from are:
* `WideActor`: Accepts all letters from all other actors in the system
* `AcceptActor`: Accepts your letters from all other actors in the system
* `SelectActor`: Accepts your letters from a selected list of actors only
* `RestrictActor`: Accepts your letters from a selected list of actors where per letter the sender actor may be restricted
* `RefuseActor`: Accepts no letters (use to offload work on an other thread)
All restrictions are enforced at compile time. The `WideActor` is comparable to a 'non typed' actor and is
mainly for making the transition from an other actor framework to Leucine easier.

In a simple application it could look something like this:
```Scala
Expand Down
8 changes: 4 additions & 4 deletions shared/src/main/scala/s2a/leucine/demo/chat/access.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ class Access extends RestrictActor(Access,"Access") :
println("Access Actor Started.")

/* Currently registered users. */
var store: Map[String,String] = Map.empty
private var store: Map[String,String] = Map.empty

/* See if a user is present in the store, and if so the password is valid. */
def checkUser(name: String, password: String): Boolean = store.get(name).map(_ == password).getOrElse(false)
private def checkUser(name: String, password: String): Boolean = store.get(name).map(_ == password).getOrElse(false)

/* Receive method that handles the incoming requests. */
def receive[Sender <: Accept](letter: Letter[Sender], sender: Sender): Unit = (letter,sender) match
final protected def receive[Sender <: Accept](letter: Letter[Sender], sender: Sender): Unit = (letter,sender) match
/* If the pair message comes from the Register actor, we store it as a new/updated user */
case (Access.Pair(name,password),source: Register) => store += name -> password
/* If the pair message comes from the Text Actor we must verify if the user has the correct credentials */
Expand All @@ -53,7 +53,7 @@ object Access extends RestrictDefine, Stateless :
/* We only accept letters from the Register or Text actors. */
type Accept = Register | Text

/* Logger.Letter is the base type for all letters: */
/* Letter is the base type for all letters: */
sealed trait Letter[Sender <: Accept] extends Actor.Letter[Sender]

/* A letter to send name and password to me. */
Expand Down
8 changes: 4 additions & 4 deletions shared/src/main/scala/s2a/leucine/demo/chat/chartgrt.scala
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,16 @@ object Chatgrt :
given Actor.Anonymous = Actor.Anonymous

/* Service that generates a random character words. */
val noise = new Noise
private val noise = new Noise

/* Service that keeps a list of the approved accounts. */
val access = new Access
private val access = new Access

/* Service that keeps a list of new passwords to be handed out. */
val register = new Register(access,noise)
private val register = new Register(access,noise)

/* Service that constructs random texts. */
val text = new Text(access,noise)
private val text = new Text(access,noise)

/* Stop this demo */
def stop(): Unit =
Expand Down
6 changes: 3 additions & 3 deletions shared/src/main/scala/s2a/leucine/demo/chat/noise.scala
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ class Noise extends RestrictActor(Noise,"Noise") :
println("Noise Actor Started.")

/* Constructs a string with 'length' random chars. */
def make(length: Int): String = Random.alphanumeric.take(length).mkString
private def make(length: Int): String = Random.alphanumeric.take(length).mkString

/* Receive method that handles the incoming requests. */
def receive[Sender <: Accept](letter: Letter[Sender], sender: Sender): Unit = (letter,sender) match
final protected def receive[Sender <: Accept](letter: Letter[Sender], sender: Sender): Unit = (letter,sender) match
/* Return a sequence of size random strings each of the same length. */
case (Noise.Request(_,size,length), source: Register) =>
val result = List.fill(size)(make(length))
Expand All @@ -55,7 +55,7 @@ object Noise extends RestrictDefine, Stateless :
/* Only the Access and Text actors may request for random content. */
type Accept = Register | Text

/* Noise.Letter is the base type for all letters: */
/* Letter is the base type for all letters: */
sealed trait Letter[Sender <: Accept] extends Actor.Letter[Sender]

/* Letter that requests for size new random char strings. */
Expand Down
6 changes: 3 additions & 3 deletions shared/src/main/scala/s2a/leucine/demo/chat/register.scala
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ class Register(access: Access, noise: Noise) extends RestrictActor(Register,"Reg
println("Register Actor Started.")

/* Supply of new passwords */
var supply: List[String] = Nil
private var supply: List[String] = Nil

/* Receive method that handles the incoming requests. */
def receive[Sender <: Accept](letter: Letter[Sender], sender: Sender): Unit = (letter,sender) match
final protected def receive[Sender <: Accept](letter: Letter[Sender], sender: Sender): Unit = (letter,sender) match
/* In case new passwords arrive, store them in the supply */
case (Register.Passwords(values),source: Noise) => supply = values
/* A request for new passwords is made. */
Expand Down Expand Up @@ -69,7 +69,7 @@ object Register extends RestrictDefine, Stateless :
/* We only accept letters from the Noise actor or from an anonymous source. */
type Accept = Noise | Anonymous

/* Logger.Letter is the base type for all letters: */
/* Letter is the base type for all letters: */
sealed trait Letter[Sender <: Accept] extends Actor.Letter[Sender]

/* Letter that contains new passwords. */
Expand Down
6 changes: 3 additions & 3 deletions shared/src/main/scala/s2a/leucine/demo/chat/text.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class Text(access: Access, noise: Noise) extends RestrictActor(Text,"Text") :
println("Text Actor Started.")

/* Receive method that handles the incoming requests. */
def receive[Sender <: Accept](letter: Letter[Sender], sender: Sender): Unit = (letter,sender) match
final protected def receive[Sender <: Accept](letter: Letter[Sender], sender: Sender): Unit = (letter,sender) match
/* If we receive this letter from an anonymous source, we interpret it as a request for a new password. */
case (Text.Lipsum(name,password),source: Anonymous) => access ! Access.Pair(name,password)
/* If we receive this letter from the Noise actor, we interpret it as random text */
Expand All @@ -43,12 +43,12 @@ class Text(access: Access, noise: Noise) extends RestrictActor(Text,"Text") :


/** Companion object where letters and accepted sender actors are defined. We keep no state. */
object Text extends RestrictDefine, Stateless :
object Text extends RestrictDefine, Stateless :

/* We only accept letters from the Noise or Access actors or from an anonymous source. */
type Accept = Access | Noise | Anonymous

/* Logger.Letter is the base type for all letters: */
/* Letter is the base type for all letters: */
sealed trait Letter[Sender <: Accept] extends Actor.Letter[Sender]

/* Letter that contains information about the user, content is sender related. */
Expand Down
14 changes: 7 additions & 7 deletions shared/src/main/scala/s2a/leucine/demo/clock/listener.scala
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,13 @@ import s2a.leucine.actors.*
class Listener extends SelectActor(Listener,"server"), TimingAid, FamilyRoot, LogInfo :

/* Time this demo will last. */
val runtime = 60.seconds
private val runtime = 60.seconds

println(s"Listener Constructed, will run for $runtime.")

/* We use different timer methods, which need different anchors so they do not overwrite each other. */
val terminationAnchor = new Object
val expectationAnchor = new Object
private val terminationAnchor = new Object
private val expectationAnchor = new Object

/* Make sure this server ends after 60 seconds. It is just for testing. */
post(Listener.Terminated,runtime,terminationAnchor)
Expand All @@ -63,7 +63,7 @@ class Listener extends SelectActor(Listener,"server"), TimingAid, FamilyRoot, Lo

/* See if there anyone knocking on the door. We need this if there is no callback
* function on the platform available. */
def connect: Option[Listener.Letter] =
private def connect: Option[Listener.Letter] =
/* Test if we have a request for a connection. */
serverSocket.request()
/* This may result in an error, if ... */
Expand Down Expand Up @@ -95,7 +95,7 @@ class Listener extends SelectActor(Listener,"server"), TimingAid, FamilyRoot, Lo


/* Handle all incoming letters. */
protected def receive(letter: Letter, sender: Sender): Unit = letter match
final protected def receive(letter: Letter, sender: Sender): Unit = letter match
/* The new connection will come in as a letter. */
case Listener.Connect(socket) =>
Logger.info("Accepted a connection.")
Expand All @@ -112,10 +112,10 @@ class Listener extends SelectActor(Listener,"server"), TimingAid, FamilyRoot, Lo
/* Stop the actor. */
stop(Actor.Stop.Direct)

protected override def except(letter: Listener.Letter, sender: Sender, cause: Exception, size: Int): Unit =
final protected override def except(letter: Listener.Letter, sender: Sender, cause: Exception, size: Int): Unit =
Logger.warn(s"Exception Occurred: ${cause.getMessage()}")

override def stopped(cause: Actor.Stop, complete: Boolean) =
final protected override def stopped(cause: Actor.Stop, complete: Boolean) =
println("Listener stopped")
/* Decently close this socket. */
serverSocket.close()
Expand Down
4 changes: 2 additions & 2 deletions shared/src/main/scala/s2a/leucine/demo/clock/provider.scala
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class Provider(protected val socket: ClientSocket, protected val parent: Listene
post(Provider.Send,2.seconds)

/* Handle the messages, which is only the posted letter in this case. */
def receive(letter: Letter, sender: Sender): Unit = letter match
final protected def receive(letter: Letter, sender: Sender): Unit = letter match
case Provider.Send =>
val datetime = new Date().toString
val message = s"Provider $path says: $datetime"
Expand All @@ -57,7 +57,7 @@ class Provider(protected val socket: ClientSocket, protected val parent: Listene
post(Provider.Send,2.seconds)

/* If this actor is stopped, we must close the connection. */
override def stopped(cause: Actor.Stop, complete: Boolean) =
final protected override def stopped(cause: Actor.Stop, complete: Boolean) =
println(s"Provider $path stopped.")
socket.close()

Expand Down
4 changes: 2 additions & 2 deletions shared/src/main/scala/s2a/leucine/demo/log/logger.scala
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,13 @@ private class Logger extends AcceptActor(Logger,"logger") :
private var level: Level = Level.Debug

/* Report that this logger has been disabled. */
override protected def stopped(cause: Actor.Stop, complete: Boolean) = println("Stopped Logger")
final protected override def stopped(cause: Actor.Stop, complete: Boolean) = println("Stopped Logger")

/* Report that this logger has started. */
println("Started Logger")

/* receive method that handles the incoming logger and control messages. */
def receive(letter: Letter): Unit = letter match
final protected def receive(letter: Letter): Unit = letter match
case msg: Message => if msg.level <= this.level then println(msg.show)
case Switch(level: Level) => this.level = level
case Stop => stop(Actor.Stop.Direct)
Expand Down
4 changes: 2 additions & 2 deletions shared/src/main/scala/s2a/leucine/demo/log/ticker.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import s2a.leucine.actors.*
class Ticker extends AcceptActor(Ticker), LogInfo :

/* We just log the fact that this actor stops. */
override protected def stopped(cause: Actor.Stop, complete: Boolean) = Logger.error(s"stopped ticker, complete=$complete")
final protected override def stopped(cause: Actor.Stop, complete: Boolean) = Logger.error(s"stopped ticker, complete=$complete")

/* In order to set the machinery in motion, a first tick must be send. */
this ! Ticker.Work
Expand All @@ -41,7 +41,7 @@ class Ticker extends AcceptActor(Ticker), LogInfo :
Logger.warn("Ticker Actor created")

/* In receive we handle the incoming letters. */
def receive(letter: Letter): (State => State) = (state: State) => {
final protected def receive(letter: Letter): (State => State) = (state: State) => {
/* In this example, we do not care about the letters that much, but more
* about the state. */
state match
Expand Down
4 changes: 2 additions & 2 deletions shared/src/main/scala/s2a/leucine/demo/trace/tree.scala
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class Tree(name: String, val parent: Option[Tree]) extends AcceptActor(Tree,name
private def write(kind: String) = println(s"$kind $path")

/* Show when the actor stops. */
override protected def stopped(cause: Actor.Stop, complete: Boolean) =
final protected override def stopped(cause: Actor.Stop, complete: Boolean) =
/* This is written for all actors. */
write(s"stop:$cause")
/* This is executed when the root actor stops, which is at the end. */
Expand All @@ -61,7 +61,7 @@ class Tree(name: String, val parent: Option[Tree]) extends AcceptActor(Tree,name
stop(Actor.Stop.Silent)


def receive(letter: Letter): Unit = letter match
final protected def receive(letter: Letter): Unit = letter match
/**/
case Tree.Create(width,level) =>
/* Calculate how many returns we expect, when we close later on. */
Expand Down

0 comments on commit 5ee6d1f

Please sign in to comment.