I found these logs here that I'm trying to duplicate in my code, specifically the start time and done times:
PID-- ThreadID----- LLvl YourKlass- JobID--------
TID-oveahmcxw INFO: HardWorker JID-oveaivtrg start
TID-oveajt7ro INFO: HardWorker JID-oveaish94 start
TID-oveahmcxw INFO: HardWorker JID-oveaivtrg done: 10.003 sec
TID-oveajt7ro INFO: HardWorker JID-oveaish94 done: 10.002 sec
Does anyone know how to access these values? I know there is a jid that gets popluated (which I'm using), but I can't for the life of me find any documentation on where start and done come from.
You can add logging by using a middleware:
class JobMiddleware
def call(worker, msg, queue)
Rails.logger.info "Job #{worker.jid} stated at #{Time.now}"
yield
Rails.logger.info "Job #{worker.jid} ended at #{Time.now}"
end
end
Add this to config/initializers/sidekiq.rb and restart your sidekiq workers.
Click here for more info about sidekiq middlewares
Related
so I want to Implement sidekiq_retries_exhausted in such a way that it triggers automatically when all retries failed Globally and this behavior should be for all workers in my codebase
currently, I have to write sidekiq_retries_exhausted every time in each worker but what I want to understand is there any way so that sidekiq_retries_exhausted triggers when all retries failed and I don't have to write this function on each worker
so in short I want to overwrite local sidekiq_retries_exhausted and making it globally available like a kind of middleware so that it triggers automatically when the worker failed it all retries and I don't have to write this in every worker
currently, it is implemented like this in every worker
sidekiq_retries_exhausted do |msg, error|
AlertOnRetriesExhaustedUtils.send_alert_on_retries_exhausted(msg, error)
end
In sidekiq v5.1 introduced global callback death_handlers when job dies
Death Notification
The sidekiq_retries_exhausted callback is specific to a Worker class. Starting in v5.1, Sidekiq can also fire a global callback when a job dies:
# this goes in your initializer
Sidekiq.configure_server do |config|
config.death_handlers << ->(job, ex) do
puts "Uh oh, #{job['class']} #{job["jid"]} just died with error #{ex.message}."
end
end
I could have 3 jobs pending in the queue, as soon as the first Job is done, all remaining workers get executed at the same time. Why is that? I want each worker to get a lock and make the other jobs wait, in a serialized-fashion.
class StuffWorker
include Sidekiq::Worker
sidekiq_options lock: :until_executed,
lock_timeout: 999,
lock_info: true,
lock_args_method: :lock_args
def self.lock_args(args)
[args[0], args[1]]
end
def perform(company_id, person_id)
sleep 10
logger.info "STARTING IT! at #{DateTime.now.strftime('%H:%M:%S')}"
end
end
Produces the following:
JID-ce8c692b5341adb7a24584ab INFO: STARTING IT! at 23:29:52
JID-ce8c692b5341adb7a24584ab INFO: done: 10.728 sec
JID-ca8dac1cbd7cbaf5d87f6096 INFO: STARTING IT! at 23:30:02
JID-463bfe792775e1412d3c0af7 INFO: STARTING IT! at 23:30:02
JID-463bfe792775e1412d3c0af7 INFO: done: 17.754 sec
JID-ca8dac1cbd7cbaf5d87f6096 INFO: done: 14.024 sec
Possible, what you want is a runtime lock only, not queue lock. You have to use while_executing lock type https://github.com/mhenrixon/sidekiq-unique-jobs#while-executing.
I have 2 Sidekiq workers:
Foo:
# frozen_string_literal: true
class FooWorker
include Sidekiq::Worker
sidekiq_options queue: :foo
def perform
loop do
File.open(File.join(Rails.root, 'foo.txt'), 'w') { |file| file.write('FOO') }
end
end
end
Bar:
# frozen_string_literal: true
class BarWorker
include Sidekiq::Worker
sidekiq_options queue: :bar
def perform
loop do
File.open(File.join(Rails.root, 'bar.txt'), 'w') { |file| file.write('BAR') }
end
end
end
Which has pretty the same functionality, both runs on different queues and the yaml file looks like this:
---
:queues:
- foo
- bar
development:
:concurrency: 5
The problem is, even both are running and showing in the Busy page of Sidekiq UI, only one of them will actually create a file and put contents in. Shouldn't Sidekiq be multi-threaded?
Update:
this happens only on my machine
i created a new project with rails new and same
i cloned a colleague project and ran his sidekiq and is working!!!
i used his sidekiq version, not working!
New Update:
this happens also on my colleague machine if he clone my project
if I run 2 jobs with a finite loop ( like 10 times do something with a sleep), first job will be executed and then the second, but after the second finishes and start again both will work on same time as expected -- everyone who cloned the project from: github.com/ArayB/sidekiq-test encountered the problem.
It's not an issue with Sidekiq. It's an issue somewhere in Ruby/MRI/Thread/GIL. Google for more info, but my understanding is that sometimes threads aren't real threads (see "green threads") so really just simulate threading. The important thing is that only one thread can execute at a time.
It's interesting that with only two threads the system isn't giving time to the second thread. No idea why, but it must realize it's mistake when you run it again.
Interestingly if you run your same app but instead fire off 10 TestWorkers (and tweak the output so you can tell the difference) sidekiq will run all 10 "at once".
10.times {|i| TestWorker.perform_async(i) }
Here is the tweaked worker. Be sure to flush the output cause that can also cause issues with threading and TTY buffering not reflecting reality.
class TestWorker
include Sidekiq::Worker
def perform(n)
10.times do |i|
puts "#{n} - #{i} - #{Time.current}"
$stdout.flush
sleep 1
end
end
end
Some interesting links:
https://en.wikipedia.org/wiki/Green_threads
http://ruby-doc.org/core-2.4.1/Thread.html#method-c-pass
https://github.com/ruby/ruby/blob/v2_4_1/thread.c
Does ruby have real multithreading?
I can't figure out what's going on with sidekiq. I could've swore this worked yesterday, but I must have been dreaming.
Here's my worker class:
class TagPostWorker
include Sidekiq::Worker
sidekiq_options queue: "tag"
sidekiq_options retry: false
def perform(options = {})
current_user = User.find(options[:user_id])
end
end
I've tried running this command on my show method in the Post:
TagPostWorker.perform_async({:user_id => current_user.id})
But I get this error:
2013-08-17T22:45:45Z 4029 TID-ors6jfr54 TagPostWorker JID-ae203958bb3bcee01c8f83ef INFO: start
2013-08-17T22:45:45Z 4029 TID-ors6jfr54 TagPostWorker JID-ae203958bb3bcee01c8f83ef INFO: fail: 0.003 sec
2013-08-17T22:45:45Z 4029 TID-ors6jfr54 WARN: {"retry"=>false, "queue"=>"tag", "class"=>"TagPostWorker", "args"=>[{"user_id"=>7}], "jid"=>"ae203958bb3bcee01c8f83ef", "enqueued_at"=>1376779545.9099338}
2013-08-17T22:45:45Z 4029 TID-ors6jfr54 WARN: Couldn't find Post without an ID
I don't understand how sidekiq could even be attempting to a Post since I'm not even calling it in the perform method. Any ideas what could be going on?
Any help is appreciated.
You may want to take a look at this blog post.
It sounds ridiculous, but Sidekiq is so fast that it can run your
worker before your model even finishes saving.
Also strange, I could've sworn I restarted Rails/sidekiq.
But I renamed the worker to TagWorker, restarted Rails/sidekiq and it started working again!
I have added the following code to my initializers:
require 'delayed/worker'
Delayed::Worker.logger = ActiveSupport::BufferedLogger.new("log/#{Rails.env}_delayed_jobs.log", Rails.logger.level)
module Delayed
class Worker
def say_with_flushing(text, level = Logger::INFO)
if logger
say_without_flushing(text, level)
logger.flush
end
end
alias_method_chain :say, :flushing
end
end
But it only seems to output stuff like:
2011-09-06T14:02:04-0700: [Worker(delayed_job host:Caribbean.local pid:80322)] 1 jobs processed at 16.5391 j/s, 0 failed ...
2011-09-06T14:03:19-0700: [Worker(delayed_job host:Caribbean.local pid:80322)] MailTest completed after 0.2072
...
Is there a way to get it to actually output what it's doing? Ideally what I am trying to get is the actual outgoing email content that would normally be seen in development mode, but have it go into the delayed_job.log (regardless of rails environment).
So without having mailing go through delayed_job, in production mode the output in the log is something like:
[Mail sent to foo#foo.com]
But I want to get the actual contents as they'd be displayed if I were in development mode-- (the entire email body, subject, etc) but again in the delayed_job log because delayed_job is handling mailing emails.