diff --git a/_posts/2018-01-23-pg_isready.md b/_posts/2018-01-23-pg_isready.md new file mode 100644 index 0000000..f96ee05 --- /dev/null +++ b/_posts/2018-01-23-pg_isready.md @@ -0,0 +1,35 @@ +--- +layout: post +title: "Using pg_isready to optimize test runs" +slug: pg_isready +date: 2018-01-23 13:00:00 +0000 +categories: postgresql bash +--- + +While working with Docker Compose to set up a containerized RSpec testing environment today, I ran into a problem. + +RSpec, running in one container, was intermittently trying to access the PostgreSQL database, located in a second container, before it had finished booting. Naturally, this was causing sporadic connection errors and test failures. + +The testing environment was distributed, with many discrete Docker Compose applications running in parallel. And PostgreSQL's launch time varied considerably, sometimes being under a couple of seconds, but occasionally taking ten seconds or more. + +This meant that naively setting a timeout (`sleep 5 && bundle exec rspec`...) was an unsatisfactory approach. It would have increased the run time of every test environment, but without completely solving the problem. + +While researching the most appropriate solution, I discovered a useful tool. [`pg_isready`](https://www.postgresql.org/docs/9.3/static/app-pg-isready.html) allows a PostgreSQL database's status to be queried quickly and simply from a script or the command line. + +Once I'd found it, using it in the RSpec container's entrypoint script was simple: + +```bash +#!/bin/bash + +set -e +echo "Launching Rails $RAILS_ENV environment with target: $@" + +until pg_isready -q -d my_database_name +do + echo "Waiting for database to be ready..." + sleep 1 +done + +bundle exec rake db:reset +bundle exec rspec $@ +```