Edit

Get started with Azure Queue Storage using F#

Azure Queue Storage provides cloud messaging between application components. In designing applications for scale, application components are often decoupled, so that they can scale independently. Queue storage delivers asynchronous messaging for communication between application components, whether they are running in the cloud, on the desktop, on an on-premises server, or on a mobile device. Queue storage also supports managing asynchronous tasks and building process work flows.

About this tutorial

This tutorial shows how to write F# code for some common tasks using Azure Queue Storage. Tasks covered include creating and deleting queues and adding, reading, and deleting queue messages.

For a conceptual overview of queue storage, see the .NET guide for queue storage. For ease, these tutorials use connection strings to authenticate with Azure. For optimal security, you should use Microsoft Entra ID with managed identities.

Prerequisites

To use this guide, you must first create an Azure storage account. You'll also need your storage access key for this account.

Create an F# script and start F# interactive

The samples in this article can be used in either an F# application or an F# script. To create an F# script, create a file with the .fsx extension, for example queues.fsx, in your F# development environment.

How to execute scripts

F# Interactive, dotnet fsi, can be launched interactively, or it can be launched from the command line to run a script. The command-line syntax is

> dotnet fsi [options] [ script-file [arguments] ]

Add packages in a script

Next, use #r nuget:package name to install the Azure.Storage.Queues package and open namespaces.Such as

> #r "nuget: Azure.Storage.Queues"
open Azure.Storage.Queues

Add namespace declarations

Add the following open statements to the top of the queues.fsx file:

open Azure.Storage.Queues // Namespace for Queue storage types
open System
open System.Text

Get your connection string

You'll need an Azure Storage connection string for this tutorial. For more information about connection strings, see Configure Storage Connection Strings.

For the tutorial, you'll enter your connection string in your script, like this:

let storageConnString = "..." // fill this in from your storage account

Create the queue service client

The QueueClient class enables you to retrieve queues stored in Queue storage. Here's one way to create the client:

let queueClient = QueueClient(storageConnString, "myqueue")

Now you are ready to write code that reads data from and writes data to Queue storage.

Create a queue

This example shows how to create a queue if it doesn't already exist:

queueClient.CreateIfNotExists()

Insert a message into a queue

To insert a message into an existing queue, first create a new Message. Next, call the SendMessage method. A Message can be created from either a string (in UTF-8 format) or a byte array, like this:

queueClient.SendMessage("Hello, World") // Insert a String message into a queue
queueClient.SendMessage(BinaryData.FromBytes(Encoding.UTF8.GetBytes("Hello, World"))) // Insert a BinaryData message into a queue

Peek at the next message

You can peek at the message in the front of a queue, without removing it from the queue, by calling the PeekMessage method.

let peekedMessage = queueClient.PeekMessage()
let messageContents = peekedMessage.Value.Body.ToString()

Get the next message for processing

You can retrieve the message at the front of a queue for processing by calling the ReceiveMessage method.

let updateMessage = queueClient.ReceiveMessage().Value

You later indicate successful processing of the message by using DeleteMessage.

Change the contents of a queued message

You can change the contents of a retrieved message in-place in the queue. If the message represents a work task, you could use this feature to update the status of the work task. The following code updates the queue message with new contents, and sets the visibility timeout to extend another 60 seconds. This saves the state of work associated with the message, and gives the client another minute to continue working on the message. You could use this technique to track multi-step workflows on queue messages, without having to start over from the beginning if a processing step fails due to hardware or software failure. Typically, you would keep a retry count as well, and if the message is retried more than some number of times, you would delete it. This protects against a message that triggers an application error each time it is processed.

queueClient.UpdateMessage(
    updateMessage.MessageId,
    updateMessage.PopReceipt,
    "Updated contents.",
    TimeSpan.FromSeconds(60.0))

De-queue the next message

Your code de-queues a message from a queue in two steps. When you call ReceiveMessage, you get the next message in a queue. A message returned from ReceiveMessage becomes invisible to any other code reading messages from this queue. By default, this message stays invisible for 30 seconds. To finish removing the message from the queue, you must also call DeleteMessage. This two-step process of removing a message assures that if your code fails to process a message due to hardware or software failure, another instance of your code can get the same message and try again. Your code calls DeleteMessage right after the message has been processed. All of the Queue methods we've shown so far have Async alternatives.

let deleteMessage = queueClient.ReceiveMessage().Value
queueClient.DeleteMessage(deleteMessage.MessageId, deleteMessage.PopReceipt)

Use Async workflows with common Queue storage APIs

This example shows how to use an async workflow with common Queue storage APIs.

async {
    let! exists = queueClient.CreateIfNotExistsAsync() |> Async.AwaitTask

    let! delAsyncMessage = queueClient.ReceiveMessageAsync() |> Async.AwaitTask

    // ... process the message here ...

    // Now indicate successful processing:
    queueClient.DeleteMessageAsync(delAsyncMessage.Value.MessageId, delAsyncMessage.Value.PopReceipt) |> Async.AwaitTask
}

Additional options for de-queuing messages

There are two ways you can customize message retrieval from a queue. First, you can get a batch of messages (up to 32). Second, you can set a longer or shorter invisibility timeout, allowing your code more or less time to fully process each message. The following code example uses ReceiveMessages to get 20 messages in one call and then processes each message. It also sets the invisibility timeout to five minutes for each message. The 5 minutes starts for all messages at the same time, so after 5 minutes have passed since the call to ReceiveMessages, any messages that have not been deleted will become visible again.

for dequeueMessage in queueClient.ReceiveMessages(20, Nullable(TimeSpan.FromMinutes(5.))).Value do
        // Process the message here.
        queueClient.DeleteMessage(dequeueMessage.MessageId, dequeueMessage.PopReceipt)

Get the queue length

You can get an estimate of the number of messages in a queue. The GetProperties method asks the Queue service to retrieve the queue attributes, including the message count. The ApproximateMessagesCount property returns the last value retrieved by the GetProperties method.

let properties = queueClient.GetProperties().Value
let count = properties.ApproximateMessagesCount

Delete a queue

To delete a queue and all the messages contained in it, call the Delete method on the queue object.

queueClient.DeleteIfExists()

Note

If you're migrating from the old libraries, they Base64-encoded messages by default, but the new libraries don't because it's more performant. For information on how to set up encoding, see MessageEncoding.

See also