7
votes

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?

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.user6089428

1 Answers

8
votes

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);
}