天蓝色队列存储 - 将消息放回队列中

azure queue storage - putting a message back in the queue

我正在构建一个队列处理 webjob 以从队列中读取消息并使用数据从 blob 存储中检索报告 uri,然后将其作为 link 在电子邮件中发送。我的流程运行良好,但我需要在特定时间 window 内发送电子邮件。

我有另一个进程 (webjob) 从 sql 后端检索此数据并将其放入电子邮件队列。

此 Web 作业每 30 分钟运行一次,仅获取当天和当前时间 window 后 2 小时内的数据。所以我知道队列中的任何内容都是今天和 'now' 后 2 小时内的。我如何进一步缩小范围以从队列中读取数据,如果 'email out' 时间设置为 19:00 而当前时间是 18:00,我可以将此消息放回队列稍后再读,下次它应该更接近 19:00 然后我可以处理它并通过电子邮件发送出去。
时间不一定是准确的,所以即使它在 19:00 的 30 分钟内(或任何它设置的发送时间)它也可以被处理。所以我有效地从队列中取出一个对象,检查它的时间,如果它不在分配的 'email out' 时间的 30 分钟内,我将它放回队列并再次处理它

** 在我的网络作业中,我有一个 'Functions' class,其中包含一个方法 'ProcessQueueMessage',只要有消息放入队列就会触发该方法。

// This function will get triggered/executed when a new message is written 
    // on an Azure Queue called queue.
    public async Task ProcessQueueMessage([QueueTrigger("%reportgenerator%")] Data.Dto.Schedule.ScheduleDto schedule)
    {
        var reports = await this._scheduledReportGenerationService.GenerateScheduledEmails(schedule.ID);
    }

ScheduleDto class 将有一个生成时间 属性,我可以读取它并将其与当前时间进行比较,并且仅当它在我指定的 'time window' 范围内时才对其进行处理。我如何阻止队列消息在此处被删除,以便我可以重新处理它?

因此,Azure 存储队列有一些功能可以帮助您应对这种情况:

关于将消息放回队列,您无需执行任何特殊操作。这是存储队列提供的功能。当您使消息出列时(GET Message 在 Azure 存储术语中),该消息在一定时间内变得不可见,如果没有被出列的进程删除,它将再次变得可见并可以被另一个进程拾取。

因此,当您使消息出列时,请检查时间,如果时间不对,则什么都不做。但是请确保一旦消息被处理,您就删除该消息,否则它会被再次接收。

您还可以做的另一件事是,当您使消息出队并发现现在不是处理该消息的正确时间时,您更新该消息并将其可见性超时 属性 设置为一个值,该值将使消息在接近处理时间时再次可见。例如,您在 18:00 处将消息出列,然后发现此消息需要在 19:00 处处理。在这种情况下,您将更新消息并将其可见性超时设置为 50 分钟(或大于 30 分钟的值,因为 30 分钟是您的 Web 作业的计划)。这将确保当您的 webjob 在 18:30 运行时,该消息不会被 web 作业拾取,因为该消息只会在 18:50.

可见

您可以在此处阅读有关更新消息的更多信息:https://docs.microsoft.com/en-us/rest/api/storageservices/update-message and about dequeuing messages here: https://docs.microsoft.com/en-us/rest/api/storageservices/get-messages

更新

我完全忘记了它在 WebJob 中,所以什么都不做实际上会删除邮件。我猜你有 2 个选项(有点重复评论中提到的内容):

  1. 抛出异常而不是什么都不做。这将确保 WebJob 处理器不会删除消息。我自己没有尝试过,但您也可以更新消息并将其可见性超时设置为更接近 WebJob 本身所需时间的值(然后抛出异常)。不过,这是一种反模式。
  2. 您在队列中添加一条新消息并将其初始可见性超时设置为接近所需时间的值(这也包含在另一个答案中),然后让该消息删除。

当您将消息添加到队列时,只需设置 initialVisibilityDelay,以便在最短处理时间之前不会看到消息。

CloudQueue queue = queueClient.GetQueueReference(queueName);
var msg = new CloudQueueMessage("Hello World!");
TimeSpan timeSpanDelay = GetEarliestProcessTime();
await queue.AddMessageAsync(msg, null, timeSpanDelay, null, null);

CloudQueue.AddMessage

当您在 Azure 存储队列中对项目进行排队时,您可以向该项目添加额外的详细信息,这将导致该项目在可配置的持续时间内隐藏。如果您的批处理作业每两个小时只能 运行,但您想延迟发送具有更细粒度时间控制的电子邮件,那么我建议每两小时排队的批处理作业可以使用此 "initialVisibilityDelay" 功能。

这是另一个描述 API 的 SO 问题。

Azure storage queue message (show at specific time)