F# XUnit test deadlocks when initializer has dependency - f#

I am having problems with a test in a netcoreapp2.2 .net core test project.
Before the tests starts I need to fetch some data that will be shared between the tests.
However, when running the following test from command line it will hang.
Executing the test like this:
dotnet test --filter "Test async initialization"
The faulty code looks like this:
let c = new HttpClient (BaseAddress = (Uri "https://swapi.co/api/people/1/"))
let luke =
async {
return! c.GetStringAsync "" |> Async.AwaitTask
} |> Async.RunSynchronously
[<Fact>]
let ``Test async initialization`` () =
Assert.NotNull(luke)
While if I put the creation of the HttpClient inside the luke fetcher like this it works:
let luke =
let c = new HttpClient (BaseAddress = (Uri "https://swapi.co/api/people/1/"))
async {
return! c.GetStringAsync "" |> Async.AwaitTask
} |> Async.RunSynchronously
[<Fact>]
let ``Test async initialization`` () =
Assert.NotNull(luke)
This means I can't share the same HttpClient between different fetchers.
Anyone knows what is going on, and how to share the same client between multiple functions?

The problem is caused because the "initialization" code isn't really initialization code. Those are just two static fields that will be evaluated only when requested. If you debug the unit test you'll see that c and luke execute only when execution reaches the line
Assert.NotNull(luke)
If you use a decompiler like JustDecompile you'll see that the module's code is placed in a static class called Tests$ whose static constructor initializes its own c and luke properties. Test async initialization is placed in a Tests class with its own c and luke properties that delegate to the Tests$ class.
Long story sort, none of that "initialization" code runs until the value of luke is requested. I don't know why that ends up blocking the test, most likely there's a conflict with the test runner. It's enough that the initialization code doesn't run at initialization.
To make the initialization code run when it should, a "classic" test type can be used :
namespace MyTests
open System
open Xunit
open System.Net.Http
open Xunit.Abstractions
type Tests() =
static let c = new HttpClient (BaseAddress = (Uri "https://swapi.co/api/people/1/"))
static let luke =
async {
return! c.GetStringAsync "" |> Async.AwaitTask
} |> Async.RunSynchronously
static do
//Pity we can't actually print here
printfn "Even more initialization!"
[<Fact>]
let ``Test async initialization`` () =
Assert.NotNull(luke)
The static bindings in this case are executed before any of the tests, as they should, and the code doesn't block. This initialization will happen only once.
To capture output the test class constructor should accept an ITestOutputHelper parameter. That's easy to do now that we have a test class :
type Tests(output:ITestOutputHelper) =
...
[<Fact>]
let ``Test async initialization`` () =
Assert.NotNull(luke)
output.WriteLine "It worked!"
Per-test initialization should go in a do block :
type Tests(output:ITestOutputHelper) =
do
output.WriteLine "This prints before each test"

Related

Returning Task<bool> in F#, what is the syntax?

I need to write a function that will return a Task in F#.
The closest I came to is:
let Test : Async<bool> =
async {
printfn "3"
true
}
but.. that doesn't work; the compiler says I'm giving an Async instead of an Async.
Am I correct to understand that there is no Task object and the return type should be defined as Async?
What is the correct syntax for this?
F# doesn't have a computation expression for the Task construct built-in by default.
However if you want to use it, you can (thanks to rspeele). You'll have to add this as a nuget package: https://github.com/rspeele/TaskBuilder.fs
Then you can use it like this:
open FSharp.Control.Tasks.V2
let taskMethod : Task<bool> =
task {
printfn "3"
return true
}
If you want to stick with the built-in Async approach you can do something like this:
open System.Threading.Tasks
let asyncMethod : Async<bool> =
async {
printfn "bob"
return true
}
let taskMethod : Task<bool> =
asyncMethod |> Async.StartAsTask

Error F# - c# async calls : converting Threading.Tasks.Task<MyType> to Async<'a>

When I try to call an async method that is in C# library from my F# code.
I get the following compilation error.
This expression was expected to have type Async<'a> but here has type Threading.Thread.Tasks.Task
SendMessageAsync is in C# library and returns Threading.Thread.Tasks.Task<MyType>
let sendEmailAsync message =
async {
let! response = client.SendMessageAsync(message)
return response
}
For converting between Task<'T> and Async<'T> there is a built-in Async.AwaitTask function.
To convert between a plain Task and Async<unit> you can create a helper function:
type Async with
member this.AwaitPlainTask (task : Task) =
task.ContinueWith(fun t -> ())
|> Async.AwaitTask
Then you can call it like this:
let sendEmailAsync message =
async {
let! response = Async.AwaitPlainTask <|client.SendMessageAsync(message)
return response
}
Of course, in this case, the response can't be anything other than (), so you might as well just write:
let sendEmailAsync message = Async.AwaitPlainTask <|client.SendMessageAsync(message)

How can I define an owin middleware class in F#?

I am trying to create the example class below (taken from here) in F#.
public class LoggingMiddleware
{
private AppFunc next;
public LoggingMiddleware(Func<IDictionary<string, object>, Task> next)
{
this.next = next;
}
public async Task Invoke(IDictionary<string, object> environment)
{
Console.WriteLine("Begin Request");
await next.Invoke(environment);
Console.WriteLine("End Request");
}
}
However, I'm struggling both with converting between the typical .NET types and the typical F# types and using the F# async workflows to achieve what is happening with the C# await.
The biggest (current) issue with F# async workflows and .Net task is that there is no direct analogy to a Task that has no return type.
From this question, I'll use this function binding to await Tasks with no return value:
let awaitTask = Async.AwaitIAsyncResult >> Async.Ignore
With that, you can directly translate your example class to:
type FSharpMiddleware(next: Func<IDictionary<string,obj>, Task>) =
member this.Invoke (environment: IDictionary<string,obj>) : Task =
async {
printfn "Begin Request"
do!
awaitTask <| next.Invoke environment
printfn "End Request"
} |> Async.StartAsTask :> Task

