Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 24 additions & 4 deletions app/controllers/catalog_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,21 @@ class CatalogController < ApplicationController

include Blacklight::Catalog

SEARCH_FACET_FIELDS = [
Settings.FIELDS.INDEX_YEAR,
Settings.FIELDS.SPATIAL_COVERAGE,
Settings.FIELDS.ACCESS_RIGHTS,
Settings.FIELDS.RESOURCE_CLASS,
Settings.FIELDS.RESOURCE_TYPE,
Settings.FIELDS.FORMAT,
Settings.FIELDS.SUBJECT,
Settings.FIELDS.THEME,
Settings.FIELDS.CREATOR,
Settings.FIELDS.PUBLISHER,
Settings.FIELDS.PROVIDER,
Settings.FIELDS.GEOREFERENCED
].freeze

configure_blacklight do |config|

# Ensures that JSON representations of Solr Documents can be retrieved using
Expand Down Expand Up @@ -117,10 +132,10 @@ class CatalogController < ApplicationController
config.add_facet_field Settings.FIELDS.SOURCE, label: 'Source', show: false
config.add_facet_field Settings.FIELDS.VERSION, label: 'Is Version Of', show: false

# Have BL send all facet field names to Solr, which has been the default
# previously. Simply remove these lines if you'd rather use Solr request
# handler defaults, or have no facets.
config.add_facet_fields_to_solr_request!
# Only request facets displayed in the sidebar. The remaining configured
# facets are internal filter fields; faceting them on every search is
# expensive on production-sized Solr indexes, especially locn_geometry.
config.add_facet_fields_to_solr_request!(*SEARCH_FACET_FIELDS)

# SEARCH RESULTS FIELDS

Expand Down Expand Up @@ -287,4 +302,9 @@ def web_services
end
end
end

def track_no_content
response.set_header('X-Robots-Tag', 'noindex, nofollow')
head :no_content
end
end
7 changes: 5 additions & 2 deletions config/database.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
---

development:
url: postgres://root:root@db/geodata-dev?pool=5
url: <%= ENV['DATABASE_URL'] || 'postgres://root:root@db/geodata-dev' %>
pool: <%= ENV.fetch('DATABASE_POOL', ENV.fetch('RAILS_MAX_THREADS', 5)) %>

test:
url: postgres://root:root@db/geodata-test?pool=5
url: <%= ENV['DATABASE_URL'] || 'postgres://root:root@db/geodata-test' %>
pool: <%= ENV.fetch('DATABASE_POOL', ENV.fetch('RAILS_MAX_THREADS', 5)) %>

production:
url: <%= ENV['DATABASE_URL'] || 'postgres://root:root@db/geodata-prod' %>
pool: <%= ENV.fetch('DATABASE_POOL', ENV.fetch('RAILS_MAX_THREADS', 5)) %>
33 changes: 20 additions & 13 deletions config/initializers/okcomputer.rb
Original file line number Diff line number Diff line change
@@ -1,27 +1,34 @@
# initializers/okcomputer.rb
# Health checks configuration

require_relative '../../lib/http_head_check'
require_relative '../../lib/geo_data_health_check'

OkComputer.logger = Rails.logger
OkComputer.check_in_parallel = true

health_check_timeout = 0.9

timed_health_check = ->(check) do
GeoDataHealthCheck::TimedHealthCheck.new(check, timeout: health_check_timeout)
end

OkComputer::Registry.register 'default', timed_health_check.call(OkComputer::Registry.fetch('default'))
OkComputer::Registry.register 'database', timed_health_check.call(OkComputer::Registry.fetch('database'))

# Check that DB migrations have run
OkComputer::Registry.register 'database-migrations', OkComputer::ActiveRecordMigrationsCheck.new
OkComputer::Registry.register 'database-migrations', timed_health_check.call(OkComputer::ActiveRecordMigrationsCheck.new)

