Last active
December 23, 2015 08:04
-
-
Save jtmueller/15e5c8dafbf5bada808b to your computer and use it in GitHub Desktop.
This file contains hidden or 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
namespace Akka.FSharp | |
open System | |
/// The result of an Akka Ask operation, either a value or an exception. | |
type AskResult<'TResult> = | |
| Ok of result: 'TResult | |
| Err of exn | |
with | |
/// Retrieves the value on success, throws an exception if there was an error. | |
member x.Value = | |
match x with | |
| Ok result -> result | |
| Err err -> | |
raise <| InvalidOperationException("Accessed the Value of an AskResult in an error state.", err) | |
[<AutoOpen>] | |
module AkkaExtensions = | |
open System.Threading.Tasks | |
open Akka.Actor | |
open Akka.FSharp | |
let private taskOpts = TaskContinuationOptions.AttachedToParent ||| TaskContinuationOptions.ExecuteSynchronously | |
let private tryCast<'TResult> (t:Task<obj>) : AskResult<'TResult> = | |
if t.IsFaulted then Err t.Exception | |
else | |
try | |
match t.Result with | |
| :? 'TResult as res -> Ok res | |
| :? AskResult<'TResult> as res -> res | |
| :? Status.Failure as fail -> Err fail.Cause | |
| :? exn as ex -> Err ex | |
| other -> | |
let msg = sprintf "Ask expected type %s but received type %s: %A" (typeof<'TResult>.FullName) (other.GetType().FullName) other | |
Err(InvalidCastException msg) | |
with ex -> | |
Err ex | |
type ICanTell with | |
/// Ask overload that returns an AskResult discriminated union instead of throwing an exception. | |
member x.Ask<'TResult>(msg:obj, ?timeout:TimeSpan) = | |
let timeout = match timeout with Some t -> Nullable(t) | None -> Nullable() | |
x.Ask(msg, timeout).ContinueWith(tryCast<'TResult>, taskOpts) | |
|> Async.AwaitTask | |
/// Bidirectional send operator. Sends a message object directly to actor | |
/// tracked by actorRef and awaits for response send back from corresponding actor. | |
/// Returns an AskResult discriminated union instead of throwing an exception. | |
let (<?) (tell: #ICanTell) (msg: obj) : Async<AskResult<'TResult>> = | |
tell.Ask<'TResult>(msg) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment