36 lines
1.5 KiB
Markdown
36 lines
1.5 KiB
Markdown
---
|
|
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:
|
|
|
|
{% highlight 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 $@
|
|
{% endhighlight %}
|