【问题标题】:Rails + Devise + delayed_job?Rails + 设计 + 延迟工作?
【发布时间】:2011-05-06 17:59:44
【问题描述】:

我有一个在 Heroku 上使用 Devise 的 Rails 3 应用程序。问题是我正在使用 Sendgrid 发送电子邮件并且电子邮件传递速度很慢,这会使应用程序挂起。所以我有兴趣使用delayed_job 在后台排队发送电子邮件,以便我的应用能够响应用户。

Devise 如何与delayed_job 一起使用?有什么方法可以设置 Devise 使用delayed_job?

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 heroku devise


    【解决方案1】:

    来自罗伯特·梅:https://gist.github.com/659514

    将此添加到config/initializers 目录中的文件中:

    module Devise
      module Models
        module Confirmable
          handle_asynchronously :send_confirmation_instructions
        end
    
        module Recoverable
          handle_asynchronously :send_reset_password_instructions
        end
    
        module Lockable
          handle_asynchronously :send_unlock_instructions
        end
      end
    end
    

    【讨论】:

    • 将该代码添加到 config/initializers 目录中的某个 file.rb 中。
    • 这对我不起作用,也许是因为如果使用设计可能使用的 Rails 3 邮件程序,则不支持此方法。有关更多信息,请参阅此链接:github.com/collectiveidea/delayed_job 并转到 Rails 3 Mailers 部分
    【解决方案2】:

    根据Devise wiki pagedevise-async gem 将为您处理此问题。它支持delayed_job、resque和sidekiq。

    【讨论】:

      【解决方案3】:

      我发现以上方法都不适合我。我正在使用Devise 2.0.4 和Rails 3.2.2 和delayed_job_active_record 0.3.2

      devise 实际上谈到在代码中的 cmets 中执行类似操作的方式是覆盖 User 类中的方法。因此,我就这样解决了,而且效果很好:

      app/models/User.rb

      def send_on_create_confirmation_instructions
        Devise::Mailer.delay.confirmation_instructions(self)
      end
      def send_reset_password_instructions
        Devise::Mailer.delay.reset_password_instructions(self)
      end
      def send_unlock_instructions
        Devise::Mailer.delay.unlock_instructions(self)
      end
      

      【讨论】:

      • 覆盖这些方法会破坏其他功能......它似乎有效,但没有在用户模型上设置 reset_password_token 请参阅我的解决方案
      • 如果您查看最新设计中的 send_reset_password_instructions 代码: # 重置密码令牌并通过电子邮件发送重置密码指令 def send_reset_password_instructions generate_reset_password_token!如果应该_generate_reset_token? self.devise_mailer.reset_password_instructions(self).deliver end 上述建议导致密码令牌未生成。
      【解决方案4】:

      这对我有用:

      在 app/models/user.rb 中

        # after your devise declarations
        handle_asynchronously :send_reset_password_instructions
        handle_asynchronously :send_confirmation_instructions
        handle_asynchronously :send_on_create_confirmation_instructions
      

      您可能不需要所有这些,具体取决于您包含的设计模块

      【讨论】:

      • 适用于我的 Rails 3.2.16 和 Devise 3.2.3。我也在使用 devise_invitable 1.3.4,为此我添加了handle_asynchronously :deliver_invitation
      • 好吧,我评论得太早了。我的用户模型中还覆盖了send_reset_password_instructions。异步运行时它不能正常工作。 ZachBeta 的1/6/2014 comment on Github 引导我尝试handle_asynchronously :send_devise_notification,它似乎可以处理包括邀请在内的所有事情。设计源代码也有一个lengthy comment关于延迟排队。
      • 如何为 "devise_token_auth" gem 完成此操作?
      【解决方案5】:

      我不确定 Devise 是否提供了一种简单的方法来进行电子邮件传递的后台处理。然而,有一些方法可以用 DelayedJoy 做到这一点。 DelyedJob 提供了一个函数“handle_asynchronously”,如果将其注入到 DeviseMailer 中,可以确保在后台进行交付。

      在你的 config/application.rb 中试试这个

      config.after_initialize do 
        ::DeviseMailer.handle_asynchronously :deliver_confirmation_instructions 
        # or
        ::DeviseMailer.handle_asynchronously :deliver!
      end
      

      您需要对此进行试验。您还可以尝试继承 DeviseMailer 并将其设置为在 config/initializer/devise_mailer_setup.rb 中的初始化程序中异步传递或类似的东西。

      【讨论】:

        【解决方案6】:

        我使用 delayed_job_mailer 插件在 Rails 2 应用程序中完成此操作。不确定它是否适用于 Rails 3。

        【讨论】:

          【解决方案7】:

          不确定为什么需要对任何延迟作业任务进行身份验证。只需让设计经过身份验证的控制器操作将电子邮件发送排队到库方法即可。

          【讨论】:

            【解决方案8】:

            对于带有 Devisedelayed_job_active_record,只需使用以下内容。 (添加到user.rb model

            handle_asynchronously :send_devise_notification, :queue => 'devise'
            

            【讨论】:

              【解决方案9】:

              我通常发现最好避免任何和所有可用于 Ruby 和 Rails 的后台作业任务管理器,期间。他们很烂。

              相反,我使用 crontab,它是一个古老的程序并且非常擅长它的工作。只需编写一个脚本来经常做你的脏活,然后告诉 crontab 使用 rails runner 在正确的时间运行它。这样可以将那些讨厌的长时间运行的任务排除在 Rails 应用程序的其余部分的运行时之外,但如果您需要/需要,您仍然可以访问数据库和整个 Rails 堆栈。

              【讨论】:

              • 我不同意“任何和所有后台作业任务管理器”很糟糕的说法。 Ruby Toolbox 对 Ruby 的队列选项进行了很好的比较:ruby-toolbox.com/categories/queueing.html
              • 假设您有一个导入,将新产品或产品的新信息放入您的应用程序。现在新产品需要生成一些元数据或者什么不需要。您是否要在 products 表中添加一个标志,以便您的 cronjob 可以获取这些项目?您多久运行一次该 cronjob?每十分钟?如果一次执行运行时间超过 10 分钟怎么办?您将运行竞争进程。看起来更像是你试图用 crontab 破解的东西最终只会成为一个工作队列的穷人实现。最好使用不会破坏数据库架构和模型的专用队列。
              猜你喜欢
              • 2011-08-06
              • 2011-12-27
              • 1970-01-01
              • 1970-01-01
              • 2011-04-16
              • 2019-05-15
              • 2015-12-03
              • 2012-03-29
              • 2015-10-08
              相关资源
              最近更新 更多