Awaiting an IAsyncOperation in F#

I have the following code in F#:
let CreateSampleDataFromJson<'T>(path) =
let uri = new Uri(path)
async {
let file = StorageFile.GetFileFromApplicationUriAsync(uri)
let jsonText = FileIO.ReadTextAsync(file)
return JsonObject<'T>.Parse(jsonText)
}
The problem I'm having is that file is an IAsyncOperation<StorageFile> and not a StorageFile as ReadTextAsync expects.
In C# you can do something similar to this:
var file = await StorageFile.GetFileFromApplicationUriAsync(uri)
i.e.
public async Task<T> CreateSampleDataFromUrl<T>(string path)
{
var uri = new Uri(path);
var file = await StorageFile.GetFileFromApplicationUriAsync(uri);
var jsonText = await FileIO.ReadTextAsync(file);
return JsonObject<T>.Parse(jsonText);
}
The problem is that I don't know how to await an IAsyncOperation in F#. The usual let! doesn't work. i.e. the following fails to compile:
async {
let! file = StorageFile.GetFileFromApplicationUriAsync(uri)
With the compiler error:
error FS0001: This expression was expected to have type Async<'a> but here has type IAsyncOperation<StorageFile>
I found a document that said there's an AsTask() extension method defined in the System.WindowsRuntimeSystemExtensions class which I can use as follows:
let! file = StorageFile.GetFileFromApplicationUriAsync(uri).AsTask() |> Async.AwaitTask
Is there a standard way of doing this or something available in an F# library somewhere that makes this a bit nicer?
Your solution seems fine by me. If you're looking for a nicer syntax, how about rolling it into a function like this (without the possibly gratuitous type annotations):
let await<'a> (op: IAsyncOperation<'a>) : Async<'a> =
op.AsTask() |> Async.AwaitTask
This will give you the almost exact same syntax you'd see in c#:
async {
let! file = await <| StorageFile.GetFileFromApplicationUriAsync(uri)
...
}
The compiler errors you were getting with your previous approaches are to be expected. All async workflow cares about is the F#-specific Async type. This type gives you a way to interop with the rest of .NET world through Tasks, but that's it. IAsyncOperation is from a 'different part of the world', I wouldn't expect F# core libraries to support it anytime soon.

Implementing Actor Model in C# 5 / Async CTP

In an Actor Model, the actors have some sort of message loop where messages are matched using e.g. pattern matching (depending on language ofc)
e.g. pseudo F#
let message_loop() =
let! message = receive_message() //sync receive message
match message with
| Foo(a,b) -> DoStuff(a,b)
| Bar(c) -> DoOtherStuff(c)
| _ -> error ("unknown message")
message_loop()
So pretty much, a message signature is matched and associated with some action to perform on the message content.
Is there any conceptual difference between this and calling actual methods?
e.g. if I would do the following in C# 5:
class MyActor
{
//message signature Foo(a,b)
public void Foo(int a,string b)
{
Act( () => DoStuff(a,b) );
}
//message signature Bar(c)
public void Bar(int c)
{
Act( () => DoOtherStuff(c));
}
// the rest is infrasturcture code, can be refactored into an Actor Base class
//this emulates the sync behavior of the above actor
//each action is pushed onto a queue
//and then processed synchronously by the message handler
private void Act(Action action)
{
actions.Post(action);
}
private BufferBlock<Action> actions = new BufferBlock<Action>();
//this needs max degreee of parallellism = 1
private ActionBlock<Action> messageHandler = new ....
}
This way, invoking a method on MyActor will result in an async message posted onto a message queue which only handles a single kind of message; an Action.
However, the behavor associated with the message is contained in the message itself (posted from the public method)
So would this be a considered a clean way to do actors in C# 5 / Async CTP?
The benefits would be that messages are simply defined as normal messages instead of creating awkward message DTO like classes.
So would this be enough to make it work?
There is a slight difference between Task-based asynchrony and MailboxProcessor. Mailbox processor will always end up in the same thread, similar to Winforms message loop. Task keeps a SynchronizationContext. This means the same behavior for Winforms and WPF, but you could end up on a different thread when working with a thread-pool.
Otherwise, and conceptually, looks right to me.
I would say your approach is reasonable.
It is actually a good practice to encapsulate an F# agent behind an interface, itself dispatching messages to the agent:
type IPrintText =
abstract Stop : unit -> unit
abstract Print : string -> unit
module Printer =
type private Message =
| PrintText of string
| Stop
let Start () =
let agent =
MailboxProcessor.Start (fun inbox ->
let rec loop () = async {
let! msg = inbox.Receive()
return!
match msg with
| PrintText text ->
printfn "%s" text
loop ()
| Stop -> async.Zero()
}
loop ())
{ new IPrintText with
member x.Stop () = agent.Post Stop
member x.Print text = agent.Post <| PrintText text }
let agent = Printer.Start ()
agent.Print "Test"
agent.Stop ()

Resources