f# actor akka.net

¿Cómo almacenar estado en un Actor F#Akka.NET?



(2)

En C # ReceiveActor s, puedo tener estados como campos privados en la clase. ¿Cómo debo hacer esto de forma idiomática con la API F #?

¿Es esta una buena idea? Alguna alternativa?

let handleMessage (mailbox: Actor<''a>) msg = let mutable i = 1 match msg with | Some x -> i <- i + x | None -> ()


Hay dos soluciones, ambas usan la definición de bucle recursivo explícito, concepto principal de los actores Akka F #.

Primero puede definir variables, que deberían ser visibles solo dentro del alcance del actor, antes de la definición del bucle (en el ejemplo siguiente he cambiado la definición a la celda de referencia, porque las variables mutables no pueden ser capturadas por cierres):

let actorRef = spawn system "my-actor" <| fun mailbox -> let i = ref 1 let rec loop () = actor { let! msg = mailbox.Receive() match msg with | Some x -> i := !i + x | None -> () return! loop() } loop()

Sin embargo, una solución más recomendada es mantener su estado inmutable durante el manejo de mensajes, y cambiarlo solo al pasar las siguientes llamadas al bucle, así:

let actorRef = spawn system "my-actor" <| fun mailbox -> let rec loop i = actor { let! msg = mailbox.Receive() match msg with | Some x -> return! loop (i + x) | None -> return! loop i } loop 1 // invoke first call with initial state


La forma en que ha propuesto es totalmente apropiada como medio de almacenar el estado dentro del actor. Las restricciones de concurrencia de procesar solo 1 mensaje en cualquier momento significa que no es posible acceder a estados no válidos como resultado de la contención en una ubicación de memoria compartida.

Sin embargo, no es la opción más idiomática. Akka.Net proporciona una API F # para trabajar con actores de forma similar a F # MailboxProcessors. En este caso, define a su actor como una función recursiva de la cola que se llama a sí misma con un nuevo estado. Aquí hay un ejemplo

spawn system "hello" <| fun mailbox -> let rec loop state = actor { let! msg = mailbox.Receive () printfn "Received %A. Now received %s messages" msg state return! loop (state + 1) //Increment a counter for the number of times the actor has received a message } loop 0

Para obtener la documentación completa sobre la API Akka.Net F #, consulte http://getakka.net/wiki/FSharp%20API