3

I am trying to create a health check page for my app. There are 3 different servers for back end, front end and database. I have created an API to check if services (sidekiq, redis) are running. Now, I want to check if postgres server is up or not. For this I have added a method

def database? ActiveRecord::Base.connection.active? end

This method returns true when postgres is running. If the Postgres server is stopped, and I try to hit my API I get

PG::ConnectionBad (could not connect to server: Connection refused Is the server running on host "localhost" (127.0.0.1) and accepting TCP/IP connections on port 5432? ):

How to rescue this error?

2
  • I don't think you can do that though the rails app since it tries to connect to the db first. You'll have to be on an app that has no db requirement which pings certain services such as db, redis, sidekiq. Redis, sidekiq you can easily do from the rails app but db, nope. Maybe someone know more :). Commented Feb 8, 2018 at 13:09
  • @razvans, Thanks. Could you please guide me what is the standard way to check db connections? Or can you elaborate more on app with no db requirement. Commented Feb 8, 2018 at 13:44

2 Answers 2

4

To prevent rails guts to be loaded before you actually check the DB connection, I would suggest to create a simple rack middleware, and put in the very beginning of middlewares stack:

class StatusMiddleware
  def initialize(app)
    @app = app
  end

  def call(env)
    return @app.call(env) unless status_request?(env)

    # Feel free to respond with JS here if needed
    if database_alive?
      [200, {}, []]
    else
      [503, {}, []]
    end
  end

  private

  def status_request?(env)
    # Change the route to whatever you like
    env['PATH_INFO'] == '/postgres_status' && env['REQUEST_METHOD'] == 'GET'
  end

  def database_alive?
    ::ActiveRecord::Base.connection.verify!
    true
  rescue StandardError
    false
  end
end

And in your config/application.rb:

config.middleware.insert_before 0, StatusMiddleware
Sign up to request clarification or add additional context in comments.

6 Comments

If Postgres server is not running, then the request doesn't reach to the controller, and PG::ConnectionBad error is thrown. So the rescue mentioned will not work.
@nattfodd But when you enter a "system health" page which eventually uses that method, won't it crash? It would.
you are right, I've changed the answer, check it out
@nattfodd. Yes! This is working properly. Will check for other services as well. Thank you!
@PrajaktaC don't forget to select the correct answer once you're done
|
0

I didn't do anything like it but here's how I'd do it.

Host a rails app (or sinatra, with no db or a dummy one) to status.myapp.com which is just a simple index page with a bunch of checks - db, redis, sidekiq. I'd make sure is hosted on the same machine as the production one.

  1. db - try to establish a connection to your production db - fails or not
  2. redis - try to see if it's a running process for redis-server
  3. sidekiq - try to see if it's a running process for sidekiq
  4. etc ...

Again, just an idea. Maybe someone did it differently.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.