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

  • Virtual actors = grains
  • At-least-once delivery by default
  • Caller awaits remote execution
  • Runtime manages pain points:

    • Clustering and availability
    • Grain distribution
    • GC inactive grains
    • Distributed transactions (Beta)

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 

DEMO

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 =>

    • safety
    • development speed

Thank you!