diff --git a/web/Gemfile b/web/Gemfile index d6845afd6a..2adb95f52d 100644 --- a/web/Gemfile +++ b/web/Gemfile @@ -20,8 +20,10 @@ gem "elasticsearch-rails" gem "govuk_notify_rails" gem "jbuilder", "~> 2.8" gem "keycloak" +gem "lograge" gem "mini_magick" gem "pg", "~> 1.1" +gem "pghero" gem "puma", "~> 3.0" gem "pundit" gem "rails", "~> 5.2" @@ -30,6 +32,7 @@ gem "rubyzip", ">= 1.2.1" gem "sass-rails", "~> 5.0" gem "sidekiq" gem "slim-rails" +gem "slowpoke" gem "strong_migrations" gem "turbolinks", "~> 5" gem "uglifier", ">= 1.3.0" diff --git a/web/Gemfile.lock b/web/Gemfile.lock index b918bd220f..72def99c86 100644 --- a/web/Gemfile.lock +++ b/web/Gemfile.lock @@ -179,6 +179,11 @@ GEM rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) ruby_dep (~> 1.2) + lograge (0.10.0) + actionpack (>= 4) + activesupport (>= 4) + railties (>= 4) + request_store (~> 1.0) loofah (2.2.3) crass (~> 1.0.2) nokogiri (>= 1.5.9) @@ -208,6 +213,8 @@ GEM parser (2.5.3.0) ast (~> 2.4.0) pg (1.1.3) + pghero (2.2.0) + activerecord powerpack (0.1.2) public_suffix (3.0.3) puma (3.12.0) @@ -218,6 +225,7 @@ GEM rack rack-test (1.1.0) rack (>= 1.0, < 3) + rack-timeout (0.4.2) rails (5.2.1) actioncable (= 5.2.1) actionmailer (= 5.2.1) @@ -250,6 +258,8 @@ GEM redcarpet (3.4.0) redis (4.0.3) regexp_parser (1.2.0) + request_store (1.4.1) + rack (>= 1.4) rest-client (2.0.2) http-cookie (>= 1.0.2, < 2.0) mime-types (>= 1.16, < 4.0) @@ -317,6 +327,10 @@ GEM rubocop (>= 0.50.0) slim (>= 3.0, < 5.0) sysexits (~> 1.1) + slowpoke (0.2.1) + actionpack + rack-timeout (>= 0.3.0, < 0.5.0) + railties solargraph (0.28.4) coderay (~> 1.1) eventmachine (~> 1.2, >= 1.2.5) @@ -408,8 +422,10 @@ DEPENDENCIES jbuilder (~> 2.8) keycloak listen (~> 3.1.5) + lograge mini_magick pg (~> 1.1) + pghero puma (~> 3.0) pundit rails (~> 5.2) @@ -425,6 +441,7 @@ DEPENDENCIES simplecov-console slim-rails slim_lint + slowpoke solargraph spring spring-watcher-listen (~> 2.0.0) diff --git a/web/README.md b/web/README.md index 2d58de1e8a..347ed6d85a 100644 --- a/web/README.md +++ b/web/README.md @@ -120,4 +120,9 @@ See the AWS account section in [the root README](../README.md#aws) to get these See the Companies House account section in [the root README](../README.md#companies-house) to get this value. + cf set-env mspsds-web PGHERO_USERNAME XXX + cf set-env mspsds-web PGHERO_PASSWORD XXX + +This sets the http auth username and password for access to the pgHero dashboard. See confluence for values. + The app can then be started using `cf restart mspsds-web`. diff --git a/web/app/controllers/errors_controller.rb b/web/app/controllers/errors_controller.rb index c000e9c972..38930bbdaf 100644 --- a/web/app/controllers/errors_controller.rb +++ b/web/app/controllers/errors_controller.rb @@ -6,4 +6,8 @@ def not_found def internal_server_error render status: :internal_server_error end + + def timeout + render :internal_server_error, status: :service_unavailable + end end diff --git a/web/config/application.rb b/web/config/application.rb index 97e6c12b6d..d3c63a714e 100644 --- a/web/config/application.rb +++ b/web/config/application.rb @@ -27,5 +27,9 @@ class Application < Rails::Application config.time_zone = "Europe/London" config.exceptions_app = self.routes + + # This is the requests' timeout value in seconds. 15 is the default set by Slowpoke + # Dev environments need longer due to occasional asset compilation + Slowpoke.timeout = Rails.env.production? ? 15 : 120 end end diff --git a/web/config/database.yml b/web/config/database.yml index e32d4dd70a..5fe1549b59 100644 --- a/web/config/database.yml +++ b/web/config/database.yml @@ -21,6 +21,9 @@ default: &default username: postgres password: pool: 5 + connect_timeout: 2 + variables: + statement_timeout: 250 development: diff --git a/web/config/environments/production.rb b/web/config/environments/production.rb index 202e8555a1..e195b20b58 100644 --- a/web/config/environments/production.rb +++ b/web/config/environments/production.rb @@ -35,6 +35,8 @@ # Enable serving of images, stylesheets, and JavaScripts from an asset server. # config.action_controller.asset_host = 'http://assets.example.com' + config.action_controller.default_url_options = { host: JSON.parse(ENV["VCAP_APPLICATION"])["application_uris"].first } + # Specifies the header that your server uses for sending files. # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX diff --git a/web/config/initializers/lograge.rb b/web/config/initializers/lograge.rb new file mode 100644 index 0000000000..bebd453f37 --- /dev/null +++ b/web/config/initializers/lograge.rb @@ -0,0 +1,5 @@ +# Be sure to restart your server when you modify this file. + +Rails.application.configure do + config.lograge.enabled = true +end diff --git a/web/config/routes.rb b/web/config/routes.rb index 00f6aac462..8821187708 100644 --- a/web/config/routes.rb +++ b/web/config/routes.rb @@ -92,6 +92,10 @@ match "/404", to: "errors#not_found", via: :all match "/500", to: "errors#internal_server_error", via: :all + # This is the page that will show for timeouts, currently showing the same as an internal error + match "/503", to: "errors#timeout", via: :all + + mount PgHero::Engine, at: "pghero" root to: redirect(path: "/investigations") end diff --git a/web/test/controllers/errors_controller_test.rb b/web/test/controllers/errors_controller_test.rb index 0bd27e38bb..d34f7361ca 100644 --- a/web/test/controllers/errors_controller_test.rb +++ b/web/test/controllers/errors_controller_test.rb @@ -18,4 +18,9 @@ class ErrorsControllerTest < ActionDispatch::IntegrationTest get "/500" assert_response :internal_server_error end + + test "should get service_unavailable" do + get "/503" + assert_response :service_unavailable + end end diff --git a/web/test/db/timeout_test.rb b/web/test/db/timeout_test.rb new file mode 100644 index 0000000000..312bc95e45 --- /dev/null +++ b/web/test/db/timeout_test.rb @@ -0,0 +1,9 @@ +require "test_helper" + +class TimeoutTest < ActiveSupport::TestCase + test "long queries timeout" do + assert_raises do + ActiveRecord::Base.connection.execute("SELECT pg_sleep(20);") + end + end +end