diff --git a/app/controllers/health_checks_controller.rb b/app/controllers/health_checks_controller.rb index cb5b2f39cf..60bab2d0f5 100644 --- a/app/controllers/health_checks_controller.rb +++ b/app/controllers/health_checks_controller.rb @@ -45,7 +45,11 @@ def check_database end def check_redis - Redis.new.ping + if Greenlight::Application.config.cache_store == :null_store + Redis.new.ping + else + Redis.new(Greenlight::Application.config.cache_store[1].except(:adapter, :channel_prefix)).ping + end rescue StandardError => e raise "Unable to connect to Redis - #{e}" end diff --git a/bin/start b/bin/start index 0952481fd7..6357a8f81e 100755 --- a/bin/start +++ b/bin/start @@ -17,11 +17,13 @@ if [ "$RAILS_ENV" = "production" ]; then sleep 1 done - while ! nc -zw3 $RDHOST $RDPORT - do - echo "Waiting for redis to start up ..." - sleep 1 - done + if [ -z "$REDIS_SENTINEL" ]; then + while ! nc -zw3 $RDHOST $RDPORT + do + echo "Waiting for redis to start up ..." + sleep 1 + done + fi fi rails assets:precompile diff --git a/config/cable.yml b/config/cable.yml index 33181ad1ea..6067880c6d 100644 --- a/config/cable.yml +++ b/config/cable.yml @@ -22,5 +22,9 @@ test: production: adapter: redis - url: <%= ENV.fetch("REDIS_URL", "") %> + url: <%= ENV.fetch("REDIS_URL", nil) || "redis://mymaster" %> + sentinels: <%= ENV.fetch("REDIS_SENTINEL", "") %> + name: mymaster + role: master + namespace: greenlight3 channel_prefix: greenlight_production diff --git a/config/environments/production.rb b/config/environments/production.rb index ac6eaad8c3..c63768ad17 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -18,6 +18,43 @@ require 'active_support/core_ext/integer/time' +class String + def string_between_markers(marker1, marker2) + self[/#{Regexp.escape(marker1)}(.*?)#{Regexp.escape(marker2)}/m, 1] + end +end + +def parse_sentinels(sentinel_str) + work_str = sentinel_str.gsub(/[[:space:]]/, '').delete_prefix('[').delete_suffix(']') # remove all white space and surrounding [] + sentinel_arr = [] + until work_str.empty? + # cut string with hash content + sub_str = work_str.string_between_markers('{', '}') + # convert that string to hash (while converting keys to symbols and + # values to integer, if possible, else make it string without single quotes) + sub_arr = sub_str.split(',').map do |h| + h1, h2 = h.split(':') + { h1.to_sym => h2.match?(/\D/) ? h2.delete("'") : h2.to_i } + end + sub_hash = sub_arr.reduce(:merge) + sentinel_arr.append(sub_hash) + # remove hash string from current working string and delete any surrounding commas + work_str.slice! "{#{sub_str}}" + work_str = work_str.delete_prefix(',').delete_suffix(',') + end + sentinel_arr +end + +def config_cache_store + if ENV.fetch('REDIS_SENTINEL', nil).present? + [:redis_cache_store, { sentinels: parse_sentinels(ENV.fetch('REDIS_SENTINEL')), + url: ENV.fetch('REDIS_URL', nil) || 'redis://mymaster', + name: 'mymaster', role: :master }] + else + [:redis_cache_store, { url: ENV.fetch('REDIS_URL', nil) }] + end +end + Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. @@ -111,7 +148,7 @@ config.log_tags = [:request_id] # Use a different cache store in production. - config.cache_store = :redis_cache_store, { url: ENV.fetch('REDIS_URL', nil) } + config.cache_store = config_cache_store # Use a real queuing backend for Active Job (and separate queues per environment). config.active_job.queue_adapter = :async # TODO: Configure :resque diff --git a/sample.env b/sample.env index e3761dfebd..1fa3a47788 100644 --- a/sample.env +++ b/sample.env @@ -15,10 +15,13 @@ BIGBLUEBUTTON_SECRET= # E.g. postgres://postgres:password@postgres:5432/greenlight-v3-production DATABASE_URL= -### REDIS CACHE URL -# Must be in the format redis://host:port +### REDIS CACHE +# REDIS_URL: Must be in the format redis://host:port # E.g. redis://redis:6379 +# REDIS_SENTINEL: Must be an array of host, port pairs. In this case leave REDIS_URL blank or set it to e.g. redis://mymaster. +# E.g. [{host: 'host1', port: 26379}, {host: 'host2', port: 26379}, {host: 'host3', port: 26379}] REDIS_URL= +REDIS_SENTINEL= ### OPTIONAL ENV VARS