ActionCable not run in background job rails 5 - ruby-on-rails

My project use rescue to run background job.
I use actioncable in a job to notify user when the job finish. but it not running when use perform_later, but perform_now => it work ok.
My job:
class FetchExternalDataJob < ApplicationJob
queue_as :default
def perform
# logic here
ActionCable.server.broadcast "some_channel", message: "finish job"
end
end
Call job:
class RoomsController < ApplicationController
def show
FetchExternalDataJob.perform_later
end
Channel javascript:
App.fetch_data = App.cable.subscriptions.create "FetchDataChannel",
received: (data) ->
console.log("job finished")

Have you set up redis as your adapter in cable.yml yet?
ei:
development:
adapter: redis
url: redis://localhost:6379/1

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

Sidekiq fake mode is not working on rails rspec testing

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

Using sidekiq/redistogo with heroku?

I followed the sideqik gem tutorial docs and heroku Redistogo addon docs
initializers/sidekiq.rb:
Sidekiq.configure_server do |config|
config.redis = { url: 'redis://redistogo:xxx.redistogo.com:10076/' }
end
Sidekiq.configure_client do |config|
config.redis = { url: 'redis://redistogo:xxx.redistogo.com:10076/' }
end
app/workers/hard_woker.rb:
class HardWorker
include Sidekiq::Worker
def perform(shop_domain, webhook)
#performing stuffs
end
Webhook I am putting into background job (trying to at least):
class OrdersCreateJob < ActiveJob::Base
def perform(shop_domain:, webhook:)
shop = Shop.find_by(shopify_domain: shop_domain)
shop.with_shopify_session do
HardWorker.perform_async(shop_domain, webhook)
end
end
end
Procfile:
hardworker: bundle exec sidekiq -t 25
There are no errors in console.
Is something wrong here, did I miss something?
My queue:
irb(main):003:0> Sidekiq::Queue.all
=> [#<Sidekiq::Queue:0x000055b53a2d0920 #name="default", #rname="queue:default">]
I assume this means nothing is in the queue?
My goal is to take all my my CreateOrderWebhook code (which is almost 500 lines) into a background job to put less strain on the app and allow webhooks /prevent webhooks from being blocked

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

Resources