diff --git a/slides/12/actor-2.md b/slides/12/actor-2.md
index e482eea..082dfce 100644
--- a/slides/12/actor-2.md
+++ b/slides/12/actor-2.md
@@ -8,26 +8,14 @@
### Agenda
* Actor lifecycle
-* ActorSelection
+* Actor selection
+* Good design practices
* State machines
-* Router
+* Router actors
---
-TODO: insert
-
-#### Actor path
-
-* Every actor has an actor path
-* Actor path can be used to send messages to an actor
-
-
-
----
-
-
----
### Actor lifecycle
@@ -42,43 +30,41 @@ Actor have 5 stage life cycle
#### Lifecycle stages
-* `Starting`: Actor is waking up
-* `Recieving`: Actor is accepting messages
-* `Stopping`: Actor is cleaning up its state, or saving state if restarting
-* `Terminated`: Actor is dead
-* `Restarting`: Actor is about to restart
+* Starting: Actor is waking up
+* Recieving: Actor is accepting messages
+* Stopping: Actor is cleaning up its state, or saving state if restarting
+* Terminated: Actor is dead
+* Restarting: Actor is about to restart
----
#### Lifecycle hooks
-* `PreStart`: Run before receiving - used to initialize
-* `PreRestart`: used to cleanup before restart
-* `PostStop`: Called when actor has stopped recieving. Cleanup - called as part of `PreRestart`
-* `PostRestart`: Called after `PreRestart` and before `PreStart`. Additional reporting/diagnosis
+* PreStart: Run before receiving - used to initialize
+* PreRestart: used to cleanup before restart
+* PostStop: Called when actor has stopped recieving. Cleanup - called as part of `PreRestart`
+* PostRestart: Called after `PreRestart` and before `PreStart`. Additional reporting/diagnosis
----
-#### How to do you do this in F#
+### classes in F#
-Method 1)
+```fsharp [1-2, 7-8]
+type PlaybackActor() =
+ inherit UntypedActor()
-```fsharp
-let preStart = Some(fun () ->
- Console.WriteLine "preStart Called"
- |> ignore)
-let mySampleActor = spawnOvrd system "actor"
- (actorOf sampleActor) <|
- {defOvrd with PreStart = preStart}
+ override __.OnReceive message =
+ // TODO
+
+ override __.PreStart() =
+ // do something, like logging for example
```
----
#### Only for `PreStart` and/or `PostStop`
-Method 2)
-
```fsharp
let sampleActor (mailbox:Actor<_>) =
// this section works like pre-start
@@ -88,7 +74,7 @@ let sampleActor (mailbox:Actor<_>) =
let rec loop () =
actor {
let! msg = mailbox.Receive ()
- // do some work
+ // TODO handle msg
return! loop ()
}
loop ()
@@ -96,38 +82,54 @@ let sampleActor (mailbox:Actor<_>) =
let aref = spawn system "actor" (sampleActor)
```
-Note:
-
-This syntax is called a computation expresion - we will briefly touch on this in week 13/14 - otherwise the HR chapter 12.
---
### ActorSelection
-* Used to send messages to actor(s) to which you don't have an `IActorRef`
-* Done by actor path
+* Every actor has an actor path
+* Actor path can be used to send messages to an actor
+* Used to send messages to actor(s) to which you don't have an IActorRef
+
-
+
----
#### ActorSelection details
-* ActorSelection
+* ActorSelection
* The processs of looking up an actor
* The object returned from that lookup
-* ActorSelection don't give you a 1:1 relationship
-* ActorSelection give you a handle to all actors behind that path
+* ActorSelection don't give you a 1:1 relationship
+* ActorSelection give you a handle to all actors behind that path
* e.g. wildcards are supported
+
+----
+
+#### Creating an actor path
+
+```fsharp
+let selection = select "path/to/actor" mailbox.Context.System
+
+// e.g.
+let myFooActor = spawn actorSystem "barActor"
+ (actorOf fooActor)
+// in an actor
+let selection' = select "akka://user/barActor"
+ mailbox.Context.System
+selection'
+* Loose coupling
+* Dynamic behavior
+* Adaptive system design
----
@@ -141,80 +143,65 @@ This syntax is called a computation expresion - we will briefly touch on this in
#### Loose coupling
-* Don't need to store and/or pass around `IActorRef`
-* Less coupling between actors/components
+* Don't need to store and/or pass around IActorRef
+* Less coupling between actors/components
----
#### Dynamic behavior
-* In a dynamic system where actors are created/removed
+* In a dynamic system where actors are created/removed
* you can send messages to known addresses
-* Don't need to be hardcoded adresses, messages can represent actorPath
+* Don't need to be hardcoded adresses, messages can represent actorPath
----
#### Adaptive system design
-* Help when buidling actor system
-* You can introduce new actors/sections without going back and changing the existing system
+* Help when buidling actor system
+* You can introduce new actors without going back and changing the existing system
----
#### When to use
-1. Talking to top level actors
+1. Talking to top level actors
* E.g you have an `AuthenticateActor` which name is `/user/AuthenticateActor`
```fsharp
select "akka://MyActorSystem/user/AuthenticateActor"
mailbox.Context.System
-2. Handoff work to a pool of worker actors
-3. When processing a message and `Sender` is not enough
-4. Send to multiple actors
+2. Send to multiple actors
+3. When processing a message and 'Sender' is not enough
+4. Handoff work to a pool of worker actors
----
-#### Don't send `ActorPaths` around
+#### Take care when passing `ActorPaths` around
Because:
* ActorSelection can be relative
-----
-
-#### Creating an actor path
-
-```fsharp
-let selection = select "path/to/actor" mailbox.Context.System
-
-// e.g.
-let myFooActor = spawn actorSystem "barActor"
- (actorOf fooActor)
-// in an actor
-let selection' = select "akka://user/barActor"
- mailbox.Context.System
-selection'
+* Always communicate via top-level actors
+* Delegate risky operations to leafs
----
### Knowledge
-* Make it possible to change implementation details (DIP, LSP)
-* Top-level actors are interfaces
+* Make it possible to change implementation details (DIP, LSP)
+* Use top-level actors as interfaces
-
+
----
@@ -223,10 +210,10 @@ selection'
* by `IActorRef` or `ActorSelection`
-* Make extension possible (OCP)
-* Return is possible with `IActorRef.Forward`
+* Makes extension possible (OCP)
+* Return is possible with IActorRef.Forward
---
@@ -239,12 +226,12 @@ selection'
+* Many state machines have some sort of time perspective
* change state after some time
* stay in a state for some time
-\* called `become` in C# and Scala
+\* called become in C# and Scala
----
@@ -273,10 +260,10 @@ let actor (mailbox: Actor<_>) =
#### Different states
-* In the above example our actor can handle messages base on 3 states
+* In the above example our actor can handle messages base on 3 states
* `autenticating`, `unauthenticated` and `authenticated`
-* This enables reusablitity, and different work with little code
-* Safe because we only handle one messages at a time.
+* This enables reusablitity, and different work with little code
+* Safe because actors only handle one messages at a time.
----
@@ -284,7 +271,7 @@ let actor (mailbox: Actor<_>) =
Let us imagine a chat example:
-```fsharp
+```fsharp [1-13|7|14-25|6|26-36 ]
let rec authenticating () =
actor {
let! message = mailbox.Receive ()
@@ -343,10 +330,10 @@ let actor (mailbox: Actor<_>) =
#### Unhandled messages
-* Actors has a `Stash` which acts like stack structure
+* Actors has a Stash
which acts like stack structure
* Calling `mailbox.Stash ()` puts current message onto stack
-* `mailbox.Unstash ()` puts the top message at the front of the inbox
-* `mailbox.UnstashAll ()` unstashed all messages.
+* mailbox.Unstash ()
puts the top message at the front of the inbox
+* mailbox.UnstashAll ()
unstashes all messages.
* Preserves FIFO order
@@ -354,7 +341,7 @@ let actor (mailbox: Actor<_>) =
#### Unstash in our example
-```fsharp
+```fsharp[9-12|5,7]
let rec authenticating () =
actor {
let! message = mailbox.Receive ()
@@ -375,49 +362,53 @@ let rec authenticating () =
#### Stashed messages
-* Keep states
-* In case of restart
+* Keep states
+* In case of restart
* Stash is lost with actor state
- * Unstash all before restart can save messages in mailbox
+ * Unstash all before restart will save messages in mailbox
-```fsharp
-let preRestart = Some(fun (basefn: exn * obj -> unit)
- -> mailbox.UnstashAll () |> ignore)
-let mySampleActor = spawnOvrd system "actor"
- (actorOf sampleActor)
- <| { defOvrd with PreRestart = preRestart }
+```fsharp [2]
+let disposableActor (mailbox:Actor<_>) =
+ mailbox.Defer (fun () -> mailbox.UnstashAll ())
+ let rec loop () =
+ actor {
+ let! msg = mailbox.Receive()
+ return! loop ()
+ }
+ loop()
```
+
---
### Router
-* Special actor types (Pool or Group)
-* Can handle multiple messages at a time (Whuut!)
-* Router actors can only forward messages (puh)
-* Routers can be configured programaticly or using conf files
+* Special actor types (Pool or Group)
+* Can handle multiple messages at a time (Whuut!)
+* Router actors can only forward messages (puh)
+* Routers can be configured programaticly or using conf files
----
#### Pool Router
-* Owns (supervise) their routee children
-* Makes it possible to control pool size
+* Owns (supervise) their routee children
+* Makes it possible to control pool size
----
#### Routing strategies
-* `Broadcast` - Forward to all routees
-* `Random` - Forward to a random routee
-* `ConsistentHash` - Forward to a specific routee based on message
+* Broadcast - Forward to all routees
+* Random - Forward to a random routee
+* ConsistentHash - Forward to a specific routee based on message
----
#### Supervision
-* Router are actors so we can used `SupervisorStrategy`
-* Default is 'always escalate'
+* Router are actors so we can used SupervisorStrategy
+* Default is 'always escalate'
----
@@ -461,20 +452,20 @@ akka.actor.deployment {
Try to evenly distribute work
-* `RoundRobin` - just forward each message to a new routee
-* `TailChooping` - forward to one random routee, after some delay send to a new until answer is recieved.
-* `ScatterGatherFirstCompleted` - forward to all routees and return first answer. If no answer within a given timeframe, reply to sender.
+* RoundRobin
- just forward each message to a new routee
+* TailChooping
- forward to one random routee, after some delay send to a new until answer is recieved.
+* ScatterGatherFirstCompleted
- forward to all routees and return first answer. If no answer within a given timeframe, reply to sender.
----
#### Load balacing 2 (Pool only)
-* `Resizable` - Forward to routee with fewest messages in mailbox
+* Resizable
- Forward to routee with fewest messages in mailbox
1. Idle routee
2. Routee with empty mailbox
3. Routee with fewest messages
4. Remote routee
-* `ResizableRouter` - 'Auto scaling', tries to detect pressure on routee and expand/contract pool size
+* ResizableRouter
- 'Auto scaling', tries to detect pressure on routee and expand/contract pool size
----
@@ -495,10 +486,10 @@ router Do not supervise the routee
* ActorRefs are handed to the Group Router
-```fsharp
+```fsharp [10-11]
// Create some routee actors
let c1 = spawn mailbox.Context "coordinator1" (coordinatorA)
let c2 = spawn mailbox.Context "coordinator2" (coordinatorA)
@@ -511,6 +502,7 @@ let coordinatorPaths =
let coordinator = mailbox.Context.ActorOf(
Props.Empty.WithRouter(BroadcastGroup(coordinatorPaths)))
```
+
----
@@ -519,7 +511,7 @@ let coordinator = mailbox.Context.ActorOf(
* Use Pool actor unless
1. Router should be able to send via `ActorSelection`
2. You router cannot (for some reason) be responsible for routees
- 3. You need to be able to send to different actors
+ 3. You need to be able to send to different types of actors
---
diff --git a/slides/12/index.html b/slides/12/index.html
index d348397..526e008 100644
--- a/slides/12/index.html
+++ b/slides/12/index.html
@@ -17,6 +17,23 @@
+