user_controller.rb
class UsersController
def create
MyJob.perform_later
User.create(...)
end
end
my_job.rb
class MyJob < ActiveJob::Base
queue_as :default
def perform()
puts "START"
sleep 3
puts "END"
end
end
config/initializer/sucker_punch.rb
require 'sucker_punch/async_syntax'
Rails.application.configure do
config.active_job.queue_adapter = :sucker_punch
end
When I run MyJob.perform_laterin a rails console, everything work fine and the logger display this message Enqueued MyJob (Job ID: 6c857af8-a8ed-4bd0-918b-4296c4315727) to SuckerPunch(default)
However, when I send an http request to my user_controller, I don't receive any response before 3 seconds (which make me think that the job is not executed asynchronously), and the logger display this Enqueued MyJob (Job ID: e3d698eb-00d8-4849-9496-f01c53fc7217) to Inline(default)
It seems to use the inline (default?) adapter in controllers, which is not asynchronous.
ps : I'm using puma as http server, and using sucker_punch without ActiveJob works fine
Related
I've got Sidekiq worker SyncProductsWorker which calls inside the controller action:
class ProductsController < BaseApiController
def fetch_all
::Imports::FetchAllProductsWorker.perform_async
head :ok
end
end
And Sidekiq job FetchAllProductsJob with the same code as SyncProductsWorker as a schedule job inside sidekiq.yml
sidekiq.yml
:queues:
- imports_fetch_all
:dynamic: true
:schedule:
imports_fetch_all_job:
cron: '0 0 * * *' # at midnight
class: Imports::FetchAllProductsJob
queue: imports_fetch_all
So basically both classes, worker and job looks almost the same:
# worker
module Imports
class FetchAllProductsWorker
include Sidekiq::Worker
sidekiq_options queue: 'imports_fetch_all'
def perform
puts 'test'
end
end
end
# schedule job
module Imports
class FetchAllProductsJob < ApplicationJob
sidekiq_options queue: 'imports_fetch_all'
def perform
puts 'test'
end
end
end
How to avoid code duplication to not have two files with the same code?
There is no reason to talk to Sidekiq directly in one place, and ActiveJob in another place. Both places can just talk directly to the ActiveJob job. Delete your Sidekiq worker, and replace your call to the worker's perform_async with a call to the job's perform_later:
def fetch_all
::Imports::FetchAllProductsJob.perform_later
head :ok
end
I'd like to test my worker with Rspec and the gem sidekiq-uniq-job.
Let's say I have this job :
class TestJob < ApplicationWorker
include Sidekiq::Worker
sidekiq_options queue: 'test_queue', lock: :until_executed
def perform
puts "Hello World !"
end
end
I would like to be able to test it with the following test for instance :
it "doesn't enqueue a job to send an email to the rider" do
TestJob.perform_async
TestJob.perform_async
expect(TestJob.jobs.size).to eq(1)
end
This would allow me to be sure that my job will never be queued more than once.
How would you do it ??
I am trying to test a job on my rails code I have the following
RSpec.describe MyJob, type: :job do
it 'job in correct queue' do
VCR.use_cassette('mycassette/type') do
described_class.perform_later(id)
assert_equal 1, described_class.jobs.size
end
end
end
The above gives me an error undefined method jobs I have tested and it seems that I am running on the correct mode, Sidekiq::Testing.fake? gives me true
perform_later means you're using ActiveJob instead of using Sidekiq directly, so you also have to use ActiveJob's testing helpers: https://edgeapi.rubyonrails.org/classes/ActiveJob/TestHelper.html
assert_enqueued_jobs 1 do
described_class.perform_later(id)
end
Alternatively you can remove ActiveJob entirely by changing your job definition from:
class MyJob < ActiveJob::Base
queue_as :my_queue
# ...
to:
class MyJob
include Sidekiq::Worker
sidekiq_options queue: 'my_queue'
# ...
I have a job file and I am using delayed_job driver for rails.
It works fine for perform later.
My job file:
jobs/test_job_job.rb
class TestJobJob < ActiveJob::Base
queue_as :default
def perform(*args)
puts("test")
end
def test_method
puts('test method')
end
end
In my controller, I did,
TestJobJob.perform_later
It worked fine and gave me right output:
Output:
[Worker(host:hunter pid:8079)] Job ActiveJob::QueueAdapters::DelayedJobAdapter::JobWrapper (id=18) RUNNING
test
[Worker(host:hunter pid:8079)] Job ActiveJob::QueueAdapters::DelayedJobAdapter::JobWrapper (id=18) COMPLETED after 0.0397
[Worker(host:hunter pid:8079)] 1 jobs processed at 1.3259 j/s, 0 failed
But when I changed to,
TestJobJob.delay(run_at: 2.minutes.from_now)
Job was not even en-queued, and when I did,
TestJobJob.delay(run_at: 2.minutes.from_now).test_method
It gave me error: undefined method `test_method' for TestJobJob
My config:application.rb
config.active_job.queue_adapter = :delayed_job
I have a problem with sidekiq/activejob integration. I have a controller that calls a perform_later method from a MyJob class. This works with the perform method, but when I change to perfom_later, the job is scheduled in my development log. However, when I see the sidekiq dashboard, at the retries section, I can see NameError: uninitialized constant (look below image)
These are my files:
# app/jobs/crime_job.rb
class CrimeJob < ActiveJob::Base
queue_as :default
def perform(crime)
puts "Perform #{crime}"
end
def self.job_name(crime)
"RadarCrime:#{crime.id}"
end
end
Crime Controller
# app/controllers/crime_controller.rb
def show
# [...]
CrimeJob.perform_later(#crime)
end
Sidekiq initializer
# config/initializers/active_job.rb
Rails.application.config.active_job.queue_adapter = :sidekiq
Well, I also open an issue in Sidekiq repository, and the solution is easier than I've think.
Just restart the sidekiq process and it's works fine.
Issue link: https://github.com/mperham/sidekiq/issues/2207