Search code examples
c#azureazure-functionsmessage-queue

Azure Queue Trigger function instantly moving messages to poison queue


So I have quite a basic Azure HTTP function that creates job messages whenever I do a POST request to the url:

using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.Functions.Worker;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Azure.Storage.Queues;

namespace WeatherImageGenerator.HTTP
{
    public class StartJobFunction
    {

        private readonly ILogger<StartJobFunction> _logger;
        
        public StartJobFunction(ILogger<StartJobFunction> logger)
        {
            _logger = logger;
        }

        [Function("StartJobFunction")]
        public async Task<IActionResult> Run (
            [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequest req)
            {
                _logger.LogInformation("Received request to start a job.");

                var jobId = Guid.NewGuid().ToString();

                var message = JsonConvert.SerializeObject(new { JobId = jobId, Status = "Pending"});

                string connectionString = Environment.GetEnvironmentVariable("AzureWebJobsStorage");
                QueueClient queueClient = new QueueClient(connectionString, "startjobqueue");

                await queueClient.CreateIfNotExistsAsync();

                await queueClient.SendMessageAsync(message);

                _logger.LogInformation($"Sent message to start job queue for job {jobId}");

                return new OkObjectResult(new { JobId = jobId });
            }
    }
}

However, the moment I add an Azure Queue Trigger to this queue (even with the generated code in VSCode), all messages instantly reach the MaxDequeueCount of 5 and get sent to the poison queue. How can I fix this?

For reference, here's the generated Azure Queue Trigger function:

using System;
using Azure.Storage.Queues.Models;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Logging;

namespace WeatherImageGenerator.Queue
{
    public class ProcessStartJobQueue
    {
        private readonly ILogger<ProcessStartJobQueue> _logger;

        public ProcessStartJobQueue(ILogger<ProcessStartJobQueue> logger)
        {
            _logger = logger;
        }

        [Function(nameof(ProcessStartJobQueue))]
        public void Run([QueueTrigger("startjobqueue", Connection = "AzureWebJobsStorage")] QueueMessage message)
        {
            _logger.LogInformation($"C# Queue trigger function started for message: {message.MessageText}");
        }
    }
}

It doesn't even show the queue logger information, just instantly sends messages to the poison queue.


Solution

  • Your issue is with your message encoding.

    Older versions of queueClient used to perform encoding automatically, but this is no longer the default behavior as-per documentation here.

    Thus, you're going to want to base64encode your string before you send it.

    You can do this by using:

    var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(message);
    var encodedMessage = System.Convert.ToBase64String(plainTextBytes);
    

    and then send the encodedMessage string instead of your original message string.

    I suggest creating a static helper method to handle this more easily.