diff --git a/app/controllers/health/health_controller.rb b/app/controllers/health/health_controller.rb index 99927729aca..4990c263e00 100644 --- a/app/controllers/health/health_controller.rb +++ b/app/controllers/health/health_controller.rb @@ -5,6 +5,7 @@ class HealthController < AbstractHealthController def health_checker checkers = { database: DatabaseHealthChecker, + redis_session: RedisSessionHealthChecker, account_reset: AccountResetHealthChecker, } MultiHealthChecker.new(**checkers) diff --git a/app/controllers/health/redis_session_controller.rb b/app/controllers/health/redis_session_controller.rb new file mode 100644 index 00000000000..1cec418f771 --- /dev/null +++ b/app/controllers/health/redis_session_controller.rb @@ -0,0 +1,9 @@ +module Health + class RedisSessionController < AbstractHealthController + private + + def health_checker + RedisSessionHealthChecker + end + end +end diff --git a/app/services/redis_session_health_checker.rb b/app/services/redis_session_health_checker.rb new file mode 100644 index 00000000000..9fef24d9609 --- /dev/null +++ b/app/services/redis_session_health_checker.rb @@ -0,0 +1,30 @@ +module RedisSessionHealthChecker + module_function + + # @return [HealthCheckSummary] + def check + HealthCheckSummary.new(healthy: health_write_and_read.present?, result: health_write_and_read) + rescue StandardError => err + NewRelic::Agent.notice_error(err) + HealthCheckSummary.new(healthy: false, result: err.message) + end + + # @api private + def health_write_and_read + REDIS_POOL.with do |client| + client.setex(health_record_key, health_record_ttl, "healthy at " + Time.now.iso8601) + client.get(health_record_key) + end + end + + # @api private + def health_record_key + "healthcheck_" + Socket.gethostname + end + + # @api private + def health_record_ttl + # If we can't read back within a second that is just unacceptable + 1 + end +end diff --git a/spec/services/redis_session_health_checker_spec.rb b/spec/services/redis_session_health_checker_spec.rb new file mode 100644 index 00000000000..9a260aa09a7 --- /dev/null +++ b/spec/services/redis_session_health_checker_spec.rb @@ -0,0 +1,32 @@ +require 'rails_helper' + +RSpec.describe RedisSessionHealthChecker do + describe '.check' do + subject(:summary) { RedisSessionHealthChecker.check } + + context 'when the redis session store is healthy' do + it 'returns a healthy check' do + expect(summary.healthy).to eq(true) + expect(summary.result).to start_with("healthy at ") + end + end + + context 'when the redis session store is unhealthy' do + before do + expect(RedisSessionHealthChecker).to receive(:simple_query). + and_raise(RuntimeError.new('canceling statement due to statement timeout')) + end + + it 'returns an unhealthy check' do + expect(summary.healthy).to eq(false) + expect(summary.result).to include('canceling statement due to statement timeout') + end + + it 'notifies NewRelic' do + expect(NewRelic::Agent).to receive(:notice_error) + + summary + end + end + end +end