I use resque-history plugin for monitoring done tasks.
Firstly I include this string require 'resque-history/server' into routes file, and then I see new history tab in dashboard.
This is some code in /app/jobs/welcome_email_job.rb
require 'resque-history'
class WelcomeEmailJob < ActiveJob::Base
extend Resque::Plugins::History
#max_history = 200
#queue = :email
def perform(user)
UserMailer.welcome_email(user).deliver_now
puts "I delivered mail to #{user.login} now, sincerly yours Resque <3"
end
end
When job was done, I see in stats tab how many jobs was processed, but history tab empty, just only table head. Can I resolve this trouble?
Try restarting your workers (they aren't restarted automatically).
Related
I am facing an issue concerning logs. I built a rails app using ActiveJob with Sidekiq.
I want to write an entry into rails logs from a background job.
Usually, when I want to write an entry, I do something like this (in a controller for instance):
Rails.logger.fatal "BIG ISSUE!!!"
So I wanted to do the same but this time, in a background job:
class MyJob < ApplicationJob
queue_as :default
def perform(*args)
Rails.logger.fatal"FATAL TEST"
end
end
However nothing is written in the rails logs. Can you explain me why? And how to make this work?
Sidekiq logs will go to the /var/log/syslog to redirect check out this article https://github.com/mperham/sidekiq/wiki/Logging
I'm working on a product that calls of perform_later jobs. This works for our product in production because we have a series of workers who will run all the jobs.
But, when I'm using the app locally, I don't have access to these workers, and I'd like to change all the perform_laters into perform_nows only when I use the app locally.
What's the best way to do this? One idea I had was to add something in my env file that would add a variable to make all perform_laters into perform_nows -- but I'm not sure what a flag or variable like that would look like.
Ideas?
The clean solution is to change the adapter in development environment.
In your /config/environments/development.rb you need to add:
Rails.application.configure do
config.active_job.queue_adapter = :inline
end
"When enqueueing jobs with the Inline adapter the job will be executed immediately."
In your app you can have:
/my_app/config/initializers/jobs_initializer.rb
module JobsExt
extend ActiveSupport::Concern
class_methods do
def perform_later(*args)
puts "I'm on #{Rails.env} envirnoment. So, I'll run right now"
perform_now(*args)
end
end
end
if Rails.env != "production"
puts "including mixin"
ActiveJob::Base.send(:include, JobsExt)
end
This mixin will be included on test and development environments only.
Then, if you have the job in:
/my_app/app/jobs/my_job.rb
class MyJob < ActiveJob::Base
def perform(param)
"I'm a #{param}!"
end
end
You can execute:
MyJob.perform_later("job")
And get:
#=> "I'm a job!"
Instead of the job instance:
#<MyJob:0x007ff197cd1938 #arguments=["job"], #job_id="aab4dbfb-3d57-4f6d-8994-065a178dc09a", #queue_name="default">
Remember: Doing this, ALL your Jobs will be executed right now on test and dev environments. If you want to enable this functionality for a single job, you will need to include the JobsExt mixin in that job only.
We solved this by calling an intermediate method which then called perform_later or perform_now depending on Rails config:
def self.perform(*args)
if Rails.application.config.perform_later
perform_later(*args)
else
perform_now(*args)
end
end
And simply updated environments configs accordingly
I have some methods that works with API of third party app. To do it on button click is no problem, but it should be permanent process.
How to run them background? And how to pause the cycle for make some other works with same API and resume the cycle after the job is done.
Now I read about ActiveJob, but its has time dependences only...
UPDATE
I've tried to make it with whenever and sidekiq, task runs, but it do nothing. Where to look for logs I can't understand.
**schedule.rb**
every 1.minute do
runner "UpdateWorker.perform_async"
end
**update_worker.rb**
class UpdateWorker
include Sidekiq::Worker
include CommonMods
def perform
logger.info "Things are happening."
logger.debug "Here's some info: #{hash.inspect}"
myMethod
end
def myMethod
....
....
....
end
end
It's not exactly what I need, but better then nothing. Can somebody explain me with examples?
UPDATE 2 After manipulating with code it's absolutely necessary to restart sidekiq . With this problem is solved, but I'm not sure that this is the best way.
You can define a job which enqueues itself:
class MyJob < ActiveJob::Base
def perform(*args)
# Do something unless some flag is raised
ensure
self.class.set(wait: 1.hour).perform_later(*args)
end
end
There are several libraries to schedule jobs on a regular basis. For example you could use to sidekiq-cron to run a job every minute.
If you want to pause it for some time, you could set a flag somewhere (Redis/database/file) and skip execution as long it is detected.
On a somewhat related note: don't use sidetiq. It was really great but it's not maintained anymore and has incompatibilities to current Sidekiq versions.
Just enqueue next execution in ensure section after job completes after checking some flag that indicates that it should.
Also i recommend adding some delay there so that you don't end up with dead loop on some error inside job
I dont know ActiveJobs, but I can recommend the whenever gem to create cron (periodic background) jobs. Basically you end up writing a rake tasks. Like this:
desc 'send digest email'
task send_digest_email: :environment do
# ... set options if any
UserMailer.digest_email_update(options).deliver!
end
I never added a rake task to itself but for repeated processing you could do somehow like this (from answers to this specific question)
Rake::Task["send_digest_email"].execute
I need to add a job to the Sidekiq queue when my Rails app starts, to update some data, but I don't know where is the best place to do it.
Right now, I've wrote this on my application.rb:
class Application < Rails::Application
config.after_initialize do
MyWorker.perform_async
end
end
But the problem is that when I run the sidekiq command it will also load the Rails stack, so I'll end up with 2 jobs on the queue.
Is there any other way of doing that? This is my first big Rails app and my first time with Sidekiq, so I don't know if I'm not understanding things correctly. That might not be the right way of doing that.
Thanks!
A better solution would be to create an initializer config/initializers/sidekiq.rb
Sidekiq.configure_client do |config|
Rails.application.config.after_initialize do
# You code goes here
end
end
We were having issues w/ Redis connections and multiple jobs being launched.
I ended up using this and it seems to be working well:
if defined?(Sidekiq)
Sidekiq.configure_server do |config|
config.on(:startup) do
already_scheduled = Sidekiq::ScheduledSet.new.any? {|job| job.klass == "MyWorker" }
MyWorker.perform_async unless already_scheduled
end
end
end
Probably foreman suits for your purposes.
I know this is old, but none of this worked for me - would still start the job several times. I came up with the following solution:
I have a Class to do the actual Job:
class InitScheduling
include Sidekiq::Worker
def perform
# your code here
end
end
And I have an inizializer, which would normally start 3 Times, every time, something loads the Rails environment. So I use the Job as a state variable that this job is already scheduled:
# code in inizilizer/your_inizilizer.rb
Rails.application.config.after_initialize do
all_jobs = Sidekiq::ScheduledSet.new
# If this is True InitScheduling is already scheduled - don't start it again
unless all_jobs.map(&:klass).include?("InitScheduling")
puts "########### InitScheduling ##############"
# give rails time to build before running this job & keeps this initialization from re-running
InitScheduling.perform_in(5.minutes)
# your code here
end
end
I am running a delayed job worker. When ever I invoke the foo method, worker prints hello.
class User
def foo
puts "Hello"
end
handle_asynchronously :foo
end
If I make some changes to the foo method, I have to restart the worker for the changes to reflect. In the development mode this can become quite tiresome.
I am trying to find a way to reload the payload class(in this case User class) for every request. I tried monkey patching the DelayedJob library to invoke require_dependency before the payload method invocation.
module Delayed::Backend::Base
def payload_object_with_reload
if Rails.env.development? and #payload_object_with_reload.nil?
require_dependency(File.join(Rails.root, "app", "models", "user.rb"))
end
#payload_object_with_reload ||= payload_object_without_reload
end
alias_method_chain :payload_object, :reload
end
This approach doesn't work as the classes registered using require_dependency needs to be reloaded before the invocation and I haven't figured out how to do it. I spent some time reading the dispatcher code to figure out how Rails reloads the classes for every request. I wasn't able to locate the reload code.
Has anybody tried this before? How would you advise me to proceed? Or do you have any pointers for locating the Rails class reload code?
I managed to find a solution. I used ActiveSupport::Dependencies.clear method to clear the loaded classes.
Add a file called config/initializers/delayed_job.rb
Delayed::Worker.backend = :active_record
if Rails.env.development?
module Delayed::Backend::Base
def payload_object_with_reload
if #payload_object_with_reload.nil?
ActiveSupport::Dependencies.clear
end
#payload_object_with_reload ||= payload_object_without_reload
end
alias_method_chain :payload_object, :reload
end
end
As of version 4.0.6, DelayedJob reloads automatically if Rails.application.config.cache_classes is set to false:
In development mode, if you are using Rails 3.1+, your application code will automatically reload every 100 jobs or when the queue finishes. You no longer need to restart Delayed Job every time you update your code in development.
This looks like it solves your problem without the alias_method hackery:
https://github.com/Viximo/delayed_job-rails_reloader