From c997091166ba1801eea3a587c913b020b9b84ce4 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Wed, 3 May 2017 23:18:13 +0200 Subject: [PATCH] Clean up redis configuration. Allow using REDIS_URL to set advanced (#2732) connection options instead of setting REDIS_HOST etc individually Close #1986 --- .env.production.sample | 3 ++- config/cable.yml | 10 --------- config/environments/development.rb | 8 ------- config/environments/production.rb | 21 ------------------ config/initializers/ostatus.rb | 9 ++++---- config/initializers/redis.rb | 20 +++++++++++++++--- config/initializers/sidekiq.rb | 9 +++----- streaming/index.js | 34 ++++++++++++++++++++++++------ 8 files changed, 53 insertions(+), 61 deletions(-) delete mode 100644 config/cable.yml diff --git a/.env.production.sample b/.env.production.sample index ca0314824..058e794b4 100644 --- a/.env.production.sample +++ b/.env.production.sample @@ -1,7 +1,8 @@ # Service dependencies +# You may set REDIS_URL instead for more advanced options REDIS_HOST=redis REDIS_PORT=6379 -# REDIS_DB=0 +# You may set DB_URL instead for more advanced options DB_HOST=db DB_USER=postgres DB_NAME=postgres diff --git a/config/cable.yml b/config/cable.yml deleted file mode 100644 index 34759a772..000000000 --- a/config/cable.yml +++ /dev/null @@ -1,10 +0,0 @@ -development: - adapter: redis - url: redis://localhost:6379/1 - -test: - adapter: async - -production: - adapter: redis - url: redis://<%= ENV['REDIS_PASSWORD'] ? ':' + ENV['REDIS_PASSWORD'] + '@' : '' %><%= ENV['REDIS_HOST'] || 'localhost' %>:<%= ENV['REDIS_PORT'] || 6379 %>/1 diff --git a/config/environments/development.rb b/config/environments/development.rb index 4b25ab1a8..58e8a0728 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -16,14 +16,6 @@ Rails.application.configure do if Rails.root.join('tmp/caching-dev.txt').exist? config.action_controller.perform_caching = true - config.cache_store = :redis_store, { - host: ENV['REDIS_HOST'] || 'localhost', - port: ENV['REDIS_PORT'] || 6379, - db: 0, - namespace: 'cache', - expires_in: 1.minute, - } - config.public_file_server.headers = { 'Cache-Control' => 'public, max-age=172800', } diff --git a/config/environments/production.rb b/config/environments/production.rb index 1f2b5e05d..3cbf5f899 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -45,27 +45,6 @@ Rails.application.configure do # Use a different logger for distributed setups. # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new) - # Parse and split the REDIS_URL if passed (used with hosting platforms such as Heroku). - # Set ENV variables because they are used elsewhere. - if ENV['REDIS_URL'] - redis_url = URI.parse(ENV['REDIS_URL']) - ENV['REDIS_HOST'] = redis_url.host - ENV['REDIS_PORT'] = redis_url.port.to_s - ENV['REDIS_PASSWORD'] = redis_url.password - db_num = redis_url.path[1..-1] - ENV['REDIS_DB'] = db_num if db_num.present? - end - - # Use a different cache store in production. - config.cache_store = :redis_store, { - host: ENV.fetch('REDIS_HOST') { 'localhost' }, - port: ENV.fetch('REDIS_PORT') { 6379 }, - password: ENV.fetch('REDIS_PASSWORD') { false }, - db: ENV.fetch('REDIS_DB') { 0 }, - namespace: 'cache', - expires_in: 10.minutes, - } - # Enable serving of images, stylesheets, and JavaScripts from an asset server. # config.action_controller.asset_host = 'http://assets.example.com' diff --git a/config/initializers/ostatus.rb b/config/initializers/ostatus.rb index 155d0a9f1..a905a032c 100644 --- a/config/initializers/ostatus.rb +++ b/config/initializers/ostatus.rb @@ -1,9 +1,9 @@ # frozen_string_literal: true -port = ENV.fetch('PORT') { 3000 } -host = ENV.fetch('LOCAL_DOMAIN') { "localhost:#{port}" } +port = ENV.fetch('PORT') { 3000 } +host = ENV.fetch('LOCAL_DOMAIN') { "localhost:#{port}" } web_host = ENV.fetch('WEB_DOMAIN') { host } -https = ENV['LOCAL_HTTPS'] == 'true' +https = ENV['LOCAL_HTTPS'] == 'true' Rails.application.configure do config.x.local_domain = host @@ -15,7 +15,6 @@ Rails.application.configure do config.x.streaming_api_base_url = 'http://localhost:4000' if Rails.env.production? - config.action_cable.allowed_request_origins = ["http#{https ? 's' : ''}://#{web_host}"] - config.x.streaming_api_base_url = ENV.fetch('STREAMING_API_BASE_URL') { "http#{https ? 's' : ''}://#{web_host}" } + config.x.streaming_api_base_url = ENV.fetch('STREAMING_API_BASE_URL') { "http#{https ? 's' : ''}://#{web_host}" } end end diff --git a/config/initializers/redis.rb b/config/initializers/redis.rb index 3660c4a9b..dd7fa112e 100644 --- a/config/initializers/redis.rb +++ b/config/initializers/redis.rb @@ -1,8 +1,22 @@ # frozen_string_literal: true +if ENV['REDIS_URL'].blank? + password = ENV.fetch('REDIS_PASSWORD') { '' } + host = ENV.fetch('REDIS_HOST') { 'localhost' } + port = ENV.fetch('REDIS_PORT') { 6379 } + db = ENV.fetch('REDIS_DB') { 0 } + + ENV['REDIS_URL'] = "redis://#{password.blank? ? '' : ":#{password}@"}#{host}:#{port}/#{db}" +end + Redis.current = Redis.new( - host: ENV.fetch('REDIS_HOST') { 'localhost' }, - port: ENV.fetch('REDIS_PORT') { 6379 }, - password: ENV.fetch('REDIS_PASSWORD') { false }, + url: ENV['REDIS_URL'], driver: :hiredis ) + +Rails.application.configure do + config.cache_store = :redis_store, ENV['REDIS_URL'], { + namespace: 'cache', + expires_in: 10.minutes, + } +end diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb index 8ae3bd5a2..3d2e4741d 100644 --- a/config/initializers/sidekiq.rb +++ b/config/initializers/sidekiq.rb @@ -1,12 +1,9 @@ -host = ENV.fetch('REDIS_HOST') { 'localhost' } -port = ENV.fetch('REDIS_PORT') { 6379 } -password = ENV.fetch('REDIS_PASSWORD') { false } -db = ENV.fetch('REDIS_DB') { 0 } +# frozen_string_literal: true Sidekiq.configure_server do |config| - config.redis = { host: host, port: port, db: db, password: password } + config.redis = { url: ENV['REDIS_URL'] } end Sidekiq.configure_client do |config| - config.redis = { host: host, port: port, db: db, password: password } + config.redis = { url: ENV['REDIS_URL'] } end diff --git a/streaming/index.js b/streaming/index.js index 3be844037..18da58e49 100644 --- a/streaming/index.js +++ b/streaming/index.js @@ -16,23 +16,42 @@ dotenv.config({ path: env === 'production' ? '.env.production' : '.env' }) -if (cluster.isMaster) { - // cluster master +const dbUrlToConfig = (dbUrl) => { + if (!dbUrl) { + return {} + } + const params = url.parse(dbUrl) + const auth = params.auth ? params.auth.split(':') : [] + + return { + user: auth[0], + password: auth[1], + host: params.hostname, + port: params.port, + database: params.pathname ? params.pathname.split('/')[1] : null, + ssl: true + } +} + +if (cluster.isMaster) { + // Cluster master const core = +process.env.STREAMING_CLUSTER_NUM || (env === 'development' ? 1 : Math.max(os.cpus().length - 1, 1)) + const fork = () => { const worker = cluster.fork(); + worker.on('exit', (code, signal) => { log.error(`Worker died with exit code ${code}, signal ${signal} received.`); setTimeout(() => fork(), 0); }); }; + for (let i = 0; i < core; i++) fork(); + log.info(`Starting streaming API server master with ${core} workers`) - } else { - // cluster worker - + // Cluster worker const pgConfigs = { development: { database: 'mastodon_development', @@ -51,14 +70,15 @@ if (cluster.isMaster) { } const app = express() - const pgPool = new pg.Pool(pgConfigs[env]) + const pgPool = new pg.Pool(Object.assign(dbUrlToConfig(process.env.DB_URL), pgConfigs[env])) const server = http.createServer(app) const wss = new WebSocket.Server({ server }) const redisClient = redis.createClient({ host: process.env.REDIS_HOST || '127.0.0.1', port: process.env.REDIS_PORT || 6379, - password: process.env.REDIS_PASSWORD + password: process.env.REDIS_PASSWORD, + url: process.env.REDIS_URL || null }) const subs = {}