Heroku/Sidekiq not finding Database Record after_commit - ruby-on-rails

Here is my code:
after_commit :notify, on: :create
The notify method, calls to ServiceRequestMailerWorker.perform_async(self.id, email) and here is my that mailer looks like:
class ServiceRequestMailerWorker
include Sidekiq::Worker
def perform(service_request_id, send_to)
#service_request = ServiceRequest.find(service_request_id)
#customer = #service_request.customer
WarrantyMailer.submitted(#service_request, #customer, send_to).deliver
end
end
Error:
2014-07-22T03:05:25.626004+00:00 app[worker.1]: 2014-07-22T03:05:25.625Z 2 TID-os0kqm6sg DEBUG: enqueued retry: {"retry":true,"queue":"default","class":"ServiceRequestMailerWorker","args":[787,"email#email.com"],"jid":"f1d8f416718bafa8c809fa3e","enqueued_at":1405998308.4219391,"error_message":"Couldn't find ServiceRequest with 'id'=787 [WHERE (company_id IS NOT NULL)]","error_class":"ActiveRecord::RecordNotFound","failed_at":1405998308.618538,"retry_count":0}
This ONLY happens in my staging environment on Heroku. I have been trying to debug this for hours. Anyone else run into this issue?

Related

how to retry a sidekiq worker without raising a exception

My sidekiq worker use get request to get the speech recognition outcome, the response status will be "SUCCESS" or "FAILED" or "RUNNING". when the status is "RUNNING", I want to retry the sidekiq worker in 10 minutes. How can I retry without sleep or raise a exception. Because sleep will consume too much resource and raise exception will leave newrelic error log which I don't want to record.
class GetAsrTextWorker
include Sidekiq::Worker
sidekiq_options :queue => :default, :retry => 5
sidekiq_retry_in do | count|
600 * (count + 1)
end
def perform(task_id):
# get request to get the outcome
if status == "SUCCESSD"
# save the outcome
elsif status == "FAILED"
raise AsrError
elsif status == "RUNNING"
raise "Asr running"
end
rescue AsrError => e
Sidekiq.logger.error e.message
end
end
This method will retry this worker but will lead to ugly error log in newrelic which I don't want to record.
Use the New Relic Ruby agent option error_collector.ignore_errors to ignore the specific exception you are raising:
Define a custom exception you can raise:
# lib/retry_job.rb
class RetryJob < StandardError; end
Define a worker that raises the exception:
# app/workers/foo_worker.rb
class FooWorker
include Sidekiq::Worker
def perform
raise RetryJob
end
end
Ignore that exception with the New Relic agent:
# config/newrelic.yml
common: &default_settings
error_collector:
ignore_errors: "ActionController::RoutingError,Sinatra::NotFound,RetryJob"

ActionCable not run in background job rails 5

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

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

DelayedJob gem behaving different in local and on heroku

I am a newbie to delayed job but in local the gem is working flawlessly. In production, the gem logs an entry in delayed_jobs table and then within milli-seconds completes it, deletes it without processing.
A critical difference I found was the handler entry created in the database.
Local
--- !ruby/object:Delayed::PerformableMethod
object: !ruby/ActiveRecord:User
attributes:
id: '1'
email: abc#example.com.au
is_pending: pending
method_name: :job_without_delay
args:
- false
Heroku
--- !ruby/object:Delayed::PerformableMethod
attributes:
id: 1
email: abc#example.com.au
is_pending: pending
What is going on? Can any one please assist?
Controller
def make_pending
#user = current_user
#user.job(false)
redirect_to user_path(current_user)
end
User Model
def job(silence)
Project.job(self.id, silence)
end
handle_asynchronously :job, :run_at => Proc.new { 5.minutes.from_now }
Another difference
Local logs
[Worker(host:__.local pid:5179)] Starting job worker
[Worker(host:__.local pid:5179)] User#job_without_delay completed after 417.0975
[Worker(host:__.local pid:5179)] 1 jobs processed at 0.0024 j/s, 0 failed ...
Heroku logs
013-01-14T12:15:37+00:00 app[worker.1]: [Worker(host:19edbbfb-b8b9-4528-bca6-46ecac4e66bc pid:2)] NilClass# completed after 0.0119
2013-01-14T12:15:37+00:00 app[worker.1]: [Worker(host:19edbbfb-b8b9-4528-bca6-46ecac4e66bc pid:2)] 1 jobs processed at 26.9897 j/s, 0 failed ...
Finally found solution
Added a new model dj.rb
class Dj < Struct.new(:uid, :silence)
def perform
......
end
end

Delayed_job in rails failing

I am just beginning to look into using the delayed_job gem.
To test it, I added "delayed" to the welcome email function and changed that call from
UserMailer.welcome_email(self).deliver
to
UserMailer.delay.welcome_email(self)
This is called inside the User model after_create. I see an entry show up in the delayed_job table after the function executes. Now when I run "rake jobs:work" on command line the task starts but gives errors as below
[Worker(host:Sanjay-PC pid:7008)] Starting job worker
[Worker(host:Sanjay-PC pid:7008)] Class#welcome_email failed with NoMethodError: undefined method `welcome_email' for #<Class:0x4871d60> - 0 failed attempts
[Worker(host:Sanjay-PC pid:7008)] 1 jobs processed at 0.0939 j/s, 1 failed ...
Thinking that if I changed the welcome_email method declaration to a Class method as
def self.welcome_email(user)
(added self. in front) that might help. But then when I run rake jobs:work I get the following error
rake aborted!
undefined method `welcome_email' for class `UserMailer'
C:/Ruby192/lib/ruby/gems/1.9.1/gems/activesupport-3.0.5/lib/active_support/core_ext/module/aliasing.rb:31:in `alias_method'
C:/Ruby192/lib/ruby/gems/1.9.1/gems/activesupport-3.0.5/lib/active_support/core_ext/module/aliasing.rb:31:in `alias_method_chain'
C:/Ruby192/lib/ruby/gems/1.9.1/gems/delayed_job-2.1.4/lib/delayed/message_sending.rb:50:in `handle_asynchronously'
c:/mgn/mgn-r3/app/mailers/user_mailer.rb:10:in `<class:UserMailer>'
c:/mgn/mgn-r3/app/mailers/user_mailer.rb:1:in `<top (required)>'
C:/Ruby192/lib/ruby/gems/1.9.1/gems/activesupport-3.0.5/lib/active_support/dependencies.rb:454:in `load'
<Stack truncated>
It seems to now know the class as UserMailer but it somehow doesn't see the class method welcome_email.
I am on Rails 3.0.5, Ruby 1.9.2p180 and the installed delayed_job gem is 2.1.4 - on Windows
Can't seem to find any related answers anywhere.
Thanks for your thoughts.
-S
Adding UserMailer code per #pjammer's request
class UserMailer < ActionMailer::Base
default :from => "from#example.com"
def welcome_email(user)
#user = user
#url = "http://example.com/login"
mail(:to => user.email,
:subject => "Welcome to My Awesome Site")
end
end
Just use this
UserMailer.delay.welcome_email(self).deliver
instead of
UserMailer.welcome_email(self).delay.deliver
My solution was to redefine function at the handler class (for you it's UserMailer class)
def self.taguri
'tag:ruby.yaml.org,2002:class'
end
It's a hack and I'll try to find a better solution but now it works for me.
(Rails 3.0.9, Ruby 1.9.2-p290, delayed_job 2.1.4)
https://groups.google.com/forum/?fromgroups=#!topic/delayed_job/_gvIcbXrOaE solved my handles_asynchronously error for class methods.
As per Brandon Keeper in the link above, the code is the following:
class ClassName
class << self
def foo
end
handle_asynchronously :foo
end
end
then use ClassName.delay.foo

Resources