Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Async Await in F#

I am rewriting some of the C# in this lab to F#: https://github.com/Microsoft/TechnicalCommunityContent/tree/master/IoT/Azure%20Stream%20Analytics/Session%202%20-%20Hands%20On

I am on Exercise 6, #17 - creating the SimpleEventProcessor type.
I want to implement the CloseAsync method

C#

async Task IEventProcessor.CloseAsync(PartitionContext context, CloseReason reason)
    {
        Debug.WriteLine("Processor Shutting Down. Partition '{0}', Reason: '{1}'.", context.Lease.PartitionId, reason);
        if (reason == CloseReason.Shutdown)
        {
            await context.CheckpointAsync();
        }
    }

and I started like this:

member this.CloseAsync(context, reason) = 
    Debug.WriteLine("Processor Shutting Down. Partition '{0}', Reason: '{1}'.", context.Lease.PartitionId, reason)
    match reason with 
    | CloseReason.Shutdown -> await context.CheckpointAsync()
    | _ -> ()

but I have 2 questions:

  1. How do I return await in F# world?
  2. How do I return the NOT case -> C# just ignore that possibility.
like image 293
Jamie Dixon Avatar asked Mar 09 '23 00:03

Jamie Dixon


1 Answers

  1. If the value has type Async<'T>, you can just return it without any keyword. If it has type Task or Task<'T>, you can do |> Async.AwaitTask.

  2. You can return async { return () }.

So you get this:

member this.CloseAsync(context, reason) = 
    Debug.WriteLine("Processor Shutting Down. Partition '{0}', Reason: '{1}'.", context.Lease.PartitionId, reason)
    match reason with 
    | CloseReason.Shutdown -> context.CheckpointAsync() |> Async.AwaitTask
    | _ -> async { return () }

Another possibility is to put the whole block in an async workflow, and use return! for 1 and return for 2:

member this.CloseAsync(context, reason) = 
    async {
        Debug.WriteLine("Processor Shutting Down. Partition '{0}', Reason: '{1}'.", context.Lease.PartitionId, reason)
        match reason with 
        | CloseReason.Shutdown -> return! context.CheckpointAsync() |> Async.AwaitTask
        | _ -> return ()
    }

In fact, using an async workflow allows you to drop the () case similarly to C#:

member this.CloseAsync(context, reason) = 
    async {
        Debug.WriteLine("Processor Shutting Down. Partition '{0}', Reason: '{1}'.", context.Lease.PartitionId, reason)
        if reason = CloseReason.Shutdown then
            return! context.CheckpointAsync() |> Async.AwaitTask
    }
like image 143
Tarmil Avatar answered Mar 16 '23 14:03

Tarmil