How to call an actor within itself in F# Akka - f#

The code I have is --
let mySlaveActor (mailbox: Actor<_>) =
let rec loop() = actor {
let mutable actor_id = -1
let mutable rumor = ""
let! rcv = mailbox.Receive()
let sender = mailbox.Sender()
match rcv with
| MessageType2(idx) ->
actor_id <- idx
| MessageType8(neighbor) ->
if (neighbor <> -1) then
let neighbor_slave = spawn mailbox (sprintf "workerActor%i" neighbor) mySlaveActor
neighbor_slave <! MessageType5(actor_id)
The current object is of a mySlaveActor whose name is workerActor1 and I want to call WorkerActor2 when the match is MessageType8(..). But in the penultimate line, I get an error like --
The value or constructor `mySlaveActor` is not defined
Am I doing something wrong is my code missing something? Thanks for the help.

Related

Data being lost while sending messages form one actor to another

I have created an Agent say "A", which simply sends some bulky data to Agent "B".
Agent A Code :
let largeText = "some large text (around 30kb)"
InputData_Type =
{
//some code
Body : string
}
let default_InputData =
{
//some code
Body = largeText
}
type ActorMsg =
| InItServices
| Data of InputData_Type
| UpdateList
let system = ActorSystem.Create("A")
let actRef = system.ActorSelection("akka.tcp://B#localhost:9999/user/EchoServer")
actRef.Ask(JsonConvert.SerializeObject(InItServices)).Wait()
[1..1000000]
|> List.iter(fun x ->
actRef.Tell(JsonConvert.SerializeObject(Data (default_InputData))))
let listLength = string(actRef.Ask(JsonConvert.SerializeObject(UpdateList)).Result)
printfn "length is %A" listLength
Agent "B" is stores/maintains the data he received into a database.
Agent B code :
try
let echoServer =
spawn system "EchoServer"
<| fun mailbox ->
let rec loop( cnt : int32 ) =
actor {
let! message = mailbox.Receive()
let sender = mailbox.Sender()
let deserializedEmailData = JsonConvert.DeserializeObject<ActorMsg> (message)
match deserializedEmailData with
| InItServices ->
sender <! ""
return! loop (0)
| Data (textData)->
// some logic to maintain list
let count = cnt + 1
return! loop (count)
| UpdateList ->
//some logic to store list
sender <! ("Length is " + cnt.ToString())
return! loop (0)
}
loop(0)
()
with
|exc ->
printfn "%A" exc
Agent "A" and "B" are created on same machine but are on different ports.
I have observed that, number of records received by agent B are different each time when I execute above setup.
Means say If I sent 20000 messages to Agent B, Agent B is actually receiving only say 1600(number varies) messages.
What exactly going wrong in above scenario ?

How to avoid mutable reference to Actor instance

I'm trying to gain some experience with Akka.NET actors in F#. I have the scenario when one actor needs to spin up another actor as its child. The first actor would convert each message and then send the result to the other actor. I use actorOf2 function to spawn actors. Here is my code:
let actor1 work1 work2 =
let mutable actor2Ref = null
let imp (mailbox : Actor<'a>) msg =
let result = work1 msg
if actor2Ref = null then
actor2Ref <- spawn mailbox.Context "decide-actor" (actorOf2 <| work2)
actor2Ref <! result
imp
let actor1Ref = actor1 work1' work2'
|> actorOf2
|> spawn system "my-actor"
What I don't like is the mutable actor reference. But I had to make it mutable because I need mailbox.Context to spawn a child actor, and I don't have any context before the first call. I saw this question but I don't know how to apply it to my function.
In a more advanced scenario I need a collection of child actors which is partitioned by a key. I'm using a Dictionary of actor refs in this scenario. Is there a better (more F#-ish) way?
In order to keep your "state" across iterations, you need to make the iterations explicit. That way, you can pass the current "state" as tail call argument. Just as in the question you linked:
let actor1 work1 work2 (mailbox : Actor<'a>) =
let rec imp actor2 =
actor {
let! msg = mailbox.Receive()
let result = work1 msg
let actor2 =
match actor2 with
| Some a -> a // Already spawned on a previous iteration
| None -> spawn mailbox.Context "decide-actor" (actorOf2 <| work2)
actor2 <! result
return! imp (Some actor2)
}
imp None
And now, you don't need to use actorOf2 or actorOf for spawning this actor, because it already has the right signature:
let actor1Ref =
actor1 work1' work2'
|> spawn system "my-actor"
.
EDIT
If you're concerned about the extra boilerplate, nothing prevents you from packing the boilerplate away as a function (after all, actorOf2 does something similar):
let actorOfWithState (f: Actor<'msg> -> 'state -> 'msg -> 'state) (initialState: 'state) mailbox =
let rec imp state =
actor {
let! msg = mailbox.Receive()
let newState = f mailbox state msg
return! imp newState
}
imp initialState
And then:
let actor1 work1 work2 (mailbox : Actor<'a>) actor2 msg =
let result = work1 msg
let actor2 =
match actor2 with
| Some a -> a
| None -> spawn mailbox.Context "decide-actor" (actorOf2 work2)
actor2 <! result
actor2
let actor1Ref =
actor1 work1' work2'
|> actorOfWithState
|> spawn system "my-actor"
You could do something along these lines, and just not store a reference to the child actor at all, because the Context is already doing that for you.
let actor =
let ar = mailbox.Context.Child(actorName)
if ar.IsNobody() then
spawn mailbox.Context actorName handler
else ar
If the Context.Child lookup turns out to be too slow, creating a memoized function that keeps mutability hidden from the other code would be pretty easy to do.

How can I manage an exclusive state in F#?

I am not sure about "exclusive state management" thing in the title, I did my best making it up trying to put the problem concisely.
I am porting some of my C# code to F# trying to do it as idiomatic as I can. I have an entity that requests a number of ID's from a sequence in my database and then dispenses these ID to anyone in need. Once an id is given out it should no longer be available for anybody else. Hence there must be some sort of state associated with that entity that keeps track of the remaining number of IDs. Since using a mutable state is not idiomatic, what I can do is to write something like this:
let createIdManager =
let idToStartWith = 127
let allowed = 10
let givenOut = 0
(idToStartWith, allowed, givenOut)
-
let getNextAvailableId (idToStartWith, allowed, givenOut) =
if givenOut< allowed
then ((idToStartWith, allowed, givenOut+ 1), Some(idToStartWith + givenOut))
else ((idToStartWith, allowed, givenOut), None)
let (idManager, idOpt) = getNextAvailableId createIdManager()
match idOpt with
| Some(id) -> printf "Yay!"
| None -> reloadIdManager idManager |> getNextAvailableId
This approach is idiomatic (as far as I can tell) but extremely vulnerable. There are so many ways to get it messed up. My biggest concern is that once an id is advanced and a newer copy of id manager is made, there is no force that can stop you from using the older copy and get the same id again.
So how do I do exclusive state management, per se, in F#?
If you only need to initialize the set of ids once then you can simply hide a mutable reference to a list inside a local function scope, as in:
let nextId =
let idsRef = ref <| loadIdsFromDatabase()
fun () ->
match idsRef.Value with
| [] ->
None
| id::ids ->
idsRef := ids
Some id
let id1 = nextId ()
let id2 = nextId ()
You could use a state-monad(Computational Expression).
First we declare the state-monad
type State<'s,'a> = State of ('s -> 'a * 's)
type StateBuilder<'s>() =
member x.Return v : State<'s,_> = State(fun s -> v,s)
member x.Bind(State v, f) : State<'s,_> =
State(fun s ->
let (a,s) = v s
let (State v') = f a
v' s)
let withState<'s> = StateBuilder<'s>()
let runState (State f) init = f init
Then we define your 'IdManager' and a function to get the next available id as well as the new state after the execution of the function.
type IdManager = {
IdToStartWith : int
Allowed : int
GivenOut : int
}
let getNextId state =
if state.Allowed > state.GivenOut then
Some (state.IdToStartWith + state.GivenOut), { state with GivenOut = state.GivenOut + 1 }
else
None, state
Finally we define our logic that requests the ids and execute the state-monad.
let idStateProcess =
withState {
let! id1 = State(getNextId)
printfn "Got id %A" id1
let! id2 = State(getNextId)
printfn "Got id %A" id2
//...
return ()
}
let initState = { IdToStartWith = 127; Allowed = 10; GivenOut = 0 }
let (_, postState) =
runState
idStateProcess
initState //This should be loaded from database in your case
Output:
Got id Some 127
Got id Some 128

Why does ZeroMQ's socket.recv call hang in the following code?

I have encountered a problem with a simple pub-sub example in ZeroMQ. I have read plenty of documentation, but I cannot seem to find an answer.
I got libzmq and clrzmq from NuGet. For both the functions below the socket address is:
let sktAddr = "tcp://127.0.0.1:3456"
Here is a simple publisher, that queues a message every second.
// Publisher - this seems to work fine
let publisher () : unit =
let skt = (new ZMQ.Context()).Socket(ZMQ.SocketType.PUB)
skt.SetSockOpt(ZMQ.SocketOpt.LINGER, 0)
skt.Bind sktAddr
skt.SendMore("TEST_TOPIC", Text.Encoding.Unicode) |> ignore
let rec h1 () : unit =
let nv = DateTime.Now.ToUniversalTime().ToString()
printfn "Sending value: %s" nv
skt.Send(Text.Encoding.Unicode.GetBytes nv) |> ignore
Threading.Thread.Sleep 1000
let swt = new Threading.SpinWait()
swt.SpinOnce()
if Console.KeyAvailable then
match Console.ReadKey().Key with
| ConsoleKey.Q -> ()
| _ -> h1()
else
h1()
h1()
The following simple subscriber throws no error, but hangs at the line indicated below.
// Subscriber
let subscriber () : unit =
let skt = (new ZMQ.Context()).Socket(ZMQ.SocketType.SUB)
skt.Connect sktAddr
skt.Subscribe("TEST_TOPIC", Text.Encoding.Unicode)
let rec h1 () : unit =
let oDat = skt.Recv() // THE PROGRAMME HANGS HERE!
let strODat = (new Text.UnicodeEncoding()).GetString oDat
if oDat <> null then
printfn "Received: %s" strODat
else
printfn "No data received"
let swt = new System.Threading.SpinWait()
swt.SpinOnce()
if Console.KeyAvailable then
match Console.ReadKey().Key with
| ConsoleKey.Q -> ()
| _ -> h1()
else
h1()
h1()
I have read this question, but no solution is provided. So I am posting a new question here.
Thanks in advance for your help.
I believe the problem is in the publisher:
skt.SendMore("TEST_TOPIC", Text.Encoding.Unicode)
Not knowing F#, it appears the above statement happens outside the loop. If the subscriber is listening on TEST_TOPIC, any messages originating from the publisher require the topic name to precede content for each message, so the publisher must do this each time it sends:
skt.SendMore("TEST_TOPIC", Text.Encoding.Unicode)
skt.Send("some data here", Text.Encoding.Unicode)
..try this...
let publisher () : unit =
let skt = (new ZMQ.Context()).Socket(ZMQ.SocketType.PUB)
skt.SetSockOpt(ZMQ.SocketOpt.LINGER, 0)
skt.Bind sktAddr
let rec h1 () : unit =
let nv = DateTime.Now.ToUniversalTime().ToString()
printfn "Sending value: %s" nv
skt.SendMore("TEST_TOPIC", Text.Encoding.Unicode) |> ignore
skt.Send(Text.Encoding.Unicode.GetBytes nv) |> ignore
Threading.Thread.Sleep 1000
let swt = new Threading.SpinWait()
swt.SpinOnce()
if Console.KeyAvailable then
match Console.ReadKey().Key with
| ConsoleKey.Q -> ()
| _ -> h1()
else
h1()
h1()
..and the subscriber has to receive twice for each message:
// Subscriber
let subscriber () : unit =
let skt = (new ZMQ.Context()).Socket(ZMQ.SocketType.SUB)
skt.Connect sktAddr
skt.Subscribe("TEST_TOPIC", Text.Encoding.Unicode)
let rec h1 () : unit =
let topicName = skt.Recv()
let oDat = skt.Recv()
let strODat = (new Text.UnicodeEncoding()).GetString oDat
if oDat <> null then
printfn "Received: %s" strODat
else
printfn "No data received"
let swt = new System.Threading.SpinWait()
swt.SpinOnce()
if Console.KeyAvailable then
match Console.ReadKey().Key with
| ConsoleKey.Q -> ()
| _ -> h1()
else
h1()
h1()

Eliminating my explicit state passing via like, monads and stuff

I'm working through the book Land of Lisp in F# (yeah weird, I know). For their first example text adventure, they make use of global variable mutation and I'd like to avoid it. My monad-fu is weak, so right now I'm doing ugly state passing like this:
let pickUp player thing (objects: Map<Location, Thing list>) =
let objs = objects.[player.Location]
let attempt = objs |> List.partition (fun o -> o.Name = thing)
match attempt with
| [], _ -> "You cannot get that.", player, objs
| thing :: _, things ->
let player' = { player with Objects = thing :: player.Objects }
let msg = sprintf "You are now carrying %s %s" thing.Article thing.Name
msg, player', things
let player = { Location = Room; Objects = [] }
let objects =
[Room, [{ Name = "whiskey"; Article = "some" }; { Name = "bucket"; Article = "a" }];
Garden, [{ Name = "chain"; Article = "a length of" }]]
|> Map.ofList
let msg, p', o' = pickUp player "bucket" objects
// etc.
How can I factor out the explicit state to make it prettier? (Assume I have access to a State monad type if it helps; I know there is sample code for it in F# out there.)
If you want to use the state monad to thread the player's inventory and world state through the pickUp function, here's one approach:
type State<'s,'a> = State of ('s -> 'a * 's)
type StateBuilder<'s>() =
member x.Return v : State<'s,_> = State(fun s -> v,s)
member x.Bind(State v, f) : State<'s,_> =
State(fun s ->
let (a,s) = v s
let (State v') = f a
v' s)
let withState<'s> = StateBuilder<'s>()
let getState = State(fun s -> s,s)
let putState v = State(fun _ -> (),v)
let runState (State f) init = f init
type Location = Room | Garden
type Thing = { Name : string; Article : string }
type Player = { Location : Location; Objects : Thing list }
let pickUp thing =
withState {
let! (player, objects:Map<_,_>) = getState
let objs = objects.[player.Location]
let attempt = objs |> List.partition (fun o -> o.Name = thing)
match attempt with
| [], _ ->
return "You cannot get that."
| thing :: _, things ->
let player' = { player with Objects = thing :: player.Objects }
let objects' = objects.Add(player.Location, things)
let msg = sprintf "You are now carrying %s %s" thing.Article thing.Name
do! putState (player', objects')
return msg
}
let player = { Location = Room; Objects = [] }
let objects =
[Room, [{ Name = "whiskey"; Article = "some" }; { Name = "bucket"; Article = "a" }]
Garden, [{ Name = "chain"; Article = "a length of" }]]
|> Map.ofList
let (msg, (player', objects')) =
(player, objects)
|> runState (pickUp "bucket")
If you want to use mutable state in F#, then the best way is just to write a mutable object. You can declare a mutable Player type like this:
type Player(initial:Location, objects:ResizeArray<Thing>) =
let mutable location = initial
member x.AddThing(obj) =
objects.Add(obj)
member x.Location
with get() = location
and set(v) = location <- v
Using monads to hide mutable state isn't as common in F#. Using monads gives you essentially the same imperative programming model. It hides the passing of state, but it doesn't change the programming model - there is some mutable state that makes it impossible to parallelize the program.
If the example uses mutation, then it is probably because it was designed in an imperative way. You can, change the program architecture to make it more functional. For example, instead of picking the item (and modifying the player), the pickUp function could just return some object representing a request to pick the item. The world would then have some engine that evaluates these requests (collected from all players) and calculates the new state of the world.

Resources