标签: rails-activejob

ActiveJob GlobalID 和内存中的 ActiveRecord 对象

我正在使用排队系统 (Sidekiq) 并希望转移到 ActiveJob 以获得性能优势,因为每次将 ActiveRecord 对象传递给工作人员时都不必查询数据库。我想询问并确认,因为我不是 100% 确定,但我的理解是,当 ActiveJob 使用 GlobalID 传递所有在内存中完成的 ActiveRecord 对象并且没有完成对数据库的单独查询时,对吗?

ruby activerecord ruby-on-rails rails-activejob

2
推荐指数
1
解决办法
2333
查看次数

如何测试 ActiveJob 回调?

我正在为学生构建电子邮件提醒功能。他们应该按照讲师指定的时间间隔收到一封电子邮件,表明他们取得了多少进步。

我的方法是使用 ActiveJob 来安排发送电子邮件的作业,然后当执行该作业时,我使用回调after_perform来安排下一个作业(摘自这篇文章)。看起来是这样的:

class StudentReminderJob < ApplicationJob
  queue_as :default

  after_perform do |job|
    # (get user update frequency preference)

    self.class.set(wait: update_frequency).perform_later(job.arguments[0]) 
  end

  def perform(user)
    # Send email containing student stats information
    UserMailer.send_student_reminder_email(user)
  end
end
Run Code Online (Sandbox Code Playgroud)

最初的一组提醒将由 rake 任务启动。

我的问题是这样的:当尝试测试上面的代码时,perform_enqueued_jobs我似乎遇到了无限循环。这是我的测试:

require 'rails_helper'

describe StudentReminderJob, active_job: true, type: :job do
  include ActiveJob::TestHelper
  include ActiveSupport::Testing::TimeHelpers

  let(:user) { create :user }
  subject(:job) { described_class.perform_later(user) }

  it 'gets enqueued' do
    # Passes
    expect { job }.to have_enqueued_job(described_class)
  end

  it 'receives …
Run Code Online (Sandbox Code Playgroud)

rspec ruby-on-rails delayed-job rails-activejob

2
推荐指数
1
解决办法
1767
查看次数

Rails活动作业使用,或使用Rails自动运行观察程序线程

很高兴看到Rails 4.2附带Active Job作为后台作业的通用界面.但是我找不到如何在文档中启动一个worker.似乎该文档仍然不成熟(例如,正确版本的Sneakers仅在Rails中提及Gemfile),因此我不确定"正在运行的工作者"部分是否处于"活动作业"中或者仅在文档中未提及.

因此,对于Active Job,我是否仍需要手动启动作业观察程序线程,就像sidekiq在我的情况下一样rake sneakers:run?如果是这样,我应该在哪里放置这些命令以便rails server在开发环境中自动运行这些并行任务?

ruby ruby-on-rails rails-activejob

1
推荐指数
1
解决办法
1525
查看次数

如何使用ActiveJob和Sidekiq限制失败的作业重试计数器?

我想限制的数量retries当作业使用失败ActiveJobSidekiq作为适配器.

使用Sidekiq,我可以这样做:

class LessRetryableWorker
  include Sidekiq::Worker
  sidekiq_options :retry => 5

  def perform(...)
  end
end
Run Code Online (Sandbox Code Playgroud)

Sidekiq配置不提供全局retry配置.每个工人负责设置retry选项.所以我想我必须在ActiveJob端实现它才能正确完成它.

ruby rails-activejob

1
推荐指数
1
解决办法
1726
查看次数

适用于特定作业的 ActiveJob 内联队列适配器

有没有办法将 ActiveJob 队列适配器设置为内联特定后台作业?

就我而言,我想在测试中运行一些后台作业来构建集成测试。我不关心作业内部细节,因为我的目的只是运行后台作业并断言结果。但是,这些集成测试并未涵盖所有后台作业,因此我不想全局设置队列适配器。

