sshaw/rack-downtime

View on GitHub
README.md

Summary

Maintainability
Test Coverage
# Rack::Downtime

Planned downtime management for Rack applications

[![Build Status](https://travis-ci.org/sshaw/rack-downtime.svg?branch=master)](https://travis-ci.org/sshaw/rack-dowmtime)
[![Code Climate](https://codeclimate.com/github/sshaw/rack-downtime/badges/gpa.svg)](https://codeclimate.com/github/sshaw/rack-downtime)

## Overview

`Rack::Dowtime` **does not** add a maintenance page -there are *plenty* of ways to do this already. Instead,
it provides one with a variety of simple ways to trigger and takedown planned maintenance notifications while a site
**is still up**.

### Examples

```ruby
require "rack/downtime"

use Rack::Downtime
```

In your layout:

```erb
<% if ENV.include?("rack.downtime") %>
  <div>
    <p>
      We will be down for maintenance on
      <%= ENV["rack.downtime"][0].strftime("%b %e") %> from
      <%= ENV["rack.downtime"][0].strftime("%l:%M %p") %> to
      <%= ENV["rack.downtime"][1].strftime("%l:%M %p") %> EST.
    </p>
  </div>
<% end %>
```

Now set the downtime using the `:file` strategy:

```
# 1 to 4 AM
> echo '2014-11-15T01:00/2014-11-15T04:00' > downtime.txt
```

If you prefer, `Rack::Downtime` can insert the message for you:

```ruby
# Inserts a downtime message
use Rack::Downtime, :insert => "my_template.erb"

# Specify where to insert message
use Rack::Downtime, :insert => "my_template.erb", :insert_at => "body #container"
```

The downtime can be set various ways:

```ruby
# From the HTTP header X-Downtime
use Rack::Downtime, :strategy => :header
use Rack::Downtime, :strategy => { :header => "X-MyHeader" }

# Or from the query string
use Rack::Downtime, :strategy => :query
use Rack::Downtime, :strategy => { :query => "dwn__" }
```

Alternate configuration:

```ruby
Rack::Downtime.strategy = :file
Rack::Downtime::Strategy::File.path = Rails.root.join("downtime.txt")
```

Control its behavior via environment variables:

```
SetEnv RACK_DOWNTIME 2014-11-15T01:00:00-05/2014-11-15T04:00:00-05

# Disable
SetEnv RACK_DOWNTIME_DISABLE 1

# Or, just turn of insertion
SetEnv RACK_DOWNTIME_INSERT  0
```

## Usage

Downtime can be retrieved from various locations via a [downtime strategy](#downtime-strategies). When downtime is detected,
it's turned into 2 instances of `DateTime` and added to the Rack environment at `rack.downtime`. The 0th
element is the start time and the 1st element is the end time.

The dates must be given as an [ISO 8601 time interval](https://en.wikipedia.org/wiki/ISO_8601#Time_intervals)
in `start/end` format. If no dates are found `rack.downtime` will not be set.

Downtime messages can also be added to the response's body. See *[Inserting a Downtime Message](#inserting-a-downtime-message)*.

### Downtime Strategies

Strategies are given via the `:strategy` option. If none is provided then `Rack::Downtime.strategy`
is used, which defaults to `:file`.

#### `:file`

Looks in the current directory for a file named `downtime.txt`. 

```ruby
use Rack::Downtime :strategy => :file
```

To use a file named `my_file.txt`:

```ruby
use Rack::Downtime :strategy => { :file => "my_file.txt" }
```

#### `:query`

Looks for a query string parameter named `__dt__`.

```ruby
use Rack::Downtime :strategy => :query
```

To use a query string named `q`:

```ruby
use Rack::Downtime :strategy => { :query => "q" }
```

#### `:header`

Looks for an HTTP header named `X-Downtime`.

```ruby
use Rack::Downtime :strategy => :header
```
To look for a header named `X-DT-4SHO`:

```ruby
use Rack::Downtime :strategy => { :header => "X-DT-4SHO" }
```

Internally the header will be converted to match
[what rack generates](http://www.rubydoc.info/github/rack/rack/master/file/SPEC#The_Environment), e.g., `HTTP_*`.

#### `:env`

Looks for an environment variable named `RACK_DOWNTIME`.

#### `:cookie`

Looks for cookie named `__dt__`.

```ruby
use Rack::Downtime :strategy => :cookie
```
To use a cookie named `oreo`:

```ruby
use Rack::Downtime :strategy => { :cookie => "oreo" }
```

#### Custom

Just pass in something that responds to `:call`, accepts a rack environment, and returns a [downtime array](#usage).

```ruby
use Rack::Downtime :strategy => ->(env) { YourDownTimeConfig.find_dowmtime }
```

### Inserting a Downtime Message

A message can be inserted by `Rack::Downtime` into your response's body whenever downtime is scheduled.
Just provide a path to an ERB template to the `:insert` option. The downtime will be passed to the template
as `start_time` and `end_time`.

By default the template will be inserted after the `body` tag. This can be changed by providing the
desired location to the `:insert_at` option. The location can be given as a CSS selector or an XPath location.

Messages are only inserted into HTML responses with a `200` status code.

**Note that when `Rack::Downtime` inserts a message it will turn a streaming response into a buffered one**.
If this is a problem you can always check for and insert the downtime yourself in your application.

## TODO

Don't invalidate XHTML responses when inserting a downtime message.

## Author

Skye Shaw [sshaw AT gmail.com]