# Check the Solr connection
# Requires the ping handler on the solr core (<core>/admin/ping).
core_baseurl = Blacklight.default_index.connection.uri.to_s.chomp('/')
OkComputer::Registry.register 'solr', OkComputer::SolrCheck.new(core_baseurl)

# Perform a Head request to check geoserver endpoint
geoserver_url = Rails.configuration.x.servers[:geoserver]
OkComputer::Registry.register 'geoserver', GeoDataHealthCheck::HttpHeadCheck.new(geoserver_url)
OkComputer::Registry.register 'solr', timed_health_check.call(OkComputer::SolrCheck.new(core_baseurl, 1))

# Perform a Head request to check secure_geoserver endpoint
geoserver_secure_url = Rails.configuration.x.servers[:geoserver_secure]
OkComputer::Registry.register 'geoserver_secure', GeoDataHealthCheck::HttpHeadCheck.new(geoserver_secure_url)
{
geoserver: Rails.configuration.x.servers[:geoserver],
geoserver_secure: Rails.configuration.x.servers[:geoserver_secure],
spatial_server: Rails.configuration.x.servers[:spatial_server]
}.each do |name, url|
next if url.blank?

# Perform a Head request to check spatial server endpoint
spatial_server_url = Rails.configuration.x.servers[:spatial_server]
OkComputer::Registry.register 'spatial_server', GeoDataHealthCheck::HttpHeadCheck.new(spatial_server_url)
OkComputer::Registry.register name.to_s, timed_health_check.call(GeoDataHealthCheck::HttpHeadCheck.new(url, health_check_timeout))
end
1 change: 1 addition & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

resource :catalog, only: [:index], as: 'catalog', path: '/catalog', controller: 'catalog' do
concerns :searchable
get ':id/track', action: :track_no_content, as: :track_no_content
end

devise_for :users, controllers: { omniauth_callbacks: 'omniauth_callbacks' }
Expand Down
10 changes: 9 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,15 @@ services:
stop_signal: SIGQUIT
stop_grace_period: 15s
environment:
- DATABASE_URL=postgres://root:root@db/geodata-dev?pool=5
- RAILS_ENV=${RAILS_ENV:-production}
- RAILS_LOG_TO_STDOUT=${RAILS_LOG_TO_STDOUT:-true}
- RAILS_SERVE_STATIC_FILES=${RAILS_SERVE_STATIC_FILES:-true}
- SECRET_KEY_BASE=${SECRET_KEY_BASE:-development-secret-key-base}
- MIN_THREADS=${MIN_THREADS:-1}
- RAILS_MAX_THREADS=${RAILS_MAX_THREADS:-5}
- PUMA_WORKERS=${PUMA_WORKERS:-2}
- DATABASE_POOL=${DATABASE_POOL:-${RAILS_MAX_THREADS:-5}}
- DATABASE_URL=postgres://root:root@db/geodata-dev
- SOLR_URL=http://solr:8983/solr/geodata-test
volumes:
- ./:/opt/app:delegated
Expand Down
6 changes: 6 additions & 0 deletions lib/geo_data_health_check.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
require_relative 'geo_data_health_check/connection_failed_error'
require_relative 'geo_data_health_check/http_head_check'
require_relative 'geo_data_health_check/timed_health_check'

module GeoDataHealthCheck
end
3 changes: 3 additions & 0 deletions lib/geo_data_health_check/connection_failed_error.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module GeoDataHealthCheck
class ConnectionFailedError < StandardError; end
end
84 changes: 84 additions & 0 deletions lib/geo_data_health_check/http_head_check.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
require 'net/http'
require 'openssl'
require 'uri'

require_relative 'connection_failed_error'

module GeoDataHealthCheck
class HttpHeadCheck < OkComputer::Check
DEFAULT_REQUEST_TIMEOUT = 5
SUCCESS_MESSAGE = 'Http head check successful.'.freeze
SUCCESSFUL_RESPONSE_CLASSES = [
Net::HTTPOK,
Net::HTTPRedirection
].freeze