ruby ruby-on-rails rails-activejob

1
推荐指数
1
解决办法
2363
查看次数

Rails 5 Active Job 和 Sidekiq 不发送邮件

所以我对 sidekiq 和 activejob 很陌生,我知道我不需要后台工作一个在创建帐户时发送的邮件,但是我真的很想了解这一切是如何工作的,最好的学习方法就是这样做。 ..

我设置了以下 Job、Mailer 和 Controller 操作,但是当我创建一个新帐户时它失败并出现错误:(为了简洁,我已经发布了整个堆栈)

e_owner: processed outbound mail in 1.3ms
[ActiveJob] [WelcomeEmailJob] [18ba16e9-e3d9-4dd1-b6f4-0a435449c68c] Performed WelcomeEmailJob from Sidekiq(default) in 26.39ms
Completed 404 Not Found in 25051ms (ActiveRecord: 91.9ms)



ActiveRecord::RecordNotFound - Couldn't find Account with 'id'=:
  activerecord (5.0.0.1) lib/active_record/core.rb:173:in `find'
  app/mailers/welcome_notification_mailer.rb:4:in `welcome_owner'
  actionpack (5.0.0.1) lib/abstract_controller/base.rb:188:in `process_action'
  actionpack (5.0.0.1) lib/abstract_controller/callbacks.rb:20:in `block in process_action'
  activesupport (5.0.0.1) lib/active_support/callbacks.rb:97:in `__run_callbacks__'
  activesupport (5.0.0.1) lib/active_support/callbacks.rb:750:in `_run_process_action_callbacks'
  activesupport (5.0.0.1) lib/active_support/callbacks.rb:90:in `run_callbacks'
  actionpack (5.0.0.1) lib/abstract_controller/callbacks.rb:19:in `process_action'
  actionpack (5.0.0.1) lib/abstract_controller/base.rb:126:in `process'
  actionmailer (5.0.0.1) lib/action_mailer/rescuable.rb:23:in …
Run Code Online (Sandbox Code Playgroud)

ruby-on-rails sidekiq rails-activejob ruby-on-rails-5

1
推荐指数
1
解决办法
647
查看次数

如何测试ActiveJob已入队?

我有一个create动作,如果记录成功保存,则调用ActiveJob。

def create
  @object = Object.new(importer_params)
  respond_to do |format|
    if @object.save
      MyJob.perform_later( @object.id )
      format.html { redirect_to @object, notice: t('.notice') }
    else
      format.html { render :new }
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

我想测试控制器规范中正确调用了Job。

describe "POST #create" do
  it {
    expect {
      post :create, { object: valid_attributes }
    }.to change(Object, :count).by(1)
  }
  it { 
    expect {
      post :create, { object: valid_attributes }
    }.to have_enqueued_job(MyJob) 
  }  
end
Run Code Online (Sandbox Code Playgroud)

但是我明白了

Failure/Error:
  expect {
    post :create, { object: valid_attributes }
  }.to have_enqueued_job(MyJob)
  expected to enqueue exactly 1 …
Run Code Online (Sandbox Code Playgroud)

rspec ruby-on-rails rails-activejob

1
推荐指数
2
解决办法
4322
查看次数

在销毁User,Rails 5之前发送电子邮件

我试图在我的User对象被销毁之前挂钩邮件程序.

我正在使用Sidekiq发送电子邮件,但是当用户被销毁时会出现此错误.

ActiveJob::DeserializationError: Error while trying to deserialize arguments: Couldn't find User with id [id]

在我的模型中,我有这个:

class User < ApplicationRecord
  before_destroy :goodbye_user

  devise :database_authenticatable, :registerable,
     :recoverable, :rememberable, :trackable, :validatable, :confirmable, :lockable

  private

  def send_devise_notification(notification, *args)
    devise_mailer.send(notification, self, *args).deliver_later
  end

  def goodbye_user
    GoodbyeUser.goodbye_user(self).deliver_later
  end

end
Run Code Online (Sandbox Code Playgroud)

告别用户邮件永远不会发送.

任何的想法?

email ruby-on-rails sidekiq rails-activejob

1
推荐指数
1
解决办法
321
查看次数

测试排队的电子邮件数量?

我们可以检查enqueued_jobs.length,前提是电子邮件是唯一可能的后台作业类型。

it 'sends exactly one, particular email' do
  expect { post :create }.to(
    # First, we can check about the particular email we care about.
    have_enqueued_mail(MyMailer, :my_particular_email)
  )

  # But we also have to check that no other email was sent.
  expect(ActiveJob::Base.queue_adapter.enqueued_jobs.length).to eq(1)
end
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法来断言:

  1. MyMailer.my_particular_email已排队,
  2. 没有其他电子邮件排队,
  3. 我们不关心其他非电子邮件后台作业是否已排队

ruby rspec ruby-on-rails rspec-rails rails-activejob

1
推荐指数
1
解决办法
1596
查看次数

Rails Sidekiq 队列大小不起作用

我有一个包含 2 个作业的 Rails 应用程序(ImportCsvJob 和 ProcessCsvJob)。这样我就可以在应用程序中明显地提示队列中仍然有作业,我有这个辅助方法(在 application_helper.rb 内):

module ApplicationHelper
   def queued_job_count
        Sidekiq::Queue.new.size
    end
end
Run Code Online (Sandbox Code Playgroud)

然后我在索引控制器上使用它,然后将其传递到视图进行处理并在应用程序中给出视觉提示。

  def index
    @still_have_jobs = !queued_job_count.zero?
  end
Run Code Online (Sandbox Code Playgroud)

但是,当我仍然有 1 个后台作业 (ImportCsvJob) 时,此方法有效,但当我添加 (ProcessCsvJob) 时,它不再有效。

导入_csv_job.rb

require 'open-uri'

class ImportCsvJob < ActiveJob::Base
  queue_as :default

  def perform(csv_record)
    csv_record[:object_changes] = ApplicationController.helpers.generate_hash(csv_record[:object_changes])
    ObjectRecord.create(csv_record)
  end
end
Run Code Online (Sandbox Code Playgroud)

process_csv_job.rb

class ProcessCsvJob < ActiveJob::Base
  queue_as :default

  def perform(csv_path)
    csv_file = open(csv_path,'rb:UTF-8')

    options = {
        row_sep: :auto, col_sep: ",", 
        user_provided_headers: [:object_id, :object_type, :timestamp, :object_changes], 
        remove_empty_values: true, 
        headers_in_file: true
    }

    SmarterCSV.process(csv_file, options) do |array| …
Run Code Online (Sandbox Code Playgroud)

ruby ruby-on-rails sidekiq rails-activejob

0
推荐指数
1
解决办法
1591
查看次数

如何从 ActiveJob 队列中清除作业?

我有一个执行状态更改的工作,而且我使用它的方式是,只有在经过一定时间后才会更改状态。

在我的工作课上:

class ItemJob < ApplicationJob
 queue_as :default

 def perform(item)
  item.do_this!
 end
end
Run Code Online (Sandbox Code Playgroud)

它是从模型调用的:

def create_item_worker
 ItemJob.set(wait: 30.seconds).perform_later(self)
end
Run Code Online (Sandbox Code Playgroud)

但是,这是行不通的,因为 ActiveJob 有一个用于不再存在的记录的作业队列。我输入bundle exec sidekiq终端,它吐出像ActiveJob::DeserializationError: Error while trying to deserialize arguments: Couldn't find Item with 'id'=67.

那么我该如何清除呢?Sidekiq::Queue.all.each(&:clear)似乎没有做任何事情。

ruby-on-rails sidekiq rails-activejob

0
推荐指数
1
解决办法
1705
查看次数