Setting the VisibilityTimeout for a Message added to an Azure Queue via Azure Function Output Binding
Asked Answered
S

1

8

I have a TimerTrigger function and the Output binding is a Azure Queue.

The idea is that every 10 minutes the timer will run, it will look at a view in my database and iterate through any rows returned adding them to the queue as messages.

Below is my sample TimerTrigger. It worked fine adding messages to the Queue.

However in my real world scenario some of the rows will require immediate execution while others will have a delay of some minutes (varies per row). I plan on handling the delay by using the VisibilityTimeout for the message.

Unfortunately the binding via a string wouldn't let me set the value. CloudQueueMessage.VisiblityTimeout (used below) is readonly.

#r "Microsoft.WindowsAzure.Storage"

using System;
using Microsoft.WindowsAzure.Storage.Queue;

public static void Run(TimerInfo myTimer,  ICollector<CloudQueueMessage> outputQueueItem, TraceWriter log)
{
    log.Info($"C# Timer trigger function executed at: {DateTime.Now}");    


    //- Add a message to be processed now.
    CloudQueueMessage msg = new CloudQueueMessage("Now");
    outputQueueItem.Add(msg);

    //- Add a message to be processed later.
    //- this code below won't work because NextVisibleTime is readonly.
    //- is there some way to set the VisibilityTimeout property before queueing?
    msg = new CloudQueueMessage("Later");
    DateTime otherDate = DateTime.Now.AddMinutes(3);

    msg.NextVisibleTime = otherDate;
    outputQueueItem.Add(msg);

}   

Is there any way to have the binding add messages to the queue and let me set the VisibilityTimeout message by message as appropriate?

Sorilda answered 4/3, 2017 at 3:17 Comment(1)
Found the following at Sound Code. "Unfortunately, the built-in Azure Functions Storage Queue’s output binding only gives us access to the CloudQueueMessage which doesn’t let us schedule a time. So I opted to simply write the code myself to connect to the queue and send it with a delay." I'll rewrite using the method proposed in the article and post back a sample here.Sorilda
S
9

Azure Functions Storage Queue’s output binding only gives us access to the CloudQueueMessage which doesn’t let us set the VisibilityTimeout for a message.

I rewrote my code to connect to the Azure Storage Queue and post the messages onto the queue manually rather than through Azure Function output binding.

See below . . .

#r "Microsoft.WindowsAzure.Storage" 

using System;
using System.Configuration;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Queue;

public static void Run(TimerInfo myTimer, TraceWriter log)
{    
    log.Info($"Queue Notifications: {DateTime.Now}, {myTimer.Schedule}, {myTimer.ScheduleStatus}, {myTimer.IsPastDue}");

    //* Setup the connection to q-notifications, create it if it doesn't exist.
    var connectionString = ConfigurationManager.AppSettings["AzureWebJobsStorage"]; 
    var storageAccount = CloudStorageAccount.Parse(connectionString);
    var queueClient = storageAccount.CreateCloudQueueClient();
    var queue = queueClient.GetQueueReference("q-notifications");
    queue.CreateIfNotExistsAsync();

    //* Eventually this will come from iterating through a SQL Database View of messages that need queueing.
    //* For testing just show we can add two messages with different Visibilty times.
    CloudQueueMessage message;
    TimeSpan delay;

    //* Queue Message for Immediate Processing.
    message = new CloudQueueMessage("Now Message");
    queue.AddMessageAsync(message, null, null, null, null);

    //* Queue Message for Later Processing.
    delay = DateTime.UtcNow.AddMinutes(3) - DateTime.UtcNow;
    message = new CloudQueueMessage("Later Message");
    queue.AddMessageAsync(message, null, delay, null, null);

    //* Queue Message for Even Later Processing.
    delay = DateTime.UtcNow.AddMinutes(12) - DateTime.UtcNow;
    message = new CloudQueueMessage("Even Later Message");
    queue.AddMessageAsync(message, null, delay, null, null);
}
Sorilda answered 4/3, 2017 at 12:56 Comment(4)
FYI - The queue input binding supports binding directly to a CloudQueue (rather than CloudQueueMessage) which would allow you to save 5 lines of code. The UI doesn't show it yet (we have a bug) but you can use the UI to add a queue output binding and change the direction of it from 'out' to 'in' in the advanced editor.Ibo
why are you doing UtcNow.AddMinutes - UtcNow and not just TimeSpan.FromMinutes(3) or something?Billbillabong
I suppose because that's just how I thought to do it. TimeSpan is more efficient.Sorilda
@Ibo are we ever going to be able to set visibilitytimeout? It seems like such an obvious need for many tasks. or can the queue be configured to batch requests in a window?Hilaryhilbert

© 2022 - 2024 — McMap. All rights reserved.