Im thinking how can I spawn an actor with some additional parameters in F# ?
I have the following actor function definition
let triggerActor (mailbox: Actor<TriggerCommand>) (name: string, expr : string, jobCallback : JobCallback) =
(...... cutted code, not needed here )
and Im trying to wrap that function to spawn an actor with
spawn system name (actorOf2 triggerActor )
but here I run into a troubles... how can I pass those additional params?
I know that I can create a custom C# style actor, but for now I want to try with F# :)
I'm not an expert on Akka, but assuming the "extra parameters" are the second argument you can do as follows.
First reverse the order of the formal parameters:
let triggerActor (name: string, expr : string, jobCallback : JobCallback) (mailbox: Actor<TriggerCommand>) = ...
Then partially apply the function:
spawn system name (actorOf2 (triggerActor ("name", "expr", jc )))
Related
Here is a test:
open System
open System.Threading
open Newtonsoft.Json
open Suave
open Suave.Logging
open Suave.Operators
open Suave.Filters
open Suave.Writers
let private configuration = {
defaultConfig with
bindings = [ HttpBinding.createSimple HTTP "0.0.0.0" 80 ]
}
let private getServerTime () : WebPart =
DateTime.UtcNow |> JsonConvert.SerializeObject |> Successful.OK >=> setMimeType "application/json"
let private webApplication =
choose
[
GET >=> choose
[
path "/servertime" >=> getServerTime ()
]
]
let start () =
let listening, server = startWebServerAsync configuration webApplication
server |> Async.Start
listening |> Async.RunSynchronously |> ignore
[<EntryPoint>]
let main _ =
start()
Thread.Sleep(Timeout.Infinite)
0
with this example, the getServerTime function is called once and this is it, every subsequent call to the endpoint will return the original result.
I don't understand why? When I use pathScan with parameters, then the function is called each time, as expected, but in this case, with a simple get, only the first call is done while this is defined as a function.
But I don't understand the doc at all either (from the flow of the doc, its contents and the overall document structure...), so the answer is probably simple :)
First of all, I would highly recommend that you study monadic composition. This is a necessary foundation for understanding these things. It will give you an idea of what >=> and >>= are and how to deal with them.
As for the problem at hand: yes, you defined getServerTime as a function, but that kind of doesn't matter, because that function is only called once, during construction of the webApplication value.
The structure of the server is such that it's literally a function HttpContext -> Async<HttpContext option>. It gets a request context and returns a modified version of it. And all of those combinators - choose and >=> and so on - they work with such functions.
The expression path "/servertime" is also such function. Literally. You can call it like this:
let httpCtx = ...
let newCtxAsync = path "/servertime" httpCtx
Moreover, the expression getServerTime() is ALSO such function. So you can do:
let httpCtx = ...
let newCtxAsync = getServerTime () httpCtx
That's what the WebPart type is. It's an async function from context to new context.
Now, what the >=> operator does is combine these functions. Makes them pipe the context from one webpart to the next. That's all.
When you wrote your getServerTime function, you created a WebPart that always returns the same thing. It's kind of like this:
let f x y = printf "x = %d" x
let g = f 42
Here, g is a function (just like a WebPart is a function), but whenever it's called, it will always return "x = 42". Why? Because I partially applied that parameter, it's sort of "baked in" in the definition of g now. The same way the current time is "baked in" in the WebPart that you have created inside getServerTime.
If you want a different time to be returned every time, you need to recreate the WebPart every time. Construct a new WebPart on every call, one with that call's time baked in. The smallest change to do that is probably this:
let private getServerTime () : WebPart =
let time : WebPart = fun ctx -> (DateTime.UtcNow |> string |> Successful.OK) ctx
time >=> setMimeType "text/plain"
On the surface it may look like the definition of time is silly: after all, let f x = g x can always be replaced by let f = g, right? Well, not always. Only as long as g is pure. But your webpart here is not: it depends on the current time.
This way, every time the time webpart is "run" (which means it gets a context as a parameter), it will run DateTime.UtcNow, then pass it to Successful.OK, and then pass the context to the resulting function.
Akka.Net:
Why does the actorOf function NOT require a function input that has a Actor<_> as a parameter?
It appears that the actorOf2 function DOES require a Actor<_> parameter.
The context of how these functions are called are the following:
let consoleWriterActor = spawn myActorSystem "consoleWriterActor" (actorOf Actors.consoleWriterActor)
let consoleReaderActor = spawn myActorSystem "consoleReaderActor" (actorOf2 (Actors.consoleReaderActor consoleWriterActor))
let consoleReaderActor (consoleWriter: IActorRef) (mailbox: Actor<_>) message =
...
let consoleWriterActor message =
...
The signature of actorOf is the following:
('Message -> unit) -> Actor<Message> -> Cont<'Message,'Returned>
The signature of actorOf2 is the following:
(Actor<Message> -> 'Message -> unit) -> Actor<Message> -> Cont<'Message,'Returned>
Conclusion:
I am new to Akka.net.
Thus, I don't understand why the "Actor<_>" parameter (which I believe represents a mailbox) would not be useful for the actorOf function.
actorOf2 function takes an Actor<_> parameter, which represents an actor execution context (from F# MailboxProcessor it's often called mailbox). It allows for things such as changing actor lifecycle, creating child actors or communicating with message sender.
However sometimes you may want to create actor, that is designed to work as a simple sink for your data i.e. processing the messages and push the result into some external service. This is where actorOf may be useful.
I am modelling a protocol in F#.
The protocol states that there is a login command that takes a username and a password as parameters, and there is a logout that takes no parameters.
The commands must be wrapped in some string post- and prefix before the protocol accepts them as a commands.
So far I have got the following model. A Command has some data associated with it, and at some point I want to wrap a given command with the post- and prefix.
To do this, I have have a new type called FormattedCommand which has a command, and a string representation of the command and the parameters along with the post/prefixes called SendString.
When I what to format a command by calling formatCommand: command:Command -> FormattedCommand I want to access the command's CommandString so I can attach the post/prefixes. How can I achieve this?
type CommandData = {
CommandString : string;
Parameters : string; }
type Command =
| Login of CommandData
| Logout of CommandData
type FormattedCommand = {
Command : Command;
SendString : string; }
let formatCommand (command:Command) =
{ Command = command; SendString = ?? }
If I understand your requirements correctly, I think that you can make it somewhat simpler.
The protocol states that there is a login command that takes a username and a password as parameters,
and there is a logout that takes no parameters.
I would model that like this:
type Command =
| Login of username:string * password:string
| Logout
The commands must be wrapped in some string post- and prefix before the protocol accepts them as a commands.
I would model that like this:
type FormattedCommand =
FormattedCommand of string
I don't see why the formatted command needs to know the original command at all. It seems like you're mixing concerns.
If you do need to pass them both around, use a tuple or make a simple record type.
I want to wrap a given command with the post- and prefix.
I would create a function that serializes the command like this:
let toFormattedCommand prefix postfix command =
let commandStr =
match command with
| Login (username,password) ->
sprintf "%s|Login|%s|%s|%s" prefix username password postfix
| Logout ->
sprintf "%s|Logout|%s" prefix postfix
FormattedCommand commandStr
I've just used bars to separate the fields. Obviously, the real protocol would be different.
The function above is generic, but you can bake in the default prefix if you like:
// bake in the defaults
let toFormattedCommandWithDefaults =
toFormattedCommand "pre" "post"
And then you can create examples like this:
let loginStr =
Login("alice","123")
|> toFormattedCommandWithDefaults
// FormattedCommand "pre|Login|alice|123|post"
let logoutStr =
Logout
|> toFormattedCommandWithDefaults
// FormattedCommand "pre|Logout|post"
you do it like this:
let formatCommand (command:Command) =
let sendString =
match command with
| Login data ->
// use data.CommandString and data.Parameters to format your result
| Logout data -> // dito
{ Command = command; SendString = sendString }
by the way:
you wrote that your Logout should have no parameters, yet you use CommandData too
Command and FormattedCommand share quite a lot - maybe you should use a ADT here too
let formatCommand (command:Command) =
{ Command = command; SendString = match command with
| Login c -> c.CommandString
| Logout c -> c.CommandString }
I have the following F# program that retrieves a webpage from the internet:
open System.Net
[<EntryPoint>]
let main argv =
let mutable pageData : byte[] = [| |]
let fullURI = "http://www.badaddress.xyz"
let wc = new WebClient()
try
pageData <- wc.DownloadData(fullURI)
()
with
| :? System.Net.WebException as err -> printfn "Web error: \n%s" err.Message
| exn -> printfn "Unknown exception:\n%s" exn.Message
0 // return an integer exit code
This works fine if the URI is valid and the machine has an internet connection and the web server responds properly etc. In an ideal functional programming world the results of a function would not depend on external variables not passed as arguments (side effects).
What I would like to know is what is the appropriate F# design pattern to deal with operations which might require the function to deal with recoverable external errors. For example if the website is down one might want to wait 5 minutes and try again. Should parameters like how many times to retry and delays between retries be passed explicitly or is it OK to embed these variables in the function?
In F#, when you want to handle recoverable errors you almost universally want to use the option or the Choice<_,_> type. In practice the only difference between them is that Choice allows you to return some information about the error while option does not. In other words, option is best when it doesn't matter how or why something failed (only that it did fail); Choice<_,_> is used when having information about how or why something failed is important. For example, you might want to write the error information to a log; or perhaps you want to handle an error situation differently based on why something failed -- a great use case for this is providing accurate error messages to help users diagnose a problem.
With that in mind, here's how I'd refactor your code to handle failures in a clean, functional style:
open System
open System.Net
/// Retrieves the content at the given URI.
let retrievePage (client : WebClient) (uri : Uri) =
// Preconditions
checkNonNull "uri" uri
if not <| uri.IsAbsoluteUri then
invalidArg "uri" "The URI must be an absolute URI."
try
// If the data is retrieved successfully, return it.
client.DownloadData uri
|> Choice1Of2
with
| :? System.Net.WebException as webExn ->
// Return the URI and WebException so they can be used to diagnose the problem.
Choice2Of2 (uri, webExn)
| _ ->
// Reraise any other exceptions -- we don't want to handle them here.
reraise ()
/// Retrieves the content at the given URI.
/// If a WebException is raised when retrieving the content, the request
/// will be retried up to a specified number of times.
let rec retrievePageRetry (retryWaitTime : TimeSpan) remainingRetries (client : WebClient) (uri : Uri) =
// Preconditions
checkNonNull "uri" uri
if not <| uri.IsAbsoluteUri then
invalidArg "uri" "The URI must be an absolute URI."
elif remainingRetries = 0u then
invalidArg "remainingRetries" "The number of retries must be greater than zero (0)."
// Try to retrieve the page.
match retrievePage client uri with
| Choice1Of2 _ as result ->
// Successfully retrieved the page. Return the result.
result
| Choice2Of2 _ as error ->
// Decrement the number of retries.
let retries = remainingRetries - 1u
// If there are no retries left, return the error along with the URI
// for diagnostic purposes; otherwise, wait a bit and try again.
if retries = 0u then error
else
// NOTE : If this is modified to use 'async', you MUST
// change this to use 'Async.Sleep' here instead!
System.Threading.Thread.Sleep retryWaitTime
// Try retrieving the page again.
retrievePageRetry retryWaitTime retries client uri
[<EntryPoint>]
let main argv =
/// WebClient used for retrieving content.
use wc = new WebClient ()
/// The amount of time to wait before re-attempting to fetch a page.
let retryWaitTime = TimeSpan.FromSeconds 2.0
/// The maximum number of times we'll try to fetch each page.
let maxPageRetries = 3u
/// The URI to fetch.
let fullURI = Uri ("http://www.badaddress.xyz", UriKind.Absolute)
// Fetch the page data.
match retrievePageRetry retryWaitTime maxPageRetries wc fullURI with
| Choice1Of2 pageData ->
printfn "Retrieved %u bytes from: %O" (Array.length pageData) fullURI
0 // Success
| Choice2Of2 (uri, error) ->
printfn "Unable to retrieve the content from: %O" uri
printfn "HTTP Status: (%i) %O" (int error.Status) error.Status
printfn "Message: %s" error.Message
1 // Failure
Basically, I split your code out into two functions, plus the original main:
One function that attempts to retrieve the content from a specified URI.
One function containing the logic for retrying attempts; this 'wraps' the first function which performs the actual requests.
The original main function now only handles 'settings' (which you could easily pull from an app.config or web.config) and printing the final results. In other words, it's oblivious to the retrying logic -- you could modify the single line of code with the match statement and use the non-retrying request function instead if you wanted.
If you want to pull content from multiple URIs AND wait for a significant amount of time (e.g., 5 minutes) between retries, you should modify the retrying logic to use a priority queue or something instead of using Thread.Sleep or Async.Sleep.
Shameless plug: my ExtCore library contains some things to make your life significantly easier when building something like this, especially if you want to make it all asynchronous. Most importantly, it provides an asyncChoice workflow and collections functions designed to work with it.
As for your question about passing in parameters (like the retry timeout and number of retries) -- I don't think there's a hard-and-fast rule for deciding whether to pass them in or hard-code them within the function. In most cases, I prefer to pass them in, though if you have more than a few parameters to pass in, you're better off creating a record to hold them all and passing that instead. Another approach I've used is to make the parameters option values, where the defaults are pulled from a configuration file (though you'll want to pull them from the file once and assign them to some private field to avoid re-parsing the configuration file each time your function is called); this makes it easy to modify the default values you've used in your code, but also gives you the flexibility of overriding them when necessary.
I'm reading Programming Erlang by Joe Armstrong(Pragmatic Bookshelf). In name_server.erl source code on Chapter 16, Where's Dict variable from? Calling dict:new() generates Dict automatically? And, reference says that dict:new() creates dictionary. Don't I need to store it as a variable like Dict = dict:new()?
-module(name_server).
-export([init/0, add/2, whereis/1, handle/2]).
-import(server1, [rpc/2]).
add(Name, Place) ->
rpc(name_server, {add, Name, Place}).
whereis(Name) ->
rpc(name_server, {whereis, Name}).
init() ->
dict:new().
handle({add, Name, Place}, Dict) ->
{ok, dict:store(Name, Place, Dict)};
handle({whereis, Name}, Dict) ->
{dict:find(Name, Dict), Dict}.
This is part of a two file example. The other file (immediately before it in the book) is server.erl. It contains a loop function that calls the handle function in name_server.erl (or whatever module you pass to it):
The line is:
{Response, State1} = Mod:handle(Request, State),
where Mod is the module passed to start earlier. And State is initialised earlier as Mod:init() in the start function.
So State is initialised to name_server:init() which in your file returns dict:new(). However, as loop is called recursively State will take the next value of State1.
So when handle is called, Dict is set to the current value of State.