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