diff --git a/app/models/admin_dashboard_data.rb b/app/models/admin_dashboard_data.rb index 596443558b6..09e7b5af642 100644 --- a/app/models/admin_dashboard_data.rb +++ b/app/models/admin_dashboard_data.rb @@ -9,7 +9,7 @@ class AdminDashboardData def as_json @json ||= { reports: REPORTS.map { |type| Report.find(type) }, - problems: [rails_env_check, host_names_check, gc_checks, clockwork_check].compact + problems: [rails_env_check, host_names_check, gc_checks, sidekiq_check || clockwork_check].compact }.merge( SiteSetting.version_checks? ? {version_check: DiscourseUpdates.check_version} : {} ) @@ -27,6 +27,11 @@ class AdminDashboardData I18n.t("dashboard.gc_warning") if ENV['RUBY_GC_MALLOC_LIMIT'].nil? end + def sidekiq_check + last_job_performed_at = Jobs.last_job_performed_at + I18n.t('dashboard.sidekiq_warning') if Jobs.queued > 0 and (last_job_performed_at.nil? or last_job_performed_at < 2.minutes.ago) + end + def clockwork_check I18n.t('dashboard.clockwork_warning') unless Jobs::ClockworkHeartbeat.is_clockwork_running? end diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index 86d409c3e95..8124f6796ae 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -285,6 +285,7 @@ en: host_names_warning: "Your config/database.yml file is using the default localhost hostname. Update it to use your site's hostname." gc_warning: 'Your server is using default ruby garbage collection parameters, which will not give you the best performance. Read this topic on performance tuning: Tuning Ruby and Rails for Discourse.' clockwork_warning: 'Clockwork is not running. Ensure that a clockwork process is always running so that important jobs can be scheduled. Learn about clockwork here.' + sidekiq_warning: 'Sidekiq is not running. Many tasks, like sending emails, are executed asynchronously by sidekiq. Please ensure at least one sidekiq process is running. Learn about Sidekiq here.' site_settings: default_locale: "The default language of this Discourse instance (ISO 639-1 Code)" diff --git a/lib/jobs.rb b/lib/jobs.rb index 3fceb1c86af..a2bd698772e 100644 --- a/lib/jobs.rb +++ b/lib/jobs.rb @@ -1,5 +1,16 @@ module Jobs + def self.queued + Sidekiq::Stats.new.enqueued + end + + def self.last_job_performed_at + Sidekiq.redis do |r| + int = r.get('last_job_perform_at') + int ? Time.at(int.to_i) : nil + end + end + class Base include Sidekiq::Worker @@ -18,6 +29,12 @@ module Jobs def perform(opts={}) opts = opts.with_indifferent_access + if SiteSetting.queue_jobs? + Sidekiq.redis do |r| + r.set('last_job_perform_at', Time.now.to_i) + end + end + if opts.delete(:sync_exec) if opts.has_key?(:current_site_id) && opts[:current_site_id] != RailsMultisite::ConnectionManagement.current_db raise ArgumentError.new("You can't connect to another database when executing a job synchronously.") diff --git a/spec/components/jobs_spec.rb b/spec/components/jobs_spec.rb index 000cf2d41ac..b769c4c1f9b 100644 --- a/spec/components/jobs_spec.rb +++ b/spec/components/jobs_spec.rb @@ -7,7 +7,7 @@ describe Jobs do describe 'when queue_jobs is true' do before do - SiteSetting.expects(:queue_jobs?).returns(true) + SiteSetting.expects(:queue_jobs?).at_least_once.returns(true) end it 'enqueues a job in sidekiq' do @@ -36,7 +36,7 @@ describe Jobs do describe 'when queue_jobs is false' do before do - SiteSetting.expects(:queue_jobs?).returns(false) + SiteSetting.expects(:queue_jobs?).at_least_once.returns(false) end it "doesn't enqueue in sidekiq" do diff --git a/spec/models/admin_dashboard_data_spec.rb b/spec/models/admin_dashboard_data_spec.rb index e285879eaa9..5c4c64e6fd0 100644 --- a/spec/models/admin_dashboard_data_spec.rb +++ b/spec/models/admin_dashboard_data_spec.rb @@ -68,4 +68,38 @@ describe AdminDashboardData do end end + describe 'sidekiq_check' do + subject { AdminDashboardData.new.sidekiq_check } + + it 'returns nil when sidekiq processed a job recently' do + Jobs.stubs(:last_job_performed_at).returns(1.minute.ago) + Jobs.stubs(:queued).returns(0) + subject.should be_nil + end + + it 'returns nil when last job processed was a long time ago, but no jobs are queued' do + Jobs.stubs(:last_job_performed_at).returns(7.days.ago) + Jobs.stubs(:queued).returns(0) + subject.should be_nil + end + + it 'returns nil when no jobs have ever been processed, but no jobs are queued' do + Jobs.stubs(:last_job_performed_at).returns(nil) + Jobs.stubs(:queued).returns(0) + subject.should be_nil + end + + it 'returns a string when no jobs were processed recently and some jobs are queued' do + Jobs.stubs(:last_job_performed_at).returns(20.minutes.ago) + Jobs.stubs(:queued).returns(1) + subject.should_not be_nil + end + + it 'returns a string when no jobs have ever been processed, and some jobs are queued' do + Jobs.stubs(:last_job_performed_at).returns(nil) + Jobs.stubs(:queued).returns(1) + subject.should_not be_nil + end + end + end \ No newline at end of file