【问题标题】:How to monitor status of actionmailer deliver_later如何监控actionmailer的状态deliver_later
【发布时间】:2019-04-10 20:28:34
【问题描述】:

TL;DR

如何跟踪由deliver_later 排队的邮件及其投递状态?

详情

我想使用来自 action mailer 的 deliver_later 异步发送一堆电子邮件。只要邮件是异步发送的,它就可以工作,wait: 按预期工作。到目前为止一切顺利。

我现在想提供一些关于已发送邮件状态的状态信息。 IE。一个简单的字符串,例如 x/y mails sent,我可以通过 http 或以后的任何方式进行查询(这不是这个问题的关注点!)。我的期望是我可以轻松访问作业队列或类似的东西,然后我可以在after_action 中注册回调,但显然没有这样的东西,看起来我需要使用所述回调手工制作,但我找不到一个资源甚至提到了“交付状态”这个话题。似乎世界上没有人对deliver_latered 邮件是否以及何时实际发送 oO 感兴趣?我能找到的最接近的事情是如何为单元测试的目的检查这一点,但这绝对不是我想要的。

【问题讨论】:

    标签: ruby-on-rails ruby actionmailer rails-activejob


    【解决方案1】:

    没有数据存储(除了您选择的后台作业系统)来存储有关异步交付的完整性或状态的信息。但是,您可以使用 Rails 观察者模式观察邮件的传递。如果您想跟踪邮件投递的尝试和状态,我会在您的数据库中为每次投递添加一个表。

    跟踪调用邮件程序方法以创建投递:

    您可以将before_action 添加到您的邮件程序中,该邮件程序会为所调用的邮件消息写入数据库记录。在此处为您的消息提供一个 UUID,以便稍后在数据库中找到它。 UUID 可以添加到您的邮件标题中。

    跟踪邮件发送者的消息(稍后):

    您可以使用register_observer 将观察者添加到您的邮件程序(或所有邮件程序)。 Observer 类必须实现self.delivered_email(message),并且该方法将在发送电子邮件后调用。此时您可以找到您的数据库记录并在其上写入时间戳以将其标记为“已发送”。

    下面是一个示例:

    这是未经测试的代码,可能与编写的不完全一样

    # your mailer class
    class NotifierMailer < ApplicationMailer
      after_action :record_delivery
    
      private
    
      def record_delivery
        # create an identifier for this mail message and add it 
        # to the headers of the mail message
        headers['X-Delivery-Id'] = SecureRandom.uuid
        # write a database record to track that this email is to be sent
        MailDelivery.create(uuid: headers['X-Delivery-Id'])
      end
    end
    
    # an observer class
    class MailDeliveryObserver
      def self.delivered_email(message)
        delivery = MailDelivery.find_by(uuid: message.headers['X-Delivery-Id'])
        delivery&.touch(:sent_at)
      end
    end
    
    # in application.rb
    # NotifierMailer can be any mailer
    NotifierMailer.register_observer(MailDeliveryObserver)
    

    Here's an article that explains a little more about observers

    And some current Rails docs on observers

    【讨论】:

    • 将标识符添加到邮件标头有什么意义?是否只是将一个人收到的实际邮件与数据库中的条目进行映射?
    • 这会在数据库中为每封电子邮件创建 2 个条目,因为回调显然被调用了两次。数据库日志很好,但我想要的是一个布尔值,它告诉我邮件(“那个”是指我之前存储在内存中的邮件对象)是否成功发送,仅此而已。除非我遗漏了什么,否则使用 actionmailer/actionjob 似乎很难做到这一点。
    • 我的意思是delivered_email 是观察者试图判断“邮件是否成功发送”的钩子,但是一旦你告诉后台工作这样做(deliver_later)你就必须以分布式方式存储该“工作”单元。根据您的电子邮件服务提供商,您通常还可以在邮件发送时从您的 ESP 接收 webhook。我认为 Amazon SES 不会这样做。否则,您发送电子邮件的后台工作必须是将“成功发送”到某处的分布式商店的工作。
    • 看到问题是 ActionMailer 创建了 2 个不同的 Mail 对象,这导致两个传递 ID 存储在数据库中,其中只有一个会被“发送”,因为另一个永远不会被发送。当第二次创建新邮件对象时,标头被删除,因此无法判断哪个 dB 记录引用了第二个邮件对象的同一消息。因此,您的方法在识别已发送邮件方面根本不起作用。最好告诉电子邮件是否发送到哪里,而不是检查是否有特定的电子邮件被称为 Delivered_later on 已发送。
    • 除此之外,解决方案有些过度设计。我可以看到一个“工作 ID”。这是由日志中的activejob生成的。我可以看到“表演”。以及匹配“作业 ID”的“执行”日志消息。必须可以为此设计一些简单的内存观察器,而不是依赖数据库。
    猜你喜欢
    • 2018-07-01
    • 2020-01-06
    • 2011-04-21
    • 1970-01-01
    • 2019-03-16
    • 2015-03-30
    • 2012-05-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多