Multiple items
val string : value:'T -> string
Full name: Microsoft.FSharp.Core.Operators.string
--------------------
type string = System.String
Full name: Microsoft.FSharp.Core.string
val printfn : format:Printf.TextWriterFormat<'T> -> 'T
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
val ignore : value:'T -> unit
Full name: Microsoft.FSharp.Core.Operators.ignore
Orleankka + F#
Stateful distributed architecture via MSFT Orleans
Alexander Prooks - @aprooks
Stateless
Pros
- Easy?
- Scalable? application servers
Cons
- State = database
- Complixity via Queues, BUSes etc. => latency
- Cache invalidation
-
External scheduling:
- lock user if it was not activated for 24 hours?
Objects in memory?
- Concurrency (locks, mutexes etc.)
- Object location
- System Resilience
- Memory management
=> Don't do it!
Actor model
- Function or object
- Isolated state
- Syncronous execution
- Messages (requests) are queued in-memory
Implementations
- Erlang ( Since 1986! )
- Akka: Jvm and .Net
- Orleans: .Net and Orbit Jvm
- ProtoActors: Go, .Net (cross platform)
Akka/Erlang
1:
2:
|
var game = activate(“game-1”, “tcp://10.0.0.1/”)
game.invoke(“foo()”)
|
Orleans
1:
2:
|
var game = getGrainReference(“game-1”)
game.invoke(“foo()”)
|
Orleans vs others
Simplicity => Profit!
Programming model
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
|
public interface IPinger{
Task<Pong> Ping();
}
public class Pinger: Grain, IPinger
{
public Task<Pong> Ping(){
return Task.FromResult("Pong");
}
}
|
Orleankka function interface
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
|
[Serializable]
public class Ping : ActorMessage<Pinger>
{
}
public class Pinger: Actor{
public Task<string> Handle(Ping request){
return Task.FromResult("Pong");
}
}
|
Calling another actor
1:
2:
|
var pinger = System.ActorOf<Pinger>("someId");
await pinger.Tell(new Ping());
|
Orleans + F# =
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
|
module Pingers =
type Message =
| Ping of string
type IPinger =
inherit IActorGrain<Message>
type Pinger() =
inherit Actor()
interface IPinger
override this.Receive message = task {
match message with
| :? Message msg ->
match msg with
| Ping name->
return some("Hello " + name)
}
|
Calling grains
1:
2:
3:
4:
5:
6:
7:
8:
|
let job() = task {
let pinger = ActorSystem.actorOf<Pinger>(actorSystem,"myId")
let! res = pinger <? Ping ("Alex")
printfn "%s" res // Hello Alex
}
Task.run (job)
|> ignore
|
Core components
1:
2:
3:
4:
5:
6:
7:
|
OnReceive -> Handle all
Activate -> load state
Reminder -> Persistent scheduling
Timers -> Recurring operations
Streams -> Pub/Sub
Reentrancy -> Concurrent execution (Queries!)
Workers -> Stateless parallelism
|
Marketing
-
Halo with 14 ml users
- EA implemented Orbit in JVM
-
Stuff I did:
- License and usage tracking + finance
- Property management system
-
Utility services
*
Wrapping up
- F# is awesome DDD oriented language
- Orleans is awesome platform
-
F# + Orleannkka =>