Last active
May 28, 2023 13:00
-
-
Save akimboyko/e58e4bfbba3e9a551f05 to your computer and use it in GitHub Desktop.
Samples from "Actor-based Concurrency with F# and Akka.NET" http://bit.ly/FSharpAkkaNET
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#time "on" | |
#load "Bootstrap.fsx" | |
open System | |
open Akka.Actor | |
open Akka.Configuration | |
open Akka.FSharp | |
open Akka.TestKit | |
// #Using Actor | |
// Actors are one of Akka's concurrent models. | |
// An Actor is a like a thread instance with a mailbox. | |
// It can be created with system.ActorOf: use receive to get a message, and <! to send a message. | |
// This example is an EchoServer which can receive messages then print them. | |
let system = ActorSystem.Create("FSharp") | |
type EchoServer = | |
inherit Actor | |
override x.OnReceive message = | |
match message with | |
| :? string as msg -> printfn "Hello %s" msg | |
| _ -> failwith "unknown message" | |
let echoServer = system.ActorOf(Props(typedefof<EchoServer>, Array.empty)) | |
echoServer <! "F#!" | |
system.Shutdown() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#time "on" | |
#load "Bootstrap.fsx" | |
open System | |
open Akka.Actor | |
open Akka.Configuration | |
open Akka.FSharp | |
open Akka.TestKit | |
// #Simplify Actor | |
// There is a simpler way to define an Actor | |
let system = ActorSystem.Create("FSharp") | |
let echoServer = | |
spawn system "EchoServer" | |
<| fun mailbox -> | |
actor { | |
let! message = mailbox.Receive() | |
match box message with | |
| :? string as msg -> printfn "Hello %s" msg | |
| _ -> failwith "unknown message" | |
} | |
echoServer <! "F#!" | |
system.Shutdown() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#time "on" | |
#load "Bootstrap.fsx" | |
open System | |
open Akka.Actor | |
open Akka.Configuration | |
open Akka.FSharp | |
open Akka.TestKit | |
// #Actor Implementation | |
// An Actor is more lightweight than a thread. Millions of actors can be generated in Akka, | |
// the secret is that an Actor can reuse a thread. | |
// | |
// The mapping relationship between an Actor and a Thread is decided by a Dispatcher. | |
// | |
// This example creates 10 Actors, and prints its thread name when invoked. | |
// | |
// You will find there is no fixed mapping relationship between Actors and Threads. | |
// An Actor can use many threads. And a thread can be used by many Actors. | |
let system = ActorSystem.Create("FSharp") | |
type EchoServer(name) = | |
inherit Actor() | |
override x.OnReceive message = | |
let tid = Threading.Thread.CurrentThread.ManagedThreadId | |
match message with | |
| :? string as msg -> printfn "Hello %s from %s at #%d thread" msg name tid | |
| _ -> failwith "unknown message" | |
let echoServers = | |
[1 .. 10] | |
|> List.map(fun id -> let properties = [| string(id) :> obj |] | |
system.ActorOf(Props(typedefof<EchoServer>, properties))) | |
let rand = Random(1234) | |
for id in [1 .. 10] do | |
(rand.Next() % 10) |> List.nth echoServers <! sprintf "F# request %d!" id | |
system.Shutdown() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#time "on" | |
#load "Bootstrap.fsx" | |
open System | |
open Akka.Actor | |
open Akka.Configuration | |
open Akka.FSharp | |
open Akka.TestKit | |
// #Synchronized Return | |
// Actors are very suitable for long-running operations, like getting resources over a network. | |
// | |
// This example creates a Task with the ask function. | |
// | |
// In the actor we use 'sender <!' to return the value. | |
// | |
// #Asynchronous Return | |
// Asynchronous operations can provide better performance. | |
// A Task in F# is very powerful, it can execute asynchronously. | |
// It can also set a in milliseconds to wait for the result of the computation | |
// before raising a `TimeoutException`. | |
let versionUrl = @"https://raw.githubusercontent.com/akkadotnet/akka.net/dev/src/SharedAssemblyInfo.cs" | |
let system = ActorSystem.Create("FSharp") | |
let fromUrl (url:string) = | |
use client = new System.Net.WebClient() | |
let response = client.DownloadString(url) | |
response | |
let echoServer = | |
spawn system "EchoServer" | |
<| fun mailbox -> | |
let rec loop() = | |
actor { | |
let! message = mailbox.Receive() | |
let sender = mailbox.Sender() | |
match box message with | |
| :? string as url -> | |
let response = fromUrl url | |
printfn "actor: done!" | |
sender <! response | |
return! loop() | |
| _ -> failwith "unknown message" | |
} | |
loop() | |
for timeout in [10; 100; 250; 2500] do | |
try | |
let task = (echoServer <? versionUrl) | |
let response = Async.RunSynchronously (task, timeout) | |
let responseLength = string(response) |> String.length | |
printfn "response: result has %d bytes" responseLength | |
with :? TimeoutException -> | |
printfn "ask: timeout!" | |
system.Shutdown() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#time "on" | |
#load "Bootstrap.fsx" | |
open System | |
open Akka.Actor | |
open Akka.Configuration | |
open Akka.FSharp | |
open Akka.TestKit | |
// #Remote Actor | |
// Actor is not only a concurrency model, it can also be used for distributed computing. | |
// This example builds an EchoServer using an Actor. | |
// Then it creates a client to access the Akka URL. | |
// The usage is the same as with a normal Actor. | |
let configuration = | |
ConfigurationFactory.ParseString( | |
@"akka { | |
log-config-on-start : on | |
stdout-loglevel : DEBUG | |
loglevel : ERROR | |
actor { | |
provider = ""Akka.Remote.RemoteActorRefProvider, Akka.Remote"" | |
debug : { | |
receive : on | |
autoreceive : on | |
lifecycle : on | |
event-stream : on | |
unhandled : on | |
} | |
} | |
remote { | |
helios.tcp { | |
port = 8777 | |
hostname = localhost | |
} | |
} | |
}") | |
let system = ActorSystem.Create("RemoteFSharp", configuration) | |
let echoServer = | |
spawn system "EchoServer" | |
<| fun mailbox -> | |
let rec loop() = | |
actor { | |
let! message = mailbox.Receive() | |
let sender = mailbox.Sender() | |
match box message with | |
| :? string -> | |
printfn "super!" | |
sender <! sprintf "Hello %s remote" message | |
return! loop() | |
| _ -> failwith "unknown message" | |
} | |
loop() | |
let echoClient = system.ActorSelection( | |
"akka.tcp://RemoteFSharp@localhost:8777/user/EchoServer") | |
let task = echoClient <? "F#!" | |
let response = Async.RunSynchronously (task, 1000) | |
printfn "Reply from remote %s" (string(response)) | |
system.Shutdown() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#time "on" | |
#load "Bootstrap.fsx" | |
open System | |
open Akka.Actor | |
open Akka.Configuration | |
open Akka.FSharp | |
open Akka.TestKit | |
// #Event Bus | |
// Originally conceived as a way to send messages to groups of actors, the EventBus has been generalized to Event Stream | |
// #Event Stream | |
// The event stream is the main event bus of each actor system: it is used for carrying log messages and Dead Letters and may be used by the user code for other purposes as well. It uses Subchannel Classification which enables registering to related sets of channels | |
let system = ActorSystem.Create("FSharp") | |
let echoServer = | |
spawn system "EchoServer" | |
<| fun mailbox -> | |
let rec loop() = | |
actor { | |
let! message = mailbox.Receive() | |
match box message with | |
| :? string -> | |
printfn "Echo '%s'" message | |
return! loop() | |
| _ -> failwith "unknown message" | |
} | |
loop() | |
let eventStream = system.EventStream | |
eventStream.Subscribe(echoServer, typedefof<string>) | |
eventStream.Publish("Anybody home?") | |
eventStream.Publish("Knock knock") | |
system.Shutdown() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#time "on" | |
#load "Bootstrap.fsx" | |
open System | |
open Akka.Actor | |
open Akka.Configuration | |
open Akka.FSharp | |
open Akka.TestKit | |
// # Discriminated unions as messages | |
// Instead of passing primitive type, let's use discriminated union | |
type ActorMsg = | |
| Hello of string | |
| Hi | |
let system = ActorSystem.Create("FSharp") | |
let echoServer = | |
spawn system "EchoServer" | |
<| fun mailbox -> | |
let rec replyUa() = | |
actor { | |
let! message = mailbox.Receive() | |
match message with | |
| Hello name -> printfn "Привіт %s" name | |
| Hi -> printfn "Привіт!" | |
return! replySw() | |
} | |
and replySw() = | |
actor { | |
let! message = mailbox.Receive() | |
match message with | |
| Hello name -> printfn "Hallå %s" name | |
| Hi -> printfn "Hallå!" | |
return! replyUa() | |
} | |
replyUa() | |
echoServer <! Hello "Kyiv F# group!" | |
echoServer <! Hello "Akka.NET team!" | |
system.Shutdown() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#time "on" | |
#I @"..\packages\Akka.0.7.0\lib\net45" | |
#I @"..\packages\Akka.FSharp.0.7.0\lib\net45" | |
#I @"..\packages\Akka.Remote.0.7.0\lib\net45" | |
#I @"..\packages\Akka.TestKit.0.7.0\lib\net45" | |
#I @"..\packages\FsPickler.0.9.11\lib\net45" | |
#I @"..\packages\FSPowerPack.Core.Community.3.0.0.0\Lib\Net40" | |
#I @"..\packages\FSPowerPack.Linq.Community.3.0.0.0\Lib\Net40" | |
#I @"..\packages\Newtonsoft.Json.6.0.1\lib\net45" | |
#I @"..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40" | |
#I @"..\packages\Helios.1.3.5.0\lib\net45" | |
#r "Akka.dll" | |
#r "Akka.FSharp.dll" | |
#r "Akka.Remote.dll" | |
#r "Akka.TestKit.dll" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
sudo mkdir -p /mnt/samples && sudo mount -r -t vboxsf samples /mnt/samples | |
cp /mnt/samples/Dockerfile . && cp -r /mnt/samples/bin . | |
docker build -t samples . | |
docker run -i samples | |
docker run -it samples bash | |
docker images |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
FROM mono:latest | |
MAINTAINER Akim Boyko "akim dot boyko at gmail.com" version: 0.1 | |
ENV AKKADIR /akka | |
RUN mkdir -p $AKKADIR | |
WORKDIR $AKKADIR | |
RUN mozroots --import --sync | |
ADD bin/Debug $AKKADIR | |
CMD [ "mono", "./Sample.exe" ] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi Patrick!
Did not see your comment. There is an updated version of slides (http://bit.ly/FSharpAkkaNET) will be available today afternoon after my talk. There are Docker samples too