diff --git a/app/models/admin_dashboard_data.rb b/app/models/admin_dashboard_data.rb index 07a7d4130e3..596443558b6 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].compact + problems: [rails_env_check, host_names_check, gc_checks, clockwork_check].compact }.merge( SiteSetting.version_checks? ? {version_check: DiscourseUpdates.check_version} : {} ) @@ -26,4 +26,8 @@ class AdminDashboardData def gc_checks I18n.t("dashboard.gc_warning") if ENV['RUBY_GC_MALLOC_LIMIT'].nil? end + + def clockwork_check + I18n.t('dashboard.clockwork_warning') unless Jobs::ClockworkHeartbeat.is_clockwork_running? + end end \ No newline at end of file diff --git a/config/clock.rb b/config/clock.rb index edb6078ec0b..ae1a5aaf9c4 100644 --- a/config/clock.rb +++ b/config/clock.rb @@ -17,4 +17,5 @@ module Clockwork every(1.minute, 'calculate_score') every(20.minutes, 'calculate_view_counts') every(1.day, 'version_check') + every(1.minute, 'clockwork_heartbeat') end diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index 00b87618ea1..86d409c3e95 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -284,6 +284,7 @@ en: rails_env_warning: "Your server is running in %{env} mode." 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.' site_settings: default_locale: "The default language of this Discourse instance (ISO 639-1 Code)" diff --git a/lib/jobs/clockwork_heartbeat.rb b/lib/jobs/clockwork_heartbeat.rb new file mode 100644 index 00000000000..10134ffbea9 --- /dev/null +++ b/lib/jobs/clockwork_heartbeat.rb @@ -0,0 +1,31 @@ +module Jobs + class ClockworkHeartbeat < Jobs::Base + + def execute(args) + $redis.set last_heartbeat_at_key, Time.now.to_i + end + + def self.is_clockwork_running? + if time = ClockworkHeartbeat.new.last_heartbeat_at + time > 2.minutes.ago + else + false + end + end + + def last_heartbeat_at + if time_int = $redis.get(last_heartbeat_at_key) + Time.at(time_int.to_i) + else + nil + end + end + + private + + def last_heartbeat_at_key + 'clockwork:last_heartbeat_at' + end + + end +end \ No newline at end of file diff --git a/spec/components/jobs/clockwork_heartbeat_spec.rb b/spec/components/jobs/clockwork_heartbeat_spec.rb new file mode 100644 index 00000000000..46240d327b1 --- /dev/null +++ b/spec/components/jobs/clockwork_heartbeat_spec.rb @@ -0,0 +1,26 @@ +require 'spec_helper' +require 'jobs' + +describe Jobs::ClockworkHeartbeat do + + describe '#is_clockwork_running?' do + + subject { Jobs::ClockworkHeartbeat.is_clockwork_running? } + + it 'returns false if last_heartbeat_at is nil' do + Jobs::ClockworkHeartbeat.any_instance.stubs(:last_heartbeat_at).returns(nil) + subject.should be_false + end + + it 'returns false if last_heartbeat_at is more than 2 minutes ago' do + Jobs::ClockworkHeartbeat.any_instance.stubs(:last_heartbeat_at).returns(10.minutes.ago) + subject.should be_false + end + + it 'returns true if last_heartbeat_at is more recent than 2 minutes ago' do + Jobs::ClockworkHeartbeat.any_instance.stubs(:last_heartbeat_at).returns(Time.zone.now) + subject.should be_true + end + end + +end \ No newline at end of file diff --git a/spec/models/admin_dashboard_data_spec.rb b/spec/models/admin_dashboard_data_spec.rb index 9020b955d86..e285879eaa9 100644 --- a/spec/models/admin_dashboard_data_spec.rb +++ b/spec/models/admin_dashboard_data_spec.rb @@ -54,4 +54,18 @@ describe AdminDashboardData do end end + describe 'clockwork_check' do + subject { AdminDashboardData.new.clockwork_check } + + it 'returns nil when clockwork is running' do + Jobs::ClockworkHeartbeat.stubs(:is_clockwork_running?).returns(true) + subject.should be_nil + end + + it 'returns a string when clockwork is not running' do + Jobs::ClockworkHeartbeat.stubs(:is_clockwork_running?).returns(false) + subject.should_not be_nil + end + end + end \ No newline at end of file