From 0cd8a007688631f89c7c3231204f873111dbf290 Mon Sep 17 00:00:00 2001 From: cotyar Date: Fri, 16 Mar 2018 12:51:54 +0000 Subject: [PATCH 1/7] Removed redundant [] on Persistence --- src/Proto.Actor.FSharp.Persistence/Proto.FSharp.Persistence.fs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Proto.Actor.FSharp.Persistence/Proto.FSharp.Persistence.fs b/src/Proto.Actor.FSharp.Persistence/Proto.FSharp.Persistence.fs index 3ea5f0b..d87ab95 100644 --- a/src/Proto.Actor.FSharp.Persistence/Proto.FSharp.Persistence.fs +++ b/src/Proto.Actor.FSharp.Persistence/Proto.FSharp.Persistence.fs @@ -8,7 +8,6 @@ namespace Avalanchain.Core open Proto.FSharp -[] module Persistence = open Proto open Proto.Persistence From c656fff3504122ef4351041d3e3e8025297761fe Mon Sep 17 00:00:00 2001 From: cotyar Date: Fri, 16 Mar 2018 16:14:55 +0000 Subject: [PATCH 2/7] Removed redundant [] on Persistence --- .paket/paket.bootstrapper.exe | Bin 63784 -> 0 bytes .../Proto.FSharp.Persistence.fs | 2 -- 2 files changed, 2 deletions(-) delete mode 100644 .paket/paket.bootstrapper.exe diff --git a/.paket/paket.bootstrapper.exe b/.paket/paket.bootstrapper.exe deleted file mode 100644 index 167dfd6c4c629c32481d28d3a203f224cfc3ad7e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 63784 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 PVCDS&TYv2E+1URBVkO7S diff --git a/src/Proto.Actor.FSharp.Persistence/Proto.FSharp.Persistence.fs b/src/Proto.Actor.FSharp.Persistence/Proto.FSharp.Persistence.fs index d87ab95..8a31e09 100644 --- a/src/Proto.Actor.FSharp.Persistence/Proto.FSharp.Persistence.fs +++ b/src/Proto.Actor.FSharp.Persistence/Proto.FSharp.Persistence.fs @@ -4,8 +4,6 @@ open Proto open System.Threading.Tasks open System -namespace Avalanchain.Core - open Proto.FSharp module Persistence = From 06c0c3475cf7e5405bb830b4f2c4a385c27af671 Mon Sep 17 00:00:00 2001 From: cotyar Date: Mon, 19 Mar 2018 20:45:51 +0000 Subject: [PATCH 3/7] Making processCommand async --- .../Proto.FSharp.Persistence.fs | 44 ++++++++++++------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/src/Proto.Actor.FSharp.Persistence/Proto.FSharp.Persistence.fs b/src/Proto.Actor.FSharp.Persistence/Proto.FSharp.Persistence.fs index 8a31e09..6f3b9fb 100644 --- a/src/Proto.Actor.FSharp.Persistence/Proto.FSharp.Persistence.fs +++ b/src/Proto.Actor.FSharp.Persistence/Proto.FSharp.Persistence.fs @@ -11,6 +11,13 @@ module Persistence = open Proto.Persistence open Proto.Persistence.SnapshotStrategies + type SenderInfo<'Event> = { // Mostly for streaming support + Address: string + Tell: 'Event -> unit + } with static member FromPID (pid: PID) = { Address = pid.Address; Tell = fun e -> pid = SenderInfo<'Event> -> 'State -> int64 -> 'Command -> Async> + let private applyEvent recoverEvent replayEvent persistedEvent state (evt: Event) = match evt with | :? RecoverEvent as e -> @@ -48,19 +55,24 @@ module Persistence = | Started _ -> async { do! persistence.RecoverStateAsync() |> Async.AwaitTask } | _ -> async {()} - let private handler (persistence: Persistence) processCommand state (ctx: IContext) (cmd: 'Command): Async = - let res = processCommand state persistence.Index cmd + let private handler (persistence: Persistence) (processCommand: CommandProcessor<'Command,'Event,'State,'CommandError>) (state: 'State) (ctx: IContext) (cmd: 'Command): Async = async { + let! res = processCommand (SenderInfo<'Event>.FromPID ctx.Sender) state persistence.Index cmd match res with - | Ok evt -> async { do! persistence.PersistEventAsync evt |> Async.AwaitTask - if isNull(ctx.Sender) |> not then ctx.Sender async { e >! ctx.Sender } + | Ok (evtOpt, save) -> match evtOpt with + | Some evt -> if save then do! persistence.PersistEventAsync evt |> Async.AwaitTask + if isNull(ctx.Sender) |> not then ctx.Sender () + | Error e -> e >! ctx.Sender + } + + let simpleProcessCommand = fun _ _ _ cmd -> async { return (Some cmd, true) |> Ok } [] module CommandSourcingAndSnapshotting = let persistDetailed (eventStore: IEventStore) (snapshotStore: ISnapshotStore) - (processCommand: 'State -> int64 -> 'Command -> Result<'Event, 'CommandError>) + (processCommand: CommandProcessor<'Command,'Event,'State,'CommandError>) (recoverEvent: 'State -> int64 -> 'Event -> 'State) (replayEvent: 'State -> int64 -> 'Event -> 'State) (persistedEvent: 'State -> int64 -> 'Event -> 'State) @@ -86,7 +98,7 @@ module Persistence = let persist (provider: IProvider) - (processCommand: 'State -> int64 -> 'Command -> Result<'Event, 'CommandError>) + (processCommand: CommandProcessor<'Command,'Event,'State,'CommandError>) (onEvent: 'State -> int64 -> 'Event -> 'State) (log: string -> unit) (snapshotStrategy: ISnapshotStrategy) @@ -108,7 +120,7 @@ module Persistence = let persistLight (provider: IProvider) - (processCommand: 'State -> int64 -> 'Command -> Result<'Event, 'CommandError>) + (processCommand: CommandProcessor<'Command,'Event,'State,'CommandError>) (onEvent: 'State -> int64 -> 'Event -> 'State) (persistentID: string) (initialState: 'State) @@ -123,7 +135,7 @@ module Persistence = initialState [] - module EventSourcingAndSnapshotting = + module EventSourcingAndSnapshotting = let persistDetailed (eventStore: IEventStore) (snapshotStore: ISnapshotStore) @@ -139,7 +151,7 @@ module Persistence = CommandSourcingAndSnapshotting.persistDetailed eventStore snapshotStore - (fun _ _ cmd -> Ok cmd) + simpleProcessCommand recoverEvent replayEvent persistedEvent @@ -159,7 +171,7 @@ module Persistence = = CommandSourcingAndSnapshotting.persist provider - (fun _ _ cmd -> Ok cmd) + simpleProcessCommand onEvent log snapshotStrategy @@ -174,7 +186,7 @@ module Persistence = = CommandSourcingAndSnapshotting.persistLight provider - (fun _ _ cmd -> Ok cmd) + simpleProcessCommand onEvent persistentID initialState @@ -193,13 +205,13 @@ module Persistence = persistentID, System.Action<_>(applySnapshot recoverSnapshot persistedSnapshot ignore)) - Actor.create3Async (systemHandler persistence) (handler persistence (fun _ _ e -> Ok e) None) + Actor.create3Async (systemHandler persistence) (handler persistence simpleProcessCommand None) [] module CommandSourcing = let persist (eventStore: IEventStore) - (processCommand: 'State -> int64 -> 'Command -> Result<'Event, 'CommandError>) + (processCommand: CommandProcessor<'Command,'Event,'State,'CommandError>) (persistedEvent: 'State -> int64 -> 'Event -> 'State) (persistentID: string) (initialState: 'State) @@ -224,7 +236,7 @@ module Persistence = = CommandSourcing.persist eventStore - (fun _ _ cmd -> Ok cmd) + simpleProcessCommand persistedEvent persistentID initialState @@ -239,7 +251,7 @@ module Persistence = persistentID None - let getEvents<'T> (handler: 'T -> unit) (persistentID: string) (indexStart: int64) (indexEnd: int64) (eventStore: IEventStore) = + let getEvents<'T> (eventStore: IEventStore) (persistentID: string) (indexStart: int64) (indexEnd: int64) (handler: 'T -> unit) = eventStore.GetEventsAsync (persistentID, indexStart, indexEnd, System.Action<_>(fun o -> if not (isNull o) then match o with From a0a2bb35105cc76777aa09e3eeef535222da04a2 Mon Sep 17 00:00:00 2001 From: cotyar Date: Tue, 20 Mar 2018 13:09:41 +0000 Subject: [PATCH 4/7] example04manyactors test. Changed benchmark to use TotalSeconds --- examples/example04manyactors/Program.fs | 2 +- src/Proto.Actor.FSharp/Proto.FSharp.fs | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/examples/example04manyactors/Program.fs b/examples/example04manyactors/Program.fs index c91260f..143e6a5 100644 --- a/examples/example04manyactors/Program.fs +++ b/examples/example04manyactors/Program.fs @@ -22,6 +22,6 @@ let main argv = let endTime = DateTime.Now let duration = (endTime - startTime) printfn "%A" duration - printfn "Messages per second %f" ((float numberOfMessages) / (float duration.Seconds)) + printfn "Messages per second %f" ((float numberOfMessages) / (float duration.TotalSeconds)) Console.ReadLine() |> ignore 0 // return an integer exit code diff --git a/src/Proto.Actor.FSharp/Proto.FSharp.fs b/src/Proto.Actor.FSharp/Proto.FSharp.fs index 565c0a6..a502cf5 100644 --- a/src/Proto.Actor.FSharp/Proto.FSharp.fs +++ b/src/Proto.Actor.FSharp/Proto.FSharp.fs @@ -5,7 +5,8 @@ open System.Threading.Tasks open System module Async = - let inline startAsPlainTask (work : Async) = Task.Factory.StartNew(fun () -> work |> Async.RunSynchronously) + let inline startAsPlainTask (work : Async) = work |> Async.StartAsTask :> Task //Task.Factory.StartNew(fun () -> work |> Async.RunSynchronously) + //let inline startAsPlainTask (work : Async) = Task.Factory.StartNew(fun () -> work |> Async.RunSynchronously) module System = let toFunc<'a> f = Func<'a>(f) @@ -201,3 +202,16 @@ module Pid = let (>!) msg (pid: PID) = tell pid msg let (?) msg (pid: PID) = ask pid msg + + //type PID<'T>(address, id) = inherit PID(address, id) + + //let tell (pid: PID) msg = + // pid.Tell(msg) + + //let ask (pid: PID) msg = + // pid.RequestAsync(msg) |> Async.AwaitTask + + //let (!) msg (pid: PID) = tell pid msg + //let (?) msg (pid: PID) = ask pid msg From 82b1aca4219574cfff5fbf257f894d576f50b77b Mon Sep 17 00:00:00 2001 From: cotyar Date: Tue, 20 Mar 2018 15:08:14 +0000 Subject: [PATCH 5/7] Removed redundant Async.RunSynchronously-s Inlined everything --- src/Proto.Actor.FSharp/Proto.FSharp.fs | 95 ++++++++++---------------- 1 file changed, 36 insertions(+), 59 deletions(-) diff --git a/src/Proto.Actor.FSharp/Proto.FSharp.fs b/src/Proto.Actor.FSharp/Proto.FSharp.fs index a502cf5..20183c0 100644 --- a/src/Proto.Actor.FSharp/Proto.FSharp.fs +++ b/src/Proto.Actor.FSharp/Proto.FSharp.fs @@ -5,8 +5,7 @@ open System.Threading.Tasks open System module Async = - let inline startAsPlainTask (work : Async) = work |> Async.StartAsTask :> Task //Task.Factory.StartNew(fun () -> work |> Async.RunSynchronously) - //let inline startAsPlainTask (work : Async) = Task.Factory.StartNew(fun () -> work |> Async.RunSynchronously) + let inline startAsPlainTask (work : Async) = Async.StartAsTask work :> Task module System = let toFunc<'a> f = Func<'a>(f) @@ -78,78 +77,68 @@ module Core = [] module Actor = - let spawn (props: Props) = Actor.Spawn(props) + let inline spawn (props: Props) = Actor.Spawn(props) - let spawnPrefix prefix (props: Props) = Actor.SpawnPrefix(props, prefix) + let inline spawnPrefix prefix (props: Props) = Actor.SpawnPrefix(props, prefix) - let spawnNamed name (props: Props) = Actor.SpawnNamed(props, name) + let inline spawnNamed name (props: Props) = Actor.SpawnNamed(props, name) - let initProps (producer: unit -> IActor) = + let inline initProps (producer: unit -> IActor) = let producerFunc = System.Func<_>(producer) Actor.FromProducer(producerFunc) - let spawnProps = initProps >> spawn + let inline spawnProps p = p |> initProps |> spawn - let spawnPropsPrefix prefix = initProps >> spawnPrefix prefix + let inline spawnPropsPrefix prefix = initProps >> spawnPrefix prefix - let spawnPropsNamed name = initProps >> spawnNamed name + let inline spawnPropsNamed name = initProps >> spawnNamed name - let withState3Async (systemMessageHandler: IContext -> SystemMessage -> 'State -> Async<'State>) (handler: IContext -> 'Message -> 'State -> Async<'State>) (initialState: 'State) = + let inline withState3Async (systemMessageHandler: IContext -> SystemMessage -> 'State -> Async<'State>) (handler: IContext -> 'Message -> 'State -> Async<'State>) (initialState: 'State) = fun () -> new FSharpActor<'Message, 'State>(systemMessageHandler, handler, initialState) :> IActor - let withState2Async (handler: IContext -> 'Message -> 'State -> Async<'State>) (initialState: 'State) = + let inline withState2Async (handler: IContext -> 'Message -> 'State -> Async<'State>) (initialState: 'State) = withState3Async (fun _ _ s -> async { return s }) handler initialState - let withStateAsync (handler: 'Message -> 'State -> Async<'State>) (initialState: 'State) = + let inline withStateAsync (handler: 'Message -> 'State -> Async<'State>) (initialState: 'State) = withState2Async (fun _ m s -> handler m s) initialState - let create3Async (systemMessageHandler: IContext -> SystemMessage -> Async) (handler: IContext -> 'Message -> Async) = + let inline create3Async (systemMessageHandler: IContext -> SystemMessage -> Async) (handler: IContext -> 'Message -> Async) = withState3Async (fun context message _ -> systemMessageHandler context message) (fun context message _ -> handler context message) () - let create2Async (handler: IContext -> 'Message -> Async) = + let inline create2Async (handler: IContext -> 'Message -> Async) = withState2Async (fun context message _ -> handler context message) () - let createAsync (handler: 'Message -> Async) = + let inline createAsync (handler: 'Message -> Async) = withState2Async (fun _ m _ -> handler m) () - let withState2 (handler: IContext -> 'Message -> 'State -> 'State) (initialState: 'State) = - async { - return withState2Async (fun ctx msg state -> async { return handler ctx msg state }) initialState - } |> Async.RunSynchronously + let inline withState2 (handler: IContext -> 'Message -> 'State -> 'State) (initialState: 'State) = + withState2Async (fun ctx msg state -> async { return handler ctx msg state }) initialState - let withState (handler: 'Message -> 'State -> 'State) (initialState: 'State) = - async { - return withStateAsync (fun msg state -> async { return handler msg state }) initialState - } |> Async.RunSynchronously + let inline withState (handler: 'Message -> 'State -> 'State) (initialState: 'State) = + withStateAsync (fun msg state -> async { return handler msg state }) initialState - let create (handler: 'Message -> unit) = - async { - return createAsync (fun msg -> async { return handler msg }) - } |> Async.RunSynchronously + let inline create (handler: 'Message -> unit) = createAsync (fun msg -> async { return handler msg }) - let create2 (handler: IContext -> 'Message -> unit) = - async { - return create2Async (fun ctx msg -> async { return handler ctx msg }) - } |> Async.RunSynchronously + let inline create2 (handler: IContext -> 'Message -> unit) = create2Async (fun ctx msg -> async { return handler ctx msg }) [] module Props = open System - let newProps() = Props() + let inline newProps() = Props() - let withProducer producer (props: Props) = + let inline withProducer producer (props: Props) = props.WithProducer(producer) - let withDispatcher dispatcher (props: Props) = + let inline withDispatcher dispatcher (props: Props) = props.WithDispatcher(dispatcher) - let withMailbox mailbox (props: Props) = + let inline withMailbox mailbox (props: Props) = props.WithMailbox(mailbox) - let withChildSupervisorStrategy supervisorStrategy (props: Props) = + let inline withChildSupervisorStrategy supervisorStrategy (props: Props) = let strategy = match supervisorStrategy with | DefaultStrategy -> Supervision.DefaultStrategy @@ -169,49 +158,37 @@ module Props = Proto.ExponentialBackoffStrategy(backoffWindow, initialBackoff) :> ISupervisorStrategy props.WithChildSupervisorStrategy(strategy) - let withReceiveMiddleware (middleware: Receive -> Receive) (props: Props) = + let inline withReceiveMiddleware (middleware: Receive -> Receive) (props: Props) = props.WithReceiveMiddleware([|toFunc2(middleware)|]) - let withReceiveMiddlewares (middlewares: (Receive -> Receive) list) (props: Props) = + let inline withReceiveMiddlewares (middlewares: (Receive -> Receive) list) (props: Props) = middlewares |> List.map toFunc2 |> Array.ofList |> (fun arr -> props.WithReceiveMiddleware(arr)) - let withSenderMiddleware (middleware: Sender -> Sender) (props: Props) = + let inline withSenderMiddleware (middleware: Sender -> Sender) (props: Props) = props.WithSenderMiddleware([|toFunc2(middleware)|]) - let withSenderMiddlewares (middlewares: (Sender -> Sender) list) (props: Props) = + let inline withSenderMiddlewares (middlewares: (Sender -> Sender) list) (props: Props) = middlewares |> List.map toFunc2 |> Array.ofList |> (fun arr -> props.WithSenderMiddleware(arr)) - let withSpawner spawner (props: Props) = + let inline withSpawner spawner (props: Props) = props.WithSpawner(spawner) [] module Pid = - let tell (pid: PID) msg = + let inline tell (pid: PID) msg = pid.Tell(msg) - let ask (pid: PID) msg = + let inline ask (pid: PID) msg = pid.RequestAsync(msg) |> Async.AwaitTask - let (!) msg (pid: PID) = tell pid msg - let (?) msg (pid: PID) = ask pid msg + let inline (!) msg (pid: PID) = tell pid msg + let inline (?) msg (pid: PID) = ask pid msg - //type PID<'T>(address, id) = inherit PID(address, id) - - //let tell (pid: PID) msg = - // pid.Tell(msg) - - //let ask (pid: PID) msg = - // pid.RequestAsync(msg) |> Async.AwaitTask - - //let (!) msg (pid: PID) = tell pid msg - //let (?) msg (pid: PID) = ask pid msg From 52fa41c25491469a600b3520eb6c4c2a4ef49bc5 Mon Sep 17 00:00:00 2001 From: cotyar Date: Wed, 21 Mar 2018 11:01:40 +0000 Subject: [PATCH 6/7] Changed message composition --- examples/example04manyactors/Program2.fs | 49 ++++++++++++++ src/Proto.Actor.FSharp/Proto.FSharp.fs | 86 +++++++++++++++--------- 2 files changed, 105 insertions(+), 30 deletions(-) create mode 100644 examples/example04manyactors/Program2.fs diff --git a/examples/example04manyactors/Program2.fs b/examples/example04manyactors/Program2.fs new file mode 100644 index 0000000..32a551d --- /dev/null +++ b/examples/example04manyactors/Program2.fs @@ -0,0 +1,49 @@ +open System +open Proto.FSharp +open Proto + +type Msg = + | Inc of int + | Get + +[] +let main argv = + let mutable state = 0 + let handler (ctx: IContext) msg = + match msg with + | Inc _ -> state <- state + 1 + | Get -> ctx.Sender Actor.spawnProps + + let createAndTell x = + Actor.create (fun msg -> counter Actor.initProps + |> Actor.spawn + + let numberOfMessages = 1000000 + let startTime = DateTime.Now + async { + Seq.init numberOfMessages id + |> Seq.map createAndTell + |> Seq.iteri (fun i pid -> pid Async.Parallel + //|> Async.RunSynchronously + //|> ignore + } |> Async.Start + + async { + let mutable count = -1 + while count < 1000000 do + do! Async.Sleep 100 + let! (c: int) = counter Async.RunSynchronously + + let endTime = DateTime.Now + let duration = (endTime - startTime) + printfn "%A" duration + printfn "Messages per second %f" ((float numberOfMessages) / (float duration.TotalSeconds)) + Console.ReadLine() |> ignore + 0 // return an integer exit code diff --git a/src/Proto.Actor.FSharp/Proto.FSharp.fs b/src/Proto.Actor.FSharp/Proto.FSharp.fs index 20183c0..308697a 100644 --- a/src/Proto.Actor.FSharp/Proto.FSharp.fs +++ b/src/Proto.Actor.FSharp/Proto.FSharp.fs @@ -8,8 +8,8 @@ module Async = let inline startAsPlainTask (work : Async) = Async.StartAsTask work :> Task module System = - let toFunc<'a> f = Func<'a>(f) - let toFunc2<'a, 'b> f = Func<'a, 'b>(f) + let inline toFunc<'a> f = Func<'a>(f) + let inline toFunc2<'a, 'b> f = Func<'a, 'b>(f) [] module Core = @@ -49,43 +49,55 @@ module Core = | OneForOneStrategy of decider:Decider * maxNrOfRetries:int * withinTimeSpan:TimeSpan option | ExponentialBackoffStrategy of backoffWindow:TimeSpan * initialBackoff:TimeSpan - type FSharpActor<'Message, 'State>(systemMessageHandler: IContext -> SystemMessage -> 'State -> Async<'State>, handler: IContext -> 'Message -> 'State -> Async<'State>, initialState: 'State) = + type FSharp3AsyncActor<'Message, 'State>(handler: IContext -> obj -> 'State -> Async<'State>, initialState: 'State) = let mutable state = initialState interface IActor with member this.ReceiveAsync(context: IContext) = async { - match context.Message with - | IsSystemMessage msg -> - try - let! state' = systemMessageHandler context msg state - state <- state' - with - | x -> - printfn "Failed to execute actor: %A" x - raise x - | :? 'Message as msg -> - try - let! state' = handler context msg state - state <- state' - with - | x -> - printfn "Failed to execute actor: %A" x - raise x - | _ -> () + try + let! state' = handler context context.Message state + state <- state' + with + | x -> + printfn "Failed to execute actor: %A" x + raise x } |> Async.startAsPlainTask + type FSharp3Actor<'Message, 'State>(handler: IContext -> obj -> 'State -> 'State, initialState: 'State) = + let mutable state = initialState + interface IActor with + member this.ReceiveAsync(context: IContext) = + async { + try + let state' = handler context context.Message state + state <- state' + with + | x -> + printfn "Failed to execute actor: %A" x + raise x + } |> Async.startAsPlainTask [] module Actor = + let inline private composeAsyncHandlers (systemMessageHandler: IContext -> SystemMessage -> 'State -> Async<'State>) (handler: IContext -> 'Message -> 'State -> Async<'State>) = + fun context (msg: obj) state -> match msg with + | IsSystemMessage msg -> systemMessageHandler context msg state + | :? 'Message as msg -> handler context msg state + | _ -> async { return state } + + let inline private composeHandlers (systemMessageHandler: IContext -> SystemMessage -> 'State -> 'State) (handler: IContext -> 'Message -> 'State -> 'State) = + fun context (msg: obj) state -> match msg with + | IsSystemMessage msg -> systemMessageHandler context msg state + | :? 'Message as msg -> handler context msg state + | _ -> state + let inline spawn (props: Props) = Actor.Spawn(props) let inline spawnPrefix prefix (props: Props) = Actor.SpawnPrefix(props, prefix) let inline spawnNamed name (props: Props) = Actor.SpawnNamed(props, name) - let inline initProps (producer: unit -> IActor) = - let producerFunc = System.Func<_>(producer) - Actor.FromProducer(producerFunc) + let inline initProps (producer: unit -> IActor) = Actor.FromProducer(System.Func<_>(producer)) let inline spawnProps p = p |> initProps |> spawn @@ -95,8 +107,11 @@ module Actor = let inline withState3Async (systemMessageHandler: IContext -> SystemMessage -> 'State -> Async<'State>) (handler: IContext -> 'Message -> 'State -> Async<'State>) (initialState: 'State) = - fun () -> new FSharpActor<'Message, 'State>(systemMessageHandler, handler, initialState) :> IActor + fun () -> new FSharp3AsyncActor<'Message, 'State>((composeAsyncHandlers systemMessageHandler handler), initialState) :> IActor + let inline withObjState2Async (handler: IContext -> obj -> 'State -> Async<'State>) (initialState: 'State) = // TODO: decide on the name and create corresponding create()s + withState3Async handler handler initialState + let inline withState2Async (handler: IContext -> 'Message -> 'State -> Async<'State>) (initialState: 'State) = withState3Async (fun _ _ s -> async { return s }) handler initialState @@ -112,15 +127,26 @@ module Actor = let inline createAsync (handler: 'Message -> Async) = withState2Async (fun _ m _ -> handler m) () - let inline withState2 (handler: IContext -> 'Message -> 'State -> 'State) (initialState: 'State) = - withState2Async (fun ctx msg state -> async { return handler ctx msg state }) initialState + let inline withState3 (systemMessageHandler: IContext -> SystemMessage -> 'State -> 'State) (handler: IContext -> 'Message -> 'State -> 'State) (initialState: 'State) = + fun () -> new FSharp3Actor<'Message, 'State>((composeHandlers systemMessageHandler handler), initialState) :> IActor + + let inline withState2 (handler: IContext -> 'Message -> 'State -> 'State) (initialState: 'State) = + withState3 (fun _ _ s -> s) handler initialState + + let inline withObjState2 (handler: IContext -> obj -> 'State -> 'State) (initialState: 'State) = // TODO: decide on the name and create corresponding create()s + withState3 handler handler initialState let inline withState (handler: 'Message -> 'State -> 'State) (initialState: 'State) = - withStateAsync (fun msg state -> async { return handler msg state }) initialState + withState2 (fun _ m s -> handler m s) initialState + + let inline create3 (systemMessageHandler: IContext -> SystemMessage -> unit) (handler: IContext -> 'Message -> unit) = + withState3 (fun context message _ -> systemMessageHandler context message) (fun context message _ -> handler context message) () - let inline create (handler: 'Message -> unit) = createAsync (fun msg -> async { return handler msg }) + let inline create2 (handler: IContext -> 'Message -> unit) = + withState2 (fun context message _ -> handler context message) () - let inline create2 (handler: IContext -> 'Message -> unit) = create2Async (fun ctx msg -> async { return handler ctx msg }) + let inline create (handler: 'Message -> unit) = + withState2 (fun _ m _ -> handler m) () [] From fd0c25ffd518a198e644560394ba6d4f17c460c6 Mon Sep 17 00:00:00 2001 From: cotyar Date: Thu, 22 Mar 2018 14:17:12 +0000 Subject: [PATCH 7/7] Bug with unhandled SystemMessages fixed Concept of Effects added Some optimizations done --- src/Proto.Actor.FSharp/Proto.FSharp.fs | 84 +++++++++++++++++--------- 1 file changed, 54 insertions(+), 30 deletions(-) diff --git a/src/Proto.Actor.FSharp/Proto.FSharp.fs b/src/Proto.Actor.FSharp/Proto.FSharp.fs index 308697a..df893bb 100644 --- a/src/Proto.Actor.FSharp/Proto.FSharp.fs +++ b/src/Proto.Actor.FSharp/Proto.FSharp.fs @@ -26,7 +26,7 @@ module Core = | ReceiveTimeout of ReceiveTimeout | Continuation of Continuation - let (|IsSystemMessage|_|) (msg:obj) = + let inline (|IsSystemMessage|_|) (msg: obj) = match msg with | :? AutoReceiveMessage as m -> Some(AutoReceiveMessage m) | :? Terminated as m -> Some(Terminated m) @@ -49,28 +49,70 @@ module Core = | OneForOneStrategy of decider:Decider * maxNrOfRetries:int * withinTimeSpan:TimeSpan option | ExponentialBackoffStrategy of backoffWindow:TimeSpan * initialBackoff:TimeSpan - type FSharp3AsyncActor<'Message, 'State>(handler: IContext -> obj -> 'State -> Async<'State>, initialState: 'State) = + type Effect<'State> = obj -> (IContext -> 'State -> 'State) option + type AsyncEffect<'State> = obj -> (IContext -> 'State -> Async<'State>) option + + let inline (<|>) (e1: Effect<'State>) (e2: Effect<'State>) = + fun o -> e1 o |> Option.orElse (e2 o) + + let inline (<||>) (e1: AsyncEffect<'State>) (e2: AsyncEffect<'State>) = + fun o -> e1 o |> Option.orElse (e2 o) + + let inline (<&>) (e1: Effect<'State>) (e2: Effect<'State>) = + fun (o: obj) -> + match (e1 o), (e2 o) with + | Some f1, Some f2 -> Some <| fun ctx state -> state |> f1 ctx |> f2 ctx + | Some f1, None -> Some f1 + | None, Some f2 -> Some f2 + | None, None -> None + + let inline (<&&>) (e1: AsyncEffect<'State>) (e2: AsyncEffect<'State>) = + fun (o: obj) -> + match (e1 o), (e2 o) with + | Some f1, Some f2 -> Some <| fun ctx state -> async { let! state' = state |> f1 ctx + return! state' |> f2 ctx } + | Some f1, None -> Some f1 + | None, Some f2 -> Some f2 + | None, None -> None + + let inline typedEffect (handler: IContext -> 'Message -> 'State -> 'T) = + fun (o: obj) -> match o with + | :? 'Message as msg -> Some <| fun ctx state -> handler ctx msg state + | _ -> None + + let inline systemEffect (handler: IContext -> SystemMessage -> 'State -> 'T) = + fun (o: obj) -> match o with + | IsSystemMessage msg -> Some <| fun ctx state -> handler ctx msg state + | _ -> None + + type FSharpAsyncActor<'State>(handler: AsyncEffect<'State>, initialState: 'State) = let mutable state = initialState interface IActor with member this.ReceiveAsync(context: IContext) = async { try - let! state' = handler context context.Message state - state <- state' + let applied = handler context.Message + match applied with + | Some f -> let! state' = f context state + state <- state' + | None -> () with | x -> printfn "Failed to execute actor: %A" x raise x } |> Async.startAsPlainTask - type FSharp3Actor<'Message, 'State>(handler: IContext -> obj -> 'State -> 'State, initialState: 'State) = + type FSharpActor<'State>(handler: Effect<'State>, initialState: 'State) = let mutable state = initialState interface IActor with member this.ReceiveAsync(context: IContext) = async { try - let state' = handler context context.Message state - state <- state' + let applied = handler context.Message + match applied with + | Some f -> let state' = f context state + state <- state' + | None -> () with | x -> printfn "Failed to execute actor: %A" x @@ -79,18 +121,6 @@ module Core = [] module Actor = - let inline private composeAsyncHandlers (systemMessageHandler: IContext -> SystemMessage -> 'State -> Async<'State>) (handler: IContext -> 'Message -> 'State -> Async<'State>) = - fun context (msg: obj) state -> match msg with - | IsSystemMessage msg -> systemMessageHandler context msg state - | :? 'Message as msg -> handler context msg state - | _ -> async { return state } - - let inline private composeHandlers (systemMessageHandler: IContext -> SystemMessage -> 'State -> 'State) (handler: IContext -> 'Message -> 'State -> 'State) = - fun context (msg: obj) state -> match msg with - | IsSystemMessage msg -> systemMessageHandler context msg state - | :? 'Message as msg -> handler context msg state - | _ -> state - let inline spawn (props: Props) = Actor.Spawn(props) let inline spawnPrefix prefix (props: Props) = Actor.SpawnPrefix(props, prefix) @@ -107,13 +137,10 @@ module Actor = let inline withState3Async (systemMessageHandler: IContext -> SystemMessage -> 'State -> Async<'State>) (handler: IContext -> 'Message -> 'State -> Async<'State>) (initialState: 'State) = - fun () -> new FSharp3AsyncActor<'Message, 'State>((composeAsyncHandlers systemMessageHandler handler), initialState) :> IActor - - let inline withObjState2Async (handler: IContext -> obj -> 'State -> Async<'State>) (initialState: 'State) = // TODO: decide on the name and create corresponding create()s - withState3Async handler handler initialState - + fun () -> new FSharpAsyncActor<'State>(systemEffect(systemMessageHandler) <&&> typedEffect(handler), initialState) :> IActor + let inline withState2Async (handler: IContext -> 'Message -> 'State -> Async<'State>) (initialState: 'State) = - withState3Async (fun _ _ s -> async { return s }) handler initialState + fun () -> new FSharpAsyncActor<'State>(typedEffect handler, initialState) :> IActor let inline withStateAsync (handler: 'Message -> 'State -> Async<'State>) (initialState: 'State) = withState2Async (fun _ m s -> handler m s) initialState @@ -128,13 +155,10 @@ module Actor = withState2Async (fun _ m _ -> handler m) () let inline withState3 (systemMessageHandler: IContext -> SystemMessage -> 'State -> 'State) (handler: IContext -> 'Message -> 'State -> 'State) (initialState: 'State) = - fun () -> new FSharp3Actor<'Message, 'State>((composeHandlers systemMessageHandler handler), initialState) :> IActor + fun () -> new FSharpActor<'State>(systemEffect(systemMessageHandler) <&> typedEffect(handler), initialState) :> IActor let inline withState2 (handler: IContext -> 'Message -> 'State -> 'State) (initialState: 'State) = - withState3 (fun _ _ s -> s) handler initialState - - let inline withObjState2 (handler: IContext -> obj -> 'State -> 'State) (initialState: 'State) = // TODO: decide on the name and create corresponding create()s - withState3 handler handler initialState + fun () -> new FSharpActor<'State>(typedEffect handler, initialState) :> IActor let inline withState (handler: 'Message -> 'State -> 'State) (initialState: 'State) = withState2 (fun _ m s -> handler m s) initialState