Sidekiq fake mode is not working on rails rspec testing - ruby-on-rails

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'
# ...

Related

How to avoid code duplication in Rails Sidekiq schedule job and worker with the same code

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

Rspec: How to test that a worker having the sidekiq_option lock: :until_executed isn't enqueued twice?

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 ??

ActiveJob queue adapter ignored?

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

Ruby on Rails jobs NotImplementedError

I am trying to implement a Job in my Ruby on Rails application, but I keep getting this error:
NotImplementedError
Error from the server:
NotImplementedError (NotImplementedError):
app/controllers/cron_controller.rb:6:in `message_10_minutes'
Here's the ActiveJob:
class TestSmsJob < ActiveJob::Base
queue_as :default
#include Plivio
def perform(*args)
# do my stuff
end
end
This is the call to the function for executing the job:
class CronController < ApplicationController
def index
end
def message_10_minutes
TestSmsJob.set(wait: 10.minutes).perform_later()
render :layout => false
end
end
Do you guys know what am I missing?
Rails by default comes with own implementation of asynchronous queuing however you still needs to specify which adapter do you want to use. If you want to use built in adapter you simply don't have to bundle any other gem.
Here is the list of adapters - http://api.rubyonrails.org/classes/ActiveJob/QueueAdapters.html
Since sidekiq may be too hard for the start you can use sucker_punch - https://github.com/brandonhilkert/sucker_punch
After you choose your adapter you have to update config
module YourApp
class Application < Rails::Application
# Be sure to have the adapter's gem in your Gemfile
# and follow the adapter's specific installation
# and deployment instructions.
config.active_job.queue_adapter = :adapter_name
end
end

NameError: uninitialized constant MyJob ActiveJob and Sidekiq

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

Resources