attr_reader :url, :request_timeout

def initialize(url, request_timeout = DEFAULT_REQUEST_TIMEOUT)
super()
@url = url
@request_timeout = request_timeout
end

def check
response = perform_request

if successful_response?(response)
mark_message SUCCESS_MESSAGE
else
mark_failure
mark_message unexpected_status_message(response)
end
rescue StandardError => e
mark_message "Error: '#{e.message}'"
mark_failure
end

def perform_request
head_request
rescue Net::OpenTimeout, Net::ReadTimeout => e
raise ConnectionFailedError, "#{url} did not respond within #{request_timeout} seconds: #{e.message}"
rescue ArgumentError => e
raise ConnectionFailedError, "Invalid URL format for '#{url}': #{e.class}: #{e.message}"
rescue StandardError => e
raise ConnectionFailedError, e.message
end

private

def head_request
uri = parsed_uri

Net::HTTP.start(
uri.host,
uri.port,
use_ssl: uri.is_a?(URI::HTTPS),
verify_mode: OpenSSL::SSL::VERIFY_PEER,
open_timeout: request_timeout,
read_timeout: request_timeout
) do |http|
http.head(uri.request_uri)
end
end

def parsed_uri
URI.parse(url).tap do |uri|
raise ArgumentError, 'URL must include an HTTP or HTTPS scheme and host' unless http_uri?(uri)
end
end

def http_uri?(uri)
uri.is_a?(URI::HTTP) && uri.host
end

def successful_response?(response)
SUCCESSFUL_RESPONSE_CLASSES.any? { |klass| response.is_a?(klass) }
end

def unexpected_status_message(response)
"Error: '#{url}' http head check responded, but returned unexpected HTTP status: " \
"#{response.code} #{response.class}. Expected 200 Net::HTTPOK or a redirect."
end
end
end
42 changes: 42 additions & 0 deletions lib/geo_data_health_check/timed_health_check.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
require 'timeout'

module GeoDataHealthCheck
class TimedHealthCheck < OkComputer::Check
attr_reader :wrapped_check, :timeout

def initialize(wrapped_check, timeout:)
super()
@wrapped_check = wrapped_check
@timeout = timeout
end

def registrant_name=(name)
super
wrapped_check.registrant_name = name if wrapped_check.respond_to?(:registrant_name=)
end

def check
Timeout.timeout(timeout) do
wrapped_check.run
end

copy_wrapped_check_result
rescue Timeout::Error
fail_with_message "Health check timed out after #{timeout} seconds"
rescue StandardError => e
fail_with_message "Error: '#{e.message}'"
end

private

def copy_wrapped_check_result
mark_message wrapped_check.message
mark_failure unless wrapped_check.success?
end

def fail_with_message(message)
mark_failure
mark_message message
end
end
end
54 changes: 0 additions & 54 deletions lib/http_head_check.rb

This file was deleted.

3 changes: 2 additions & 1 deletion lib/templates/robots.txt.erb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Disallow: /catalog.rss
Disallow: /catalog*f[
Disallow: /catalog*f%5B
Disallow: /catalog/*/relations
Disallow: /catalog/*/track
Disallow: /catalog/facet/*
Disallow: /catalog/*/web_services
Disallow: /catalog/email
Expand Down Expand Up @@ -50,4 +51,4 @@ Disallow: /
User-agent: DataForSeoBot
Disallow: /

Sitemap: <%= @base_url %>/sitemap.xml.gz
Sitemap: <%= @base_url %>/sitemap.xml.gz
2 changes: 1 addition & 1 deletion spec/lib/http_head_check_spec.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
require 'rails_helper'
require_relative '../../lib/http_head_check'
require_relative '../../lib/geo_data_health_check'

RSpec.describe GeoDataHealthCheck::HttpHeadCheck do
let(:url) { 'https://example.com/endpoint' }
Expand Down
Loading
